我怎样才能制作正方形?

时间:2016-09-28 00:40:47

标签: javascript algorithm graphics box2d polygon

我试图生成随机的,凸的,非自相交的多边形 - 特别是四边形。

我得到了:

function randquad(){

          var bodyDef = new b2BodyDef,
              fixDef = new b2FixtureDef,
              x=0, y=0;

          fixDef.density = Math.random();
          fixDef.friction = Math.random();
          fixDef.restitution = Math.random()*0.3;

          bodyDef.type = b2Body.b2_dynamicBody;
          fixDef.shape = new b2PolygonShape;
          fixDef.shape.SetAsArray([
            new b2Vec2(x, y),
            new b2Vec2(x+=Math.random()*2, y+=Math.random()*2*(Math.random()<0.5?1:-1)),
            new b2Vec2(x+=Math.random()*2*(Math.random()<0.5?1:-1), y+=Math.random()*2),
            new b2Vec2(x-=Math.random()*2, y+=Math.random()*2*(Math.random()<0.5?1:-1))
          ]);
          bodyDef.position.x = Math.random() * 10;
          bodyDef.position.y = 0;
          world.CreateBody(bodyDef).CreateFixture(fixDef);
        }

我正在使用Box2D网络;然而,这个问题并不局限于它,或者javascript - 它是一个更广泛的数学问题。

我希望获得4分,按顺序,形成我正在寻找的形状。

根据我编写的代码,我经常得到理想的形状;但是,我仍然会得到自相交的形状。目前我并不太担心凸起的形状。

我需要这样的形状的原因是因为它们似乎是唯一一个网络喜欢的网站。

任何4点可以使非自相交的四边形对吗? 我应该最初生成4,并将它们分类成一个有效的序列吗? 什么是最好/最有效的方式来解决这个问题?

- 原始题目:随机四边形生成

2 个答案:

答案 0 :(得分:0)

你可以从这样一个事实开始:如果你取3个随机点,它们将总是形成一个凸的,不相交的三角形(假设这些点都是不同的)。然后你可以通过在最后一个边缘添加一个随机距离的第四个点,然后将它从三角形的中心推出一个随机数量来弹出其中一个边缘。

  • 通过生成3个随机点生成随机三角形开始:A,B,C
  • 选择介于0和1之间的随机数,并用它来计算C和A之间某一点的D点。
  • 通过平均A,B,C
  • 计算三角形的质心
  • 计算1到n之间的另一个随机数(比如2)
  • 计算从质心到D的向量(从D中减去质心),然后乘以第二个随机数,然后加回到质心。这将产生你的第四点。

我不确定你是否有任何美学要求(例如没有过分尖锐的形状),但你可以随意使用随机数生成来获得你喜欢的结果。例如,在第二步中,您可以选择介于0.2和0.8之间的随机数,因此这些点不会太靠近。您还可以在第四步中更改n的值。

另一个问题是缠绕。使用这种方法,一半四边形将具有顺时针绕组并且将是逆时针方向。如果您需要特定的绕组,您可以进行绕组测试(BC的点积与AB的法线的符号),如果它不是您想要的那样,那么只需在一个轴上反映所有点。

答案 1 :(得分:0)

如果从圆周边取出点,则所有顶点都将凸出。

知道了这一点,我们可以编程一个循环,以分支到一个不存在的圆圈,并产生一直产生凸起形状的角落。

angles=[];
for (var i = 4; i--;) angles.push(Math.random()*2*Math.PI);

现在需要对角度进行排序,因此在创建形状时,顺时针方向,它们按角度大小顺序选择。 这将阻止形状的点交叉/自交。

angles.sort()

现在,您可以使用三角函数cossin创建形状,这些函数会将角度转换为实际坐标。

polygon([
    vector(Math.cos(angles[0]), Math.sin(angles[0])),
    vector(Math.cos(angles[1]), Math.sin(angles[1])),
    vector(Math.cos(angles[2]), Math.sin(angles[2])),
    vector(Math.cos(angles[3]), Math.sin(angles[3]))
]);`