大道废

一切有为法,如梦幻泡影,如露亦如电,当作如是观.

0%

2018.05.28

至少在Chrome浏览器中,Cesium 的 Double_Click 事件触发之前会触发两次 Click 事件,所以并不推荐使用 Double_Click 事件来处理操作

2018.05.21

Geometry 不是地形的一部分,但 3DTileset 的 model 是

Geometry的缺省boundingsphere 是整个地球

Viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin) 添加后会造成

1
2
3
4
5
6
7
8
9
10
viewer.screenSpaceEventHandler.setInputAction((event) => {
let picked = viewer.scene.pick(event.endPosition);
if (picked !== prePicked) {
if (prePicked) prePicked.color = preStyle;
if (picked) {
prePicked = picked, preStyle = picked.color;
picked.color = Cesium.Color.YELLOW.withAlpha(0.5);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

这段代码出问题,它好像会改变 preStyle 的颜色

2018.05.14

https://cesium.com/blog/2018/05/01/cesium-version-1.45-released/

测试线段长度

1
2
3
4
5
6
7
8
9
10
11
12
let hierarchy = entity.polyline.positions._value;
hierarchy = Cesium.PolylinePipeline.generateArc({
positions: hierarchy,
});
let vector = new Cesium.Cartesian3();
let distance = 0;
for (let i = 3; i < hierarchy.length; i += 3) {
vector.x = hierarchy[i] - hierarchy[i - 3];
vector.y = hierarchy[i + 1] - hierarchy[i - 2];
vector.z = hierarchy[i + 2] - hierarchy[i - 1];
distance += Cesium.Cartesian3.magnitude(vector);
}

测试polygon的面积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Get the polygon from your "entity"
var polygon = theEntity.polygon;
var hierarchy = polygon.hierarchy._value;
// "indices" here defines an array, elements of which defines the indice of a vector
// defining one corner of a triangle. Add up the areas of those triangles to get
// an approximate area for the polygon
var indices = Cesium.PolygonPipeline.triangulate(hierarchy.positions, hierarchy.holes);
var area = 0; // In square kilometers
for (var i = 0; i < indices.length; i += 3) {
  var vector1 = hierarchy.positions[indices[i]];
  var vector2 = hierarchy.positions[indices[i+1]];
  var vector3 = hierarchy.positions[indices[i+2]];
  // These vectors define the sides of a parallelogram (double the size of the triangle)
  var vectorC = Cesium.Cartesian3.subtract(vector2, vector1, new Cesium.Cartesian3());
  var vectorD = Cesium.Cartesian3.subtract(vector3, vector1, new Cesium.Cartesian3());
  // Area of parallelogram is the cross product of the vectors defining its sides
  var areaVector = Cesium.Cartesian3.cross(vectorC, vectorD, new Cesium.Cartesian3());
  
  // Area of the triangle is just half the area of the parallelogram, add it to the sum.
  area += Cesium.Cartesian3.magnitude(areaVector)/2.0;
}

来自 https://groups.google.com/forum/#!topic/cesium-dev/EimmL-poCDI

3DTileset不是一次性加入全部tile,所以要定位到某个tile,必须在外部保存tile的某个属性和它的位置地址,把视角平移过去后,在3DTileset加载完成后。才可以通过 3DTileset.tileVisible 找到有这个属性的 feature 然后着色,或者通过 Cesium3DTileStyle 着色。

根据建筑物坐标与高度,定位并调整视角

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let long = -1.2917727072831369, lat = 0.7105749513910979, height = 547.7591871983744;
let heading = viewer.camera.heading, pitch = viewer.camera.pitch;

let position = viewer.scene.globe.ellipsoid.cartographicToCartesian(new Cesium.Cartographic(long, lat, 0.5 * height));
let offset = offsetFromHeadingPitchRange(heading, pitch, height * 2.0);
let transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
Cesium.Matrix4.multiplyByPoint(transform, offset, position);

function offsetFromHeadingPitchRange(heading, pitch, range) {
pitch = Cesium.Math.clamp(pitch, -Cesium.Math.PI_OVER_TWO, Cesium.Math.PI_OVER_TWO);
heading = Cesium.Math.zeroToTwoPi(heading) - Cesium.Math.PI_OVER_TWO;
var pitchQuat = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Y, -pitch);
var headingQuat = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, -heading);
var rotQuat = Cesium.Quaternion.multiply(headingQuat, pitchQuat, headingQuat);
var rotMatrix = Cesium.Matrix3.fromQuaternion(rotQuat);
var offset = Cesium.Cartesian3.clone(Cesium.Cartesian3.UNIT_X);
Cesium.Matrix3.multiplyByVector(rotMatrix, offset, offset);
Cesium.Cartesian3.negate(offset, offset);
Cesium.Cartesian3.multiplyByScalar(offset, range, offset);
return offset;
}

例子:
http://www.virtualcitysystems.de/en/

http://nrw.virtualcitymap.de/#/

http://www.3dcitydb.net/3dcitydb/fileadmin/3DWebClient/index.html

https://cesiumjs.org/demos/

http://cybercity3d.s3-website-us-east-1.amazonaws.com/?city=WashingtonDC

2018.05.08

设置Home的位置

1
2
Cesium.Camera.DEFAULT_VIEW_FACTOR = -0.3;
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = tileset._root._boundingVolume.rectangle;

Camera.lookAt 会锁住 camera 的视点,让鼠标不能移动 camera,需要 viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)

距离 3DTileset 1.5倍 boundingSpere.radius,
高度为 1.5 * distance / Math.tan(Cesium.Math.toRadians(70.0)),
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-20.0),
roll: 0.0,
时候,角度比较好

