【问题标题】:Rotate discrete Points in Java without conflicts在Java中旋转离散点而不会发生冲突
【发布时间】:2016-08-26 20:02:56
【问题描述】:

我正在使用 GenerateSolidThetaZero 函数生成仅具有整数分量的点列表。我的目标是使用以弧度为单位的角度 theta 旋转这些离散点,并且旋转后的新点仍应具有整数分量。问题是我不希望任何两个点映射到相同的值。我想要旋转前后相同数量的独特点。我使用 round 函数稍微解决了这个问题,但我仍然会得到一些非唯一的映射。基本上我只是想找到一种方法来旋转这些点并尽可能多地保留结构(尽可能少地丢失点)。我愿意使用任何图书馆。任何帮助或指导都会很棒。

注意:在我的代码中,半径为 2,生成了 13 个点。在 Pi/6 旋转后,由于这些点映射到另一个点已经映射到的相同值,我最终损失了 4 个点。

    public class pointcheck{
        // this HashSet will be used to check if a point is already in the rotated list
        public static HashSet<Point> pointSet = new HashSet<Point>();

        public static void main(String args[]) {
            //generates sort of circular solid with param being the radius
            ArrayList<Point> solid_pointList =  GenerateSolidThetaZero(2);

            //used to store original point as first part of pair and rotated point as second part of pair
            ArrayList<Pair> point_pair = new ArrayList<Pair>();

            //goes through all points in Solid_pointList adds each point to Point List with its corresponding rotated angle
            for(Point t : solid_pointList){
                point_pair.add(new Pair(t,rotation_about_origin(t,Math.PI / 6)));
            }

            for(Pair t : point_pair){
                System.out.println(t.getFirst() + "   " + t.getSecond());
            }

            System.out.println(pointSet.size());

        }

        //takes the point we want to rotate and then the angle to rotate it by
        public static Point rotation_about_origin(Point P, double theta){
            Point new_P = null;
            double old_X = P.x;
            double old_Y = P.y;
            double cos_theta = Math.cos(theta);
            double sin_theta = Math.sin(theta);
            double new_X = old_X * cos_theta - old_Y * sin_theta;
            double new_Y = old_X * sin_theta + old_Y * cos_theta;

            new_P = new Point((int)Math.round(new_X),(int)Math.round(new_Y));

            //if new_p is already in rotated solid
            if(pointSet.contains(new_P))
                System.out.println("Conflict       " + P + "          " + new_P);
            else
                //add new_P to pointSet so we know a point already rotated to that spot
                pointSet.add(new_P);
            return new_P;
        }


        private static ArrayList<Point> GenerateSolidThetaZero(int r){
            int rsq = r * r;
            ArrayList<Point> solidList=new ArrayList<Point>();
            for (int x=-r;x<=r;x++)
                for (int y=-r;y<=r;y++)
                    if (x*x + y*y <= rsq)
                        solidList.add(new Point(x,y));

            return solidList;
        }

    public static class Pair<F,S>{
        private F first; //first member of pair
        private S second; //second member of pair

        public Pair(F first, S second) {
            this.first = first;
            this.second = second;
        }

        public void setFirst(F first) {
            this.first = first;
        }

        public void setSecond(S second) {
            this.second = second;
        }

        public F getFirst() {
            return first;
        }

        public S getSecond() {
            return second;
        }
      }
    }//end of pointcheck class

如何使用不使用 90 整数倍的角度旋转点?如果已经进行了映射,我应该在旋转后将点平移到哪里?

【问题讨论】:

  • 只要使用90°的任意整数倍作为旋转角度即可。
  • 是的,我想我只会局限于这些角度。
  • 所以?这里有什么具体问题吗?
  • 如何使用不使用 90 整数倍的角度旋转点?如果已经进行了映射,我应该在旋转后将点平移到哪里?
  • 您能添加更多上下文吗?你需要这个做什么?您可以将重叠点移动到未占用的单元格。但是由于磁盘是旋转不变的,如果处理得当,这将再次产生同一个磁盘。

标签: java math rotation point


【解决方案1】:

旋转后的磁盘将覆盖与原始磁盘完全相同的像素。因此,您实际上想要解决从原始像素到旋转像素的分配问题。

将原始像素(ox, oy) 分配给相应像素(cx, cy) 的成本可以用势能来表示。比如距离:

E_o,c = length(R(ox, oy, theta) - (cx, cy))

,其中R 是旋转运算符。或者,您也可以尝试其他规范,例如二次距离。

然后,问题是找到最小化总能量的对应关系:

min_C Sum_{o \in O} E_o,c

正好解决这个问题的算法是Hungarian Algorithm。但是,如果您有大量像素,它会非常昂贵。

相反,这是一个近似的想法:

在目标像素中,不仅有颜色,还存储旋转位置。然后,像以前一样依次旋转原始像素。对旋转后的位置进行四舍五入,并检查相应的像素是否仍被占用。

如果不是,则将旋转(未圆角)位置与新颜色一起存储。

如果它被占用,检查如果你交换对应关系,能量是否会减少。如果是这样,请交换它们,这样您就可以使用前一个像素。无论如何,您都有一个未映射的原始像素。将此像素存储在列表中。

在这个过程之后,你有一个部分对应的地图和一个未映射的像素列表。选择任何未映射的像素。分析目标像素的邻居。可能总会有一个未被占用的像素(尽管我没有证据)。如果是这样,请选择这个。如果不是,请检查所有相邻像素以获得最佳能量减少和交换。继续,直到列表为空。

近似算法只是一个想法,我没有证据证明它确实有效。但听起来好像值得一试。而且肯定会比匈牙利算法快。不过,这种近似仅适用于潜在定义中 p>=1 的 Lp 范数。

【讨论】:

    猜你喜欢
    • 2011-12-03
    • 2017-03-15
    • 2014-02-02
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多