4

我刚刚开始使用three.js,并且在挤出一些二维形状时遇到了一些问题。

我有一个包含美国所有县的 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));
}
4

1 回答 1

6

看起来多边形的点顺序错误。

于 2012-11-18T17:57:15.420 回答