简体   繁体   中英

Is there a way to find polygons in given points?

I'm currently working on a way to find rectangles/polygons in up to 15 given points (Image below).

Given Points

My goal is it to find polygons in that point array, like I marked in the image below. The polygons are rectangles in the real world but they are distorted a bit that's the reason why they can look like polygons or other shapes. I must find the best rectangle/polygon.

My idea was to check all connections between the points but the total amount of that is to big to run in and it took.

Does anyone has an idea how to solve that, I researched in the web and found the k-Nearest algorithm in sklearn for python but I don't have experience with that if this is the right way to solve it and how to do that. Maybe I'll also need a method to filter out some of the outliers to make it even easier for the algorithm to find the right corner points of the polygon.

The code snippet below splits the given point string into separate arrays, the array coordinatesOnly contains just the x and y values of the points.

Many thanks for you help.

Polygon in Given Points

import math
import numpy as np
import matplotlib.pyplot as plt
import time

from sklearn.neighbors import NearestNeighbors


millis = round(int(time.time())) / 1000

####input String
print("2D to 3D convert")

resultString = "0,487.50,399.46,176.84,99.99;1,485.93,423.43,-4.01,95.43;2,380.53,433.28,1.52,94.90;3,454.47,397.68,177.07,90.63;4,490.20,404.10,-6.17,89.90;5,623.56,430.52,-176.09,89.00;6,394.66,385.44,90.22,87.74;7,625.61,416.77,-177.95,87.02;8,597.21,591.66,-91.04,86.49;9,374.03,540.89,-11.20,85.77;10,600.51,552.91,178.29,85.52;11,605.29,530.78,-179.89,85.34;12,583.73,653.92,-82.39,84.42;13,483.56,449.58,-91.12,83.37;14,379.01,451.62,-6.21,81.51"


resultString = resultString.split(";")

resultStringSplitted = list()
coordinatesOnly = list()
for i in range(len(resultString)):
        resultStringSplitted .append(resultString[i].split(","))
        newList = ((float(resultString[i].split(",")[1]),float(resultString[i].split(",")[2])))
        coordinatesOnly.append(newList)
        for j in range(len(resultStringSplitted[i])):
                resultStringSplitted[i][j] = float(resultStringSplitted[i][j])

#Check if score is valid
validScoreList = list()
for i in range(len(resultStringSplitted)):
        if resultStringSplitted[i][len(resultStringSplitted[i])-1] != 0:
                validScoreList.append(resultStringSplitted[i])
resultStringSplitted = validScoreList

#Result String array contains all 2D results
# [Point Number, X Coordinate, Y Coordinate, Angle, Point Score]
for i in range(len(resultStringSplitted)):
        plt.scatter(resultStringSplitted[i][1],resultStringSplitted[i][2])

plt.show(block=True)

Since you mentioned that you can have a maximum of 15 points, I suggest to check all possible combinations of 4 points and keep all rectangles that are close enough to perfect rectangles. For 15 points, it is "only" 15*14*13*12=32760 potential rectangles.

import math
import itertools
import numpy as np

coordinatesOnly = ((0,0),(0,1),(1,0),(1,1),(2,0),(2,1),(1,3)) # Test data
rectangles = []

# Returns True if l0 and l1 are within 10% deviation
def isValid(l0, l1):
    if l0 == 0 or l1 == 0:
        return False
    return abs(max(l0,l1)/min(l0,l1) - 1) < 0.1

for p in itertools.combinations(np.array(coordinatesOnly),4):
    for r in itertools.permutations(p,4):
        l01 = np.linalg.norm(r[1]-r[0]) # Side
        l12 = np.linalg.norm(r[2]-r[1]) # Side
        l23 = np.linalg.norm(r[3]-r[2]) # Side
        l30 = np.linalg.norm(r[0]-r[3]) # Side
        l02 = np.linalg.norm(r[2]-r[0]) # Diagonal
        l13 = np.linalg.norm(r[2]-r[0]) # Diagonal
        areSidesEqual = isValid(l01,l23) and isValid(l12,l30)
        isDiag1Valid = isValid(math.sqrt(l01*l01+l30*l30),l13) # Pythagore
        isDiag2Valid = isValid(math.sqrt(l01*l01+l12*l12),l02) # Pythagore
        if areSidesEqual and isDiag1Valid and isDiag2Valid:
            rectangles.append(r)
            break

print(rectangles)

It takes about 1 second to run on 15 points on my computer. It really depends on what are your requirements for computation time, ie, real time, interactive time, "I just don't want to spend days waiting for the answer" time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM