2017-03-03 443 views
1

我希望有人能帮助我,因为我正在努力工作中的这一部分任务。我故意没有详细说明工作任务的上下文,以尝试将注意力集中在问题。我必须将矩形合并为一个单独的多边形,如附图所示,但需要列表中的点,以便我可以将它们写入Swing Canvas的多边形(DOM对象)中,然后输出SVG。java如何将多个矩形合并为一个多边形

enter image description here

我知道每个矩形即起源。左上方的x和y坐标(float x,float y)以及每个Rectangle的Width(float)和Height(float)都可以计算每个Rectangle的所有四个角的坐标,即。顶部,右侧,底部,左侧 即。 Top = Origin = x,y,Right = x + width,Bottom = x + width,y + height和Left = x,y + height

我有一个List<Rectangle> rectangles,想要一个算法将这个列表转换成一个单独的多边形(List<Points>)其中一个点表示每个点的坐标(x,y),如图中标有红色的“x”所示。

然后我将使用这个点列表来写出一个元素DOM最终以SVG方式打印网页,所以我的最终结果必须是点列表(即用于在SVG中构建多边形形状的x,y坐标)

我看过这个答案,它做了类似的事情,但不确定如果我可以将它应用于我的案例 - 也用Python编写而不是Java。

Merging multiple adjacent rectangles into one polygon

+1

您是否允许使用内置API或此类学校作业? – MadProgrammer

+0

哪些内置API?没有这不是一个学校的任务 - 这是我必须做的工作的一部分。为什么这个问题已经被拒绝了?! – robbie70

+0

因为你要求人们给你答案,而不是自己编码。 – UnknowableIneffable

回答

1

这里是一个解决方案,我的同事和我想出了。希望它可以帮助别人。

public class PolygonHelper { 

    public Polygon makePolygon(List<Rectangle> rectangles){ 
     List<Point> points = calcPoints(rectangles); 
     return new Polygon(points); 
    } 

    private List<Point> calcPoints(List<Rectangle> rectangles) { 
     List<Point> ret = new ArrayList<>(); 

     List<Float> yCoords = new ArrayList<>(getAllYCoords(rectangles)); 
     yCoords.sort(Comparator.naturalOrder()); 

     float previousLeftCoord = 0; 
     float previousRightCoord = 0; 

     for(float yCoord : yCoords) { 
      System.out.println("Considering yCoords "+ yCoord); 
      float minimumXLeftCoord = minXLeftCoord(yCoord, rectangles); 
      float maximumXRightCoord = maxXRightCoord(yCoord, rectangles); 
      System.out.println("min X: "+minimumXLeftCoord); 
      System.out.println("max X: "+maximumXRightCoord); 

      if(yCoord == yCoords.get(0)) { 
       ret.add(new Point(minimumXLeftCoord, yCoord)); 
       ret.add(new Point(maximumXRightCoord, yCoord)); 

      } else { 

       if(minimumXLeftCoord!=previousLeftCoord) { 
        ret.add(0, new Point(previousLeftCoord, yCoord)); 
        ret.add(0, new Point(minimumXLeftCoord, yCoord)); 
       } else { 
        ret.add(0, new Point(minimumXLeftCoord, yCoord)); 
       } 

       if(maximumXRightCoord!=previousRightCoord) { 
        ret.add(new Point(previousRightCoord, yCoord)); 
        ret.add(new Point(maximumXRightCoord, yCoord)); 
       } else { 
        ret.add(new Point(maximumXRightCoord, yCoord)); 
       } 

      } 

      previousLeftCoord = minimumXLeftCoord; 
      previousRightCoord = maximumXRightCoord; 
      System.out.println(ret); 
     } 

     return ret; 

    } 

    private Set<Float> getAllYCoords(List<Rectangle> rectangles) { 
     List<Float> allBottomYCoords = rectangles.stream().map(rectangle -> rectangle.getBottom().getY()).collect(Collectors.toList()); 
     List<Float> allTopYCoords = rectangles.stream().map(rectangle -> rectangle.getTop().getY()).collect(Collectors.toList()); 

     Set<Float> allCoords = new HashSet<>(); 
     allCoords.addAll(allTopYCoords); 
     allCoords.addAll(allBottomYCoords); 
     return allCoords; 
    } 

    private float minXLeftCoord(Float y, List<Rectangle> rectangles) { 
     return rectanglesAtY(y, rectangles).stream().map(rect -> rect.getLeft().getX()).min(Comparator.naturalOrder()).get(); 
    } 

    private float maxXRightCoord(Float y, List<Rectangle> rectangles) { 
     return rectanglesAtY(y, rectangles).stream().map(rect -> rect.getRight().getX()).max(Comparator.naturalOrder()).get(); 
    } 

    private List<Rectangle> rectanglesAtY(Float y, List<Rectangle> rectangles) { 
     List<Rectangle> rectsAtYExcBottomLines = rectsAtYExcBottomLines(y, rectangles); 

     if(rectsAtYExcBottomLines.size()>0) { 
      // there are rectangles that are not closing here, so ignore those that are closing. 
      return rectsAtYExcBottomLines; 
     } else { 
      // there are only rectangle bottom lines so we need to consider them. 
      return rectsAtYIncBottomLines(y, rectangles); 
     } 
    } 

    private List<Rectangle> rectsAtYExcBottomLines(Float y, List<Rectangle> rectangles) { 
     return rectangles.stream() 
       .filter(rect -> rect.getTop().getY()<=y && rect.getBottom().getY()>y).collect(Collectors.toList()); 
    } 

    private List<Rectangle> rectsAtYIncBottomLines(Float y, List<Rectangle> rectangles) { 
     return rectangles.stream() 
       .filter(rect -> rect.getTop().getY()<=y && rect.getBottom().getY()==y).collect(Collectors.toList()); 
    } 

}