如何在SVG中细分不规则多边形

时间:2015-07-09 21:51:52

标签: svg graphics computational-geometry

给定一个不确定形状的多边形,并且知道从哪个路径开始,我需要使用起始路径作为指导将这些多边形(以SVG格式定义)切割成n个形状。

这很难解释,但想想体育场内的座位部分及其行: sections cut into rows

在处理矩形时,它似乎并不太难。我所坚持的是如何使用不规则形状的多边形。一个通用的解决方案是最好的,特别是如果它可以使用曲线,但我可以看到这将只会使问题复杂化。

我是否应该开始学习任何特定的算法?我已经开始深入研究多边形三角剖分以及如何使用耳剪方法以单调的方式分解这些多边形,但是我的脑袋开始在这里旋转。

PS:不确定它是否超级重要,但这些多边形是在SVG中定义的。

1 个答案:

答案 0 :(得分:1)

这是一种非常天真的方法:根据您需要的分区/“行”,简单地在顶部和底部顶点之间进行插值(从左到右排序)。

我使用Processing进行了快速测试:

Set Rng = Sheet3.Range(Sheet3.Cells(1, i), Sheet3.Cells(1, j))

这是shape.svg:

PShape svg,shape;

int divisions = 3;

ArrayList<PVector> top = new ArrayList<PVector>();
ArrayList<PVector> bottom = new ArrayList<PVector>();

int numVerts;
int ptSize = 5;

void setup(){
  svg = loadShape("shape.svg");
  size((int)svg.width,(int)svg.height);
  shape = svg.getChild(0);
  //find top and bottom vertices
  numVerts = shape.getVertexCount();
  float minY = height,maxY = 0;
  for(int i = 0 ; i < numVerts; i++){
    PVector v = shape.getVertex(i);
    if(v.x < minY) minY = v.y;
    if(v.y > maxY) maxY = v.y;
  } 
  float yThresh = (maxY-minY) * .25;//1/4 of height as top/bottom thresh
  //store vertices belonging to top and bottom based on min and max y values and threshold
  for(int i = 0 ; i < numVerts; i++){
    PVector v = shape.getVertex(i);
    if(v.y <= minY+yThresh) top.add(v);
    if(v.y >= maxY-yThresh) bottom.add(v);
  }
  //manual left to right sorting, this needs to be implemented properly
  PVector last = bottom.get(bottom.size()-1);
  PVector first = bottom.get(0);
  bottom.set(0,last);
  bottom.set(bottom.size()-1,first);
  //assumptions is top is a list of the top vertices of the contour sorted left to right
  //and simillary bottom is a list of bottom vertices, sorted left to right
}

void draw(){
  background(255);
  shape(shape,0,0);
  //visualize top/bottom vertices
  stroke(0,192,0);
  for(PVector v : top) ellipse(v.x,v.y,ptSize,ptSize);
  stroke(192,0,0);
  for(PVector v : bottom) ellipse(v.x,v.y,ptSize,ptSize);
  stroke(0,0,255);

  //compute interpolation step value
  float lerpStep = 1.0/(divisions+1);

  //for each division
  for(int i = 0 ; i < divisions; i++){

    //loop through contour vertices top to bottom
    for(int j = 0 ; j < top.size(); j++){
      //get top and bottom vertices
      PVector vTop = top.get(j);
      PVector vBottom = bottom.get(j);
      //interpolate between them
      PVector vLerp = PVector.lerp(vTop,vBottom, lerpStep * (i+1));
      //draw on screen
      ellipse(vLerp.x,vLerp.y,ptSize,ptSize);
    }

  }
}

void keyPressed(){
  if(keyCode == UP) divisions++;
  if(keyCode == DOWN) divisions--;
}

这是一个预览,顶部顶点标记为绿色,底部红色和插值顶点标记为蓝色:

SVG vertex interpolation

正如@Joseph O'Rourke所提到的,如果底部和底部路径不相似(相同数量的顶点和从左到右的顺序,我猜),问题就更具挑战性。 在这种情况下,应该可以实现混合算法(例如this one)。如果您已经在使用SVG格式的各种形状,那么您应该能够测试混合是否可以通过事先在Inkscape或Illustrator中尝试来解决您的问题。