【问题标题】:errors extruding shapes with three.js使用three.js 挤压形状时出错
【发布时间】: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中的挤压代码有问题?


例如,这里有一些缺失的县:

还要注意德克萨斯州缺失的三角形“沙漏”部分:这些看起来像一些只渲染了一半的县(它们最终变成三角形而不是矩形或正方形?)

Larger

为大量的代码转储道歉,我试图尽可能减少它。

设置:

/* 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


【解决方案1】:

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

【讨论】:

  • 实际上,事实证明,有一些背靠背的重复点(根据错误消息)——检查这一点并将它们扔掉似乎已经解决了大部分问题,如果不是全部的话。既然你让我找到了正确的答案,我会继续把它给你:)。
猜你喜欢
  • 2012-07-08
  • 1970-01-01
  • 2013-04-13
  • 2013-04-12
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多