【发布时间】:2014-01-16 17:07:46
【问题描述】:
我刚刚开始使用 three.js,但在挤出一些 2d 形状时遇到了一些问题。
我有一个包含美国所有县的 GeoJSON 文件。我正在使用 d3.js 和 d3.geo.albersUSa() 投影将每个纬度/经度转换为 X/Y 坐标列表,以制作 THREE.Shape,然后我将对其进行拉伸和绘制。这似乎对大多数县都有效。
我看到的问题是,某些县的子集要么无法挤出,要么挤出不正确,并出现以下警告序列:
Warning, unable to triangulate polygon!
Duplicate point 653.4789181355854:204.0166729191409
Either infinite or no solutions!
Its finite solutions.
Either infinite or no solutions!
Too bad, no solutions.
我不确定我是否完全理解问题所在——据我所知,这些特殊形状并没有什么特别之处。是我做错了什么,还是three.js中的挤压代码有问题?
例如,这里有一些缺失的县:
还要注意德克萨斯州缺失的三角形“沙漏”部分:这些看起来像一些只渲染了一半的县(它们最终变成三角形而不是矩形或正方形?)
为大量的代码转储道歉,我试图尽可能减少它。
设置:
/* initialize the scene, camera, light, and background plane */
var Map = function(params) {
this.width = params.width;
this.height = params.height;
this.container = params.target || document.body;
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.renderer.setSize(this.width, this.height);
this.renderer.setClearColorHex(0x303030, 1.0);
this.container.appendChild(this.renderer.domElement);
this.camera = new THREE.PerspectiveCamera(45, this.width / this.height,
1, 10000);
this.scene = new THREE.Scene();
this.scene.add(this.camera);
this.camera.position.z = 550;
this.camera.position.x = 0;
this.camera.position.y = 550;
this.camera.lookAt(this.scene.position);
this.projection = d3.geo.albersUsa()
.scale(1000)
.translate([250, 0]);
var pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 800;
pointLight.position.y = 800;
pointLight.position.z = 800;
var plane = new THREE.Mesh(
new THREE.PlaneGeometry(10000, 10000, 10, 10),
new THREE.MeshLambertMaterial({color: 0xffffff})
);
plane.rotation.x = -Math.PI/2;
this.scene.add(pointLight);
this.scene.add(plane);
};
渲染:
/* given a GeoJSON Feature, return a list of Vector2s
* describing where to draw the feature, using the provided projection. */
function path(proj, feature) {
if (feature.geometry.type == 'Polygon') {
return polygonPath(proj, feature.geometry.coordinates);
} else if (feature.geometry.type == 'MultiPolygon') {
return multiPolygonPath(proj, feature.geometry.coordinates);
}
}
/* a GeoJSON Polygon is a set of 'rings'. The first ring is the shape of the polygon.
* each subsequent ring is a hole inside that polygon. */
function polygonPath(proj, rings) {
var list = [];
var cur = [];
$.each(rings, function(i, ring) {
cur = [];
$.each(ring, function(i, coord) {
var pts = proj(coord);
cur.push(new THREE.Vector2(pts[0], pts[1]));
});
list.push(cur);
});
return list;
}
/* a GeoJSON MultiPolgyon is just a series of Polygons. */
function multiPolygonPath(proj, polys) {
var list = [];
$.each(polys, function(i, poly) {
list.push(polygonPath(proj, poly));
});
return list;
}
/* for each feature, find it's X/Y Path, create shape(s) with the required holes,
* and extrude the shape */
function renderFeatures(proj, features, scene, isState) {
var color = 0x33ccff;
$.each(features, function(i, feature) {
var polygons = path(proj, feature);
if (feature.geometry.type != 'MultiPolygon') {
polygons = [polygons];
}
$.each(polygons, function(i, poly) {
var shape = new THREE.Shape(poly[0]);
if (poly.length > 1) {
shape.holes = poly.slice(1).map(function(item) { return new THREE.Shape(item); });
}
var geom = new THREE.ExtrudeGeometry(shape, { amount: 20, bevelEnabled: false });
var c = new THREE.Mesh(geom, new THREE.MeshLambertMaterial({color: color}) );
c.rotation.x = Math.PI/2;
c.translateX(-290);
c.translateZ(50);
c.translateY(5);
scene.add(c);
});
});
}
Map.prototype.renderCounties = function() {
$.getJSON('/data/us-counties.json', function(json) {
renderFeatures(this.projection, json.features, this.scene, false);
this.renderer.render(this.scene, this.camera);
}.bind(this));
}
【问题讨论】:
-
您必须为每条错误消息确定一个县并生成一个简单的示例。如果您在这些县的数据中没有发现任何错误,并且您认为它应该可以工作,那么您可以将该示例以错误报告的形式提交给 three.js 问题委员会。
-
你能分享你的json吗?我想用另一个三角测量库来测试它......
-
好的,你可以在这里找到县数据:github.com/ledbettj/us-map/tree/threejs/public/data
标签: javascript d3.js three.js