通过 Camera.pickEllipsoid 得到的坐标是 WGS84 坐标系下的,在有地形信息的情况下就会偏移,就算通过 sampleTerrianMostDetailed 转化过也一样

1
2
3
4
5
6
7
8
9
10
11
12
13
let coordinate = viewer.camera.pickEllipsoid(event.position, viewer.scene.globe.ellipsoid);
coordinate = Cesium.Cartographic.fromCartesian(coordinate);
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [coordinate]).then((samples) => {
for (let sample of samples) sample.height += 10.0;
viewer.entities.add({
position: Cesium.Cartographic.toCartesian(samples[0], viewer.scene.globe.ellipsoid),
point: {
pixelSize: 5,
color: Cesium.Color.GREEN,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
});

通过下面这个 Ray 相交得到的坐标是可以有地形高度的,取决于得到是有没有加载地形信息,如果有则有高度信息,没有就没有

1
2
3
4
5
6
7
8
9
10
let ray = viewer.camera.getPickRay(event.position);
let positon = viewer.scene.globe.pick(ray, viewer.scene);
viewer.entities.add({
position: positon,
point: {
pixelSize: 5,
color: Cesium.Color.LIME,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});

screenSpaceEventHandler.setInputAction 居然一个类型只可以有一个事件监听

得到两点方向的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//Add button to View Aircraft at a Fixed Angle relative to aircraft
Sandcastle.addToolbarButton('View Aircraft Fixed Angle', function () {
viewer.trackedEntity = undefined;
viewer.clock.onTick.addEventListener(function (clock) {

//get 2 positions close together timewise
var CC3 = Cesium.Cartesian3;
var position1 = entity.position.getValue(clock.currentTime, new CC3());
var position2 = entity.position.getValue(Cesium.JulianDate.addSeconds(clock.currentTime, 1 / 60, new Cesium.JulianDate()), new CC3());

//velocity in terms of Earth Fixed
var Wvelocity = CC3.subtract(position2, position1, new CC3());
CC3.normalize(Wvelocity, Wvelocity);
var Wup = new CC3(); var Weast = new CC3(); var Wnorth = new CC3();
Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(position1, Wup);
CC3.cross({ x: 0, y: 0, z: 1 }, Wup, Weast);
CC3.cross(Wup, Weast, Wnorth);

//velocity in terms of local ENU
var Lvelocity = new CC3();
Lvelocity.x = CC3.dot(Wvelocity, Weast);
Lvelocity.y = CC3.dot(Wvelocity, Wnorth);
Lvelocity.z = CC3.dot(Wvelocity, Wup);

//angle of travel
var Lup = new CC3(0, 0, 1); var Least = new CC3(1, 0, 0); var Lnorth = new CC3(0, 1, 0);
var x = CC3.dot(Lvelocity, Least);
var y = CC3.dot(Lvelocity, Lnorth);
var z = CC3.dot(Lvelocity, Lup);
var angle = Math.atan2(x, y);//math: y b4 x, heading: x b4 y
var pitch = Math.asin(z);//make sure Lvelocity is unitized

//angles offsets
angle += 0 / 180 * Math.PI;
pitch += -20 / 180 * Math.PI;

var range = 80;
var offset = new Cesium.HeadingPitchRange(angle, pitch, range);
viewer.scene.camera.lookAt(entity.position.getValue(clock.currentTime), offset);
}); //end event listener
}); //end button

orientation : new Cesium.VelocityOrientationProperty(position) 可以得到某点的方向,但 position 需要是 Cesium.SampledProperty 根据时间的采样属性

2018.05.07

Globe 上的 ClippingPlane 定一个法向量就可以了,distance是相对与 ClippingPlaneCollection 的 ModelMatrix 的,它是以笛卡尔坐标系的中心建立了一个穿过整个坐标系的平面组,所以会在地球表面形成两个相对的切面。

如何计算一个离某个点距离为 radius 的圆的坐标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let n = 180, points = [];
let center = tileset.boundingSphere.center, radius = tileset.boundingSphere.radius;
let R = viewer.scene.globe.ellipsoid.maximumRadius; //地球半径
center = Cesium.Cartographic.fromCartesian(center); //转成经纬度坐标
//latB = latA-((radius * Math.sin(Math.PI * i / n)) * 180) / (Math.PI * ellipsoid.R)
//latB = LatA-(Y*180)/(Math.PI * e)
//loB = loA - ((rdius * Math.cost(Math.PI * i / n)) * 180) / (Math.PI * ellipsoid.R * Math.cos((LatA + LatB) / 2))
//loB = loA - (x*180)/(math.pi * r * cost((latA + latB) / 2))
for (let i = -n; i <= n; i++) {
let x = Math.cos(Math.PI * i / n) * radius;
let y = Math.sin(Math.PI * i / n) * radius;
//let LatB = center.latitude - (y * 180) / (Math.PI * R);
let LatB = center.latitude - (y / R);
//let LonB = center.longitude - (x * 180) / (Math.PI * R * Math.cos((center.latitude + LatB) / 2));
let LonB = center.longitude - (x / (R * Math.cos((center.latitude + LatB) / 2)));
let point = new Cesium.Cartographic(LonB, LatB);
point = viewer.scene.globe.ellipsoid.cartographicToCartesian(point);
points.push(point);
}

这个是不精确的版本,在小范围误差可接受,参考自地理空间距离计算优化

Polyline 这个 Geometry 不支持 heightReference,于是不会自动贴地。必须通过 Cesium.sampleTerrainMostDetailed 这个方法吧 positions 中的点进行高度调整,其中 pointsR 为高度为零的 Cartographic 对象。

1
2
3
4
5
6
7
8
9
10
Cesium.when(Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, pointsR), (samples) => {
for (let sample of samples) sample.height += 10.0;
viewer.entities.add({
polyline: {
positions: Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(samples),
width: 5,
material: Cesium.Color.WHITE,
},
});
});

2018.05.03

不支持 KHR_materials_pbrSpecularGlossiness

Entity 保存了 Graphic
Graphic 保存 Geometry 对象的描述属性,但没有定义怎么画出这个对象

Billboard:

Billboard

  • @performance Reading a property, e.g., {@link Billboard#show}, is constant time.
  • Assigning to a property is constant time but results in
  • CPU to GPU traffic when {@link BillboardCollection#update} is called. The per-billboard traffic is
  • the same regardless of how many properties were updated. If most billboards in a collection need to be
  • updated, it may be more efficient to clear the collection with {@link BillboardCollection#removeAll}
  • and add new billboards instead of modifying each one.
    照这么说来,当 BillboardCollection.update 的时候才会处理成 GPU 的数据发送至 GPU

BillboradGraphics
BillboardGraphicsSpec

BillboardCollection
BillboardCollectionSpec

BillboardVisualizer
BillboardVisualizerSpec

BillboardCollectionFS.glsl
BillboardCollectionVS.glsl

createBillboardPointCallback

Entity 不指定方向的情况下用 eastNorthUpToFixedFrame

2018.04.27

Cesium 画geometry的效率
Billboard 》polyline > box = plane 》 polygon(不带挤压高度) > polygon(带挤压高度)

一万个 ellipse ellipsoid cylinder corrdior 会有内存不足的问题

画一个带指示线的标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var viewer = new Cesium.Viewer('cesiumContainer',
{timeline: false, animation: false});
var scene = viewer.scene;
var offsetX = 50, offsetY = -80;
var pos = Cesium.Cartesian3.fromDegrees(-75.1641667, 29.9522222);
var labels = scene.primitives.add(new Cesium.LabelCollection());
labels.add({
position: pos,
text: 'Another label',
pixelOffset: new Cesium.Cartesian2(offsetX, offsetY)
});
var canvas = document.createElement('canvas');
canvas.width = Math.abs(offsetX);
canvas.height = Math.abs(offsetY);
var context2D = canvas.getContext('2d');
context2D.beginPath();
context2D.lineWidth = 3;
context2D.strokeStyle = '#ffffff';
context2D.moveTo((offsetX < 0) ? -offsetX : 0, (offsetY < 0) ? -offsetY : 0);
context2D.lineTo((offsetX < 0) ? 0 : offsetX, (offsetY < 0) ? 0 : offsetY);
context2D.stroke();
var billboards = scene.primitives.add(new Cesium.BillboardCollection());
var billboard = billboards.add({
color : Cesium.Color.RED,
image : canvas,
pixelOffset: new Cesium.Cartesian2(offsetX * 0.5, offsetY * 0.5),
position : pos
});

https://stackoverflow.com/questions/32716118/cesium-js-how-draw-line-binding-a-label-to-a-position

2018.04.26

Primitive 对象有定点着色器与片元着色器的源代码入口

Viewer.scene.drillPick 返回的 pickedObjects 数组对象
pickedObject.id 为 entity
pickedObject.primitive 为相应的 primitive 对象

添加X,Y,Z三轴线

1
2
3
4
5
6
var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(position, hprRollZero, Cesium.Ellipsoid.WGS84, converter);
scene.primitives.add(new Cesium.DebugModelMatrixPrimitive({
modelMatrix : modelMatrix,
length : 300.0,
width : 10.0
}));

2018.04.24

Geometry画出来的图形是以地球坐标系来画的, Model是以模型自身的坐标系来画的,3DTileset是以地球坐标系来画的

3DTileset.debugWireframe可以显示骨架

2018.04.16

Cesium Pick有BUG,它是根据3DTiles的boundingSphere加上geometryError来确定模型占地面积,由maximumHeight的两倍来确定模型的高度。模型在这个范围内浮动,不会有明显的问题,超出这个范围就会有点选不中,显示异常的问题。

3DTileset的modelMatrix是整个set共用的,pickedFeature里的

题图

  • 两格:均匀度较好,粉细,用于爱乐压则下压压力比较大
  • 三、四格:均匀度尚可,手冲与爱乐压时水温要控制,不要太高
  • 五、六格:均匀度最差,不推荐用这个刻度
  • 七格:均匀度相对五有提升,颗粒合适法压,如果用于手冲,水温可高,合适户外、旅行等对温度比较不好控制的场合
  • 十格:颗粒过大,没可用性

这次贡嘎之行, 因某些意外加上老天配合, 于是晴天, 下雨, 冰雹, 下雪再加雨中夜路全都遇到了, 倒也是对装备全面的检测, 对我这个装备党来说, 苦逼是苦逼了一些, 但能看到自己找来的装备的好坏倒也是一种奇葩的乐趣.

苦逼营地晒装备

Read more »

类别 名称 重量
露营 田野睡袋 872
  therm-a-rest xlite 357
  AMK Bivvy (当地布) 101
  酱铺2人Cuben金字塔(风绳绑在帐篷上) 581
  钛地钉(17根,含地钉袋) 255
  充气垫气泵(兼柴火炉鼓风机) 58
  酱铺三明治(含两个腰包一个肩包) 1010
锅炉 柴火炉(兼酒精棉球炉, 含收纳袋) 147
  1.5升 铝锅(含锡箔锅盖,碳纤锅柄,收纳袋) 105
  钛筷与钛勺 35
  Flod-A-Cup 折叠水杯 50
  2升鸭嘴兽水袋 36
  1升鸭嘴兽水袋 36
  膳魔师FEK800 357
  MSR TrailShot 净水器 150
衣服 smartwood 袜子 68
  outdome羊毛袜子 60
  迪卡侬速干长裤 320
  天石羽绒裤 260
  三峰防雨裙 72
  迪卡侬羊毛T恤 165
  老鼠神衣 272
  始祖鸟冲锋衣 340
  HW羽绒服 340
  buff防风头巾 80
  迪卡侬防风手套 82
  羽绒脚套 152
  紧身抓绒内衣 250
  紧身抓绒裤 195
  内裤 88
电器 伏来阳太阳能板 207
  18650电池(3个) 141
  米勒 ML101 33
  斑马18650头灯(含一个18650电池) 114
  小米双头充电器 61
  苹果Lightning线 8
  garmin充电线 15
  microUSB线 19
  iphone6s 152
杂项 便便铲 16
  牙刷 牙膏 毛巾 90
  太阳镜 32
  buff太阳帽 30
  救生哨加打火棒 33
  garmin forunner 935 50
  酱铺粗苯收纳袋\*2 18
  三峰网袋(中号) 13
  三峰网袋(大号) 17
  雨伞 195
总计   7266

品类 名字 数量
衣服(数量包括身上) 速干长裤 1
速干短裤 2
速干内裤 3
袜子 3
皮肤风衣 1
迪卡侬雨衣 1
速干短袖 2
修理工具 撬胎棒 2
截链器 1
魔术扣 2
补胎片 6
内胎 2
外胎 2
集成工具 1
打气桶 1
链条油 1
日常用品 毛巾 1
牙刷牙膏 1
电器 充电头 1
相机 1
18650电池 4
米勒101 1
斑马手电 1
micro-usb线 2
苹果线 1
iwatch线 1
nokia黑白机 1
苹果6s 1

台北至新竹 81公里

台北-三峡-大溪老街-石门-关西-城隍庙-新竹

台3线-县道118

景点:新竹城隍庙

新竹至台中 100公里

新竹-竹南-后茏-通霄-苑里-大甲-清水-沙鹿-台中

台61线-台1线-台12线

景点:

​ 大甲镇澜宫

​ 台中彩虹村

​ 台中逢甲夜市

台中至嘉义 94.3公里

台中-彰化-员林-北斗-西螺-斗南-民雄-嘉义

台1线

景点:嘉义火鸡肉饭

嘉义至垦丁

备用路线:

去国圣灯塔

嘉义至台南 95.2公里

嘉义-国圣港灯塔-台南

台南至枋寮 86.5公里

台1

枋寮至垦丁 59.1公里

不去国圣灯塔

嘉义至高雄 115公里

嘉义-水上-新营-林凤营-隆田-善化-永康-台南-冈山-高雄

台1线

高雄至垦丁 104公里

高雄-小港-东港-佳冬-枋寮-枋山-枫港-车城-恒春-垦丁

台17线-台1线-台26线

垦丁至台东 153公里

备用路线:

  1. 垦丁至旭海 58公里 游玩路线
  2. 旭海至台东 100公里

台26-县200甲-县199-台9

台东至玉里 85公里

台东-初鹿-鹿野-关山-池上-富里-玉里

台9

景点:池上便当

玉里至花莲太鲁阁 113公里

玉里-瑞穗-富源-光复糖厂-凤林-丰田-志学-吉安-花莲-新城-太鲁阁

台9

景点:

​ 瑞穗北回归线

​ 麻糬

花莲至苏澳 82公里

台9

景点:

​ 苏澳冷泉

​ 苏澳羊羹

苏澳至九份 89.1公里

苏澳-三貂角灯塔-九份

​ 台2线

九份至台北 94.5公里

九份-富贵角灯塔-台北

台5线

大恕家坚果探险队

坚果探险队

传统波旁种,产区:韦韦特南,等级:SHB,海拔:1800-2000

中浅烘,可能的味道:坚果、榛果、核桃、红果酸甜

Read more »

大恕家愿望收纳箱

愿望收纳箱

苏门答腊亚齐水洗曼特宁

帝比卡种, 产地亚齐,海拔1550-1700,处理:水洗,中深烘

可能尝到的味道:松子香、太妃糖、桑葚

Read more »