【问题标题】:java how to merge multiple rectangles into one polygonjava如何将多个矩形合并为一个多边形
【发布时间】:2017-07-22 22:57:58
【问题描述】:

我希望有人可以帮助我,因为我在工作中正在努力解决这部分任务。我故意没有详细说明工作任务的背景,以试图将注意力集中在问题上。我必须将矩形合并为一个多边形,如附图所示,但需要点列表,以便我可以将这些点写入多边形形状(DOM 对象)以用于 Swing Canvas,然后导出 SVG。

我知道每个矩形的原点,即。左上角的 x 和 y 坐标 (float x, float y) 以及每个 Rectangle 的 Width (float) 和 Height (float) 因此可以计算每个 Rectangle 的所有四个角的坐标,即。上、右、下、左 IE。 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

【问题讨论】:

  • 您是否可以使用内置 API 或某种学校作业?
  • 哪些内置 API?不,这不是学校作业——这是我必须完成的工作任务的一部分。为什么这个问题已经被否决了?!
  • 因为您是在要求人们给您答案,而不是尝试自己编写代码。
  • 您可以同时使用Areaadd 形状。假设您使用的是java.awt.Rectangle 之类的东西,那么您可以将它包装在Areaadd 中,将其包装到另一个代表最终状态的Area。你也可以看看java.awt.Rectangle,因为它也有很多add 方法
  • 我曾多次尝试自己编写代码,但我对我的解决方案不满意 - 它无法正常工作,我认为它不会成为解决方案的基础,因此我决定将其装箱并开始再次。我已经阅读了 Sedgewick 的算法,但这对我的任务来说似乎过于复杂。我希望至少能得到一些指向正确方向的指示。

标签: java algorithm svg geometry batik


【解决方案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());
    }

}

【讨论】:

  • 谢谢,您的代码在我的电子项目中运行良好
  • 谢谢。它拯救了我的一天。 ?
猜你喜欢
  • 2012-11-24
  • 2015-11-15
  • 2015-08-26
  • 2021-06-18
  • 2022-12-18
  • 1970-01-01
  • 2016-02-03
  • 1970-01-01
  • 2021-09-01
相关资源
最近更新 更多