Java 二维点集的包装

Java 二维点集的包装,java,r,algorithm,Java,R,Algorithm,我有一个二维点的列表 例如: x=c(4,3,3,5,6,6,4) 及 y=c(5,3,1,0,1,3,5) 这些二维点的绘图如下所示 我想画一个点集的包装,如下所示: 请注意,边界(包装)与最近点之间的垂直距离为2个单位 注意:我有许多类似于上述点集的点集。我想对所有的场景都做同样的事情 我想要这个边界多边形。谁能告诉我怎么做 Janak,任何想法都值得赞赏。要实现这一点,您可以使用这个简单的算法。 首先,我们需要坐标的中心(红点) 这可以通过将所有x值相加,然后将结果除以它们的数量来完成

我有一个二维点的列表

例如:

x=c(4,3,3,5,6,6,4)

y=c(5,3,1,0,1,3,5)

这些二维点的绘图如下所示

我想画一个点集的包装,如下所示:

请注意,边界(包装)与最近点之间的垂直距离为2个单位

注意:我有许多类似于上述点集的点集。我想对所有的场景都做同样的事情

我想要这个边界多边形。谁能告诉我怎么做


Janak,任何想法都值得赞赏。

要实现这一点,您可以使用这个简单的算法。
首先,我们需要坐标的中心(红点)
这可以通过将所有x值相加,然后将结果除以它们的数量来完成,与y值相同。

下一步是计算包裹当前坐标和中心点的矩形。(别忘了在此处添加2个单位的偏移量)

我们将对所有坐标执行此操作

在这一点上,我们已经可以停止了。只需渲染所有这些矩形,然后在图片顶部绘制坐标,但让我们进一步改进一下。
我们实际上并不需要所有的矩形,我们想要的是一个多边形来包裹这些点。 该多边形由重角与其边(蓝点)的交点定义

请注意,我们只需要距离中心最远的边和交点。
我们现在可以通过连接共享一个公共坐标并且是“邻居”的点来连接这些蓝点


更新:

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

public class PolyWrapper {

    public static void main(String[] args){

        //your example coords:
        int[] x_coords = {4,3,3,5,6,6,4};
        int[] y_coords = {5,3,1,0,1,3,5};       

        //make sure the coordinates have the same length, else they won't match
        if(x_coords.length != y_coords.length){
            System.err.println("Bad parameters given. X and Y don't match!");
            System.exit(1);
        }

        //this will hold our points:
        ArrayList<Point2D> points = new ArrayList<>();
        for(int i = 0; i < x_coords.length; i++){
            Point2D p = new Point2D.Double(x_coords[i], y_coords[i]);
            points.add(p);
        }
        //lets get the center of all those points:
        final Point2D center = get_center(points);
        ArrayList<Rectangle2D> rectangles = new ArrayList<>();

        //now lets create those wrapping rectangles:
        for(Point2D p : points){
            Rectangle2D r = new Rectangle2D.Double();
            r.setFrameFromDiagonal(center, p);
            rectangles.add(r);
        }

        //now show the wrapping rectangles:
        for(Rectangle2D r : rectangles){
            System.out.println(r.toString());
        }


    }

    //this method returns the center of a list of points
    public static Point2D get_center(ArrayList<Point2D> points){
        double x = 0,y =0;
        for(Point2D p : points){
            x += p.getX();
            y += p.getY();
        }
        x = x / points.size();
        y = y / points.size();
        Point2D c = new Point2D.Double();
        c.setLocation(x, y);
        return c;
    }
}

附言: 我试图从这一点改进算法,但遇到了一个似乎很难解决的问题——也许我会开始一个关于这个问题的新问题

(这是关于带有蓝色圆点的图片。一旦你有了矩形的所有点和它们的交点,你就很难找出结果中的哪些点是多边形所必需的)。我想我已经接近解决方案了,所以请注意我的下一次编辑。

使用Java,这变得非常简单。程序通过绘图来演示结果。也可以通过迭代
区域来获得轮廓。getPathIterator(at)
,它将逐个返回所有点

import java.awt.*;
import java.awt.geom.*;
import java.util.*;

