【问题标题】:Algorithm to pick one Polygon which is selected from a User从用户中选择一个多边形的算法
【发布时间】:2020-05-23 16:46:57
【问题描述】:

我无法找到合适的算法来检测用户是否选择了多边形。 这是我的例子:

  • 如果用户单击多边形之一,则选择一个。
  • 如果用户单击多边形二,则选择二。
  • 如果用户单击多边形 3 的左侧(我不确定对此的最佳直观反应是什么,所以实际什么都没有发生)
  • 如果用户点击多边形右侧的三三被选中。
  • 用户点击五或四五或四将被选中。

这是我对要求的实现:

// polygons - a List which contains all Polygons from a scene
Point position = input.getMouse();
List<ChangeablePolygon> selectedPolygons = new ArrayList<>();
for (ChangeablePolygon polygon : polygons) {
    polygon.setSelected(false);
    if (polygon.intersects(position))
        selectedPolygons.add(polygon);
}

if (selectedPolygons.size() == 1) {
    selectedPolygons.get(0).setSelected(true);
} else if (selectedPolygons.size() == 2) {
    ChangeablePolygon one = selectedPolygons.get(0);
    ChangeablePolygon two = selectedPolygons.get(1);
    if (Maths.isPolygonInPolygon(one, two)) {
        two.setSelected(true);
    } else if (Maths.isPolygonInPolygon(two, one)) {
        one.setSelected(true);
    } else if (one.getArea() < two.getArea()) {
        two.setSelected(true);
    } else {
        one.setSelected(true);
    }
}

/**
 * Polygon#intersects(Point):boolean
 *
 * true - if the Point is in the Polygon
 * false - otherwise 
 *
 * Polygon#getArea():double 
 * Returns the size auf the area from the Polygon 
 *
 * Maths#isPolygonInPolygon(Polygon polygon,Polygon inside):boolean
 *
 * true - if all Points from Polygon 'inside' are inside the Polygon 'Polygon'
 * false - otherwise
 */

但不幸的是,它在这个测试用例上失败了。因为如果选择了一个多边形,我选择了三个多边形,我的算法无法处理这种情况。

当然,我可以简单地将我的“两个”场景扩展为这样的:

ChangeablePolygon one = selectedPolygons.get(0);
ChangeablePolygon two = selectedPolygons.get(1);
ChangeablePolygon three = selectedPolygons.get(2);

if (Maths.isPolygonInPolygon(one, two) && Maths.isPolygonInPolygon(two, three)) {
    three.setSelected(true);
} else if (Maths.isPolygonInPolygon(two, one)) {
    one.setSelected(true);
} else if (Maths.isPolygonInPolygon(one, two)) {
    two.setSelected(true);
}

但必须有更好的解决方案。我正在寻找某种循环,如何在不为每个多边形数量添加 if-else-case 的情况下处理更多“堆叠”多边形。我没有想出有用的东西。

我应该提到我使用的引擎没有填充。不幸的是,我不能使用图形解决方案。有没有一种可能的唯一数学方法来计算这个?效率不那么重要。这是直接来自引擎的未经编辑的图像

【问题讨论】:

    标签: java algorithm 2d polygon intersection


    【解决方案1】:

    其中一种方法是按照与绘制它们相反的顺序对多边形进行排序,然后在给定位置选择第一个。

    例如,您按 4、2、3、1 的顺序绘制多边形;您按顺序对它们进行排序:1、3、2、4

    然后遍历多边形,只有直到你发现任何多边形包含给定的位置。

    伪代码:

    Polygon getSelectedPolygon(mousePosition) {
        List polygons = ...
        sortInRenderingOrder(polygons)
        reverse(polygons)
        polygon selectedPolygon = NULL
        for(Polygon polygon : polygons) {
            if(polygon.intersects(mousePosition)) {
              selectedPolygon = polygon
              break
            }
        }
        return selectedPolygon // returns NULL if nothing was selected
    }
    

    另一种方法可能是渲染方法:您希望将多边形绘制到颜色与其 id 相同的图像中。

    伪代码:

    int getSelectedPolygonID(mousePosition) {
        List polygons = ...
        sortInRenderingOrder(polygons)
        image tempImage = new image(WIDTH, HEIGHT)
        tempImage.fillWith(0)
        for(Polygon polygon : polygons) {
            polygon.renderOn(tempImage)
        }
        pixelColor = tempImage.getPixelColorAt(mousePosition)
        return pixelColor // returns 0 if nothing got selected
    }
    

    编辑: 如 cmets 中所述,如果您希望多边形 A 完全在另一个多边形 B 内,这意味着 A 的大小必须小于 B 的大小。 然后你可以像这样选择你的多边形: 伪代码:

    Polygon getSelectedPolygon(mousePosition) {
        List polygons = ...
        Polygon result = NULL
        resultSize = Infinity
        for(Polygon polygon : polygons) {
            if(polygon.intersects(mousePosition) && polygon.size() < resultSize) {
              result = polygon
              resultSize = polygon.size()
            }
        }
        return result // returns NULL if nothing was selected
    }
    

    【讨论】:

    • 这是一个很好的方法,但不幸的是我不能使用它。我已将图像调整为彩色图像,并且它们不会按顺序呈现。我将信息添加到原始帖子中。您知道其他方法吗?
    • 如果重叠,如何定义应该选择哪个多边形?
    • 我想选择多边形如何在另一个多边形内。当所有点/角都在另一个多边形内时,我的内部就被定义了。出于我的目的,我可以忽略连接点的线从另一个多边形切割线的情况。对于第一张图片中 P2 和 P3 的情况,我想我会选择面积较小的,但这是另一回事。
    • 澄清一下:如果您单击完全位于多边形 B 内的多边形 A,则应选择多边形 A。但是如果你有多边形 C 和 D,它们是重叠的,你点击它们的交点可以选择任何?
    • 我认为这对这个主题没有影响。但我目前在 C 和 D 的情况下选择面积较小的那个。但如果它们的大小完全相同,那么我会任意选择 D。我为重叠案例添加代码。
    【解决方案2】:

    一种方法是为每个多边形选择一个权重。 就像在您的第一张图片中一样,多边形 2 的分数是最不可见的(位于 exreme 后面的那个),其权重最低。

    当有MousePressEvent 时,您必须选择权重最高的多边形并选择该多边形。

    理想情况下,我会使用 [0,1] 范围内的权重。具有最低值的层,反之亦然。

    所以给定的代码是这样的:

    Point position = input.getMouse();
    
    Polygon selected = new ChangeablePolygon();
    selected.setWeight(0);// set the weight of this new polygon to be 0
    for (ChangeablePolygon polygon : polygons) {
    
         polygon.setSelected(false);
    
         if (polygon.intersects(position)){
             if(polygon.getWeight()>=selected.getWeight())
            {
                 selected.setSelected(false);
                 selected = polygon;
                 polygon.setSelected(true);
            }  
       }
    
    
         }
    }
    

    所需的 polgon 将存储在 selected 中,并且该多边形也将在 getSelected() 中返回 true

    【讨论】:

    • 如果我已经计算了多边形,这是一个优化选择的好主意。但是如何计算重量呢?我如何确定哪个是最靠后的?
    • 这取决于您如何创建多边形。如果用户创建它们,那么要创建的第一个多边形应该被赋予最低的权重,下一个应该被赋予更大的权重。没有必要将权重放在 0 和 1 之间。但是如果您以编程方式创建它们,则可以在创建循环中添加一个计数器,该计数器在每次成功创建后都会增加。
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 2022-06-22
    • 2010-09-17
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多