public class PointSet {
public static final int W = 2;
Area area = new Area();

public void add( double x, double y ){
    area.add( new Area( new Rectangle2D.Double( x-W, y-W,2*W, 2*W ) ) );
}
public void plot(){
    Board board = new Board();
    board.go( area );
}
public static void main( String[] args ){
    PointSet ps = new PointSet();
    ps.add( 4, 5);
    ps.add( 3, 3);
    ps.add( 3, 1);
    ps.add( 5, 0);
    ps.add( 6, 1);
    ps.add( 6, 3);
    ps.plot();
}
}
以及:


点坐标可以是任意浮点值吗?是否保证结果将是一个单一的连贯多边形,没有“洞”?@laune..很抱歉回复晚了。对于您提出的两个问题,答案都是肯定的(点坐标是任意浮点和无孔的单个相干多边形)。谢谢你的关注。我还是不太明白你在问什么。你是在要求一种算法来从点集生成边界,还是将点从给定边界移开?我在尝试-这可能有漏洞。计算正方形集,其角点集为C。计算所有相交矩形,其角点集为R。显然,多边形的点必须是U(C,R)的子集要构建路径,请从具有最大y坐标的正方形开始。垂直边可能相交,也可能不相交:如果相交,则找到最近的交点和导致相交的正方形;如果没有,在拐角处转弯,然后沿着那一侧行驶。继续,直到到达第一个正方形。可能需要注意浮点坐标。通过缩放(*1000000)转换为long并返回可能是一种选择。感谢Tim为解决我的问题所做的巨大努力。我期待着JAVA代码的解决方案,但不着急,你可以在有时间的时候做。祝你考试顺利。你能检查一下我是否正确使用了你的JAVA代码吗。假设点为(1,2);(2,5)和(3,2),然后中心是(3,3)。但是在这里,使用你的参数可能无法找到上述类型的边界。嘿,janak,很抱歉,我的代码还没有完成,我得到了所有的矩形,并将尽快消除这些额外的点。我希望今晚能完成。这些点的中心是(2,3),上面点(2,5)的边界是一个特例,我在写这个算法时也遇到了这个问题。解决方案是添加您描述的2个单位的边距,以便找到一个环绕矩形。这个矩形的宽度是2*margin(我真的希望我把你的问题答对了,但是我现在有点赶时间)。它运行良好,我理解你提到的问题。期待您对解决此问题的代码进行下一次编辑。@TimHallyburton您的方法中存在一个重大缺陷。可以有一组点来创建一组重叠的正方形,从而形成一个形状,该形状可以通过围绕正方形和“红色中心”的矩形的构造来放大。即使是简单集(0,0);(2,2);(4,4);(6,6); 足够了,因为两端的两个方块都被放大,包括(3,3)“红色中心”。谢谢劳恩。我非常感谢你的努力。我很快就会告诉你结果。嗨,劳恩,我试着运行你的代码,但它出现了错误,我无法解决。你能检查一下吗?你犯了什么错误?你有什么改变吗它在我的系统JDK1.8上运行得很干净,但也应该在1.7或1.6中运行。程序的第一部分显示的错误是:线程“main”java.lang中出现异常。错误:未解决的编译问题:在第1天.PointSet.main(PointSet.java:14)您插入了导入-那么这是哪一行,看起来如何。这是一个编译问题——很可能是输入错误。
import java.awt.*;
import java.awt.geom.*;
import java.util.*;

public class PointSet {
public static final int W = 2;
Area area = new Area();

public void add( double x, double y ){
    area.add( new Area( new Rectangle2D.Double( x-W, y-W,2*W, 2*W ) ) );
}
public void plot(){
    Board board = new Board();
    board.go( area );
}
public static void main( String[] args ){
    PointSet ps = new PointSet();
    ps.add( 4, 5);
    ps.add( 3, 3);
    ps.add( 3, 1);
    ps.add( 5, 0);
    ps.add( 6, 1);
    ps.add( 6, 3);
    ps.plot();
}
}
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.*;
public class Board extends JPanel {
Area area;
void go( Area area ) {
    this.area = area;
    JFrame frame = new JFrame("Circle Test");
    frame.getContentPane().add(this);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    repaint();
    frame.setPreferredSize(new Dimension(800,800));
    frame.pack();
    frame.setVisible(true);
}

public void paintComponent(Graphics g) {
  AffineTransform at = new AffineTransform();
  at.translate( 100, 100 );
  at.scale( 50, 50 );
  PathIterator pit = area.getPathIterator( at );
  Path2D path = new Path2D.Double();
  path.append( pit, true );
  Graphics2D g2d = (Graphics2D)g;
  g2d.draw( path );
}
}