13

# Вопрос по svg, algorithm – Площадь самопересекающегося многоугольника

Error: User Rate Limit Exceededsimple irregular многоугольникError: User Rate Limit ExceededError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

This question arose when investigating edge cases for my solution to Error: User Rate Limit Exceeded.

## Defining the Area

Error: User Rate Limit ExceedednotError: User Rate Limit Exceeded • Error: User Rate Limit Exceededsourceforge.net/projects/jsclipperError: User Rate Limit Exceeded

от
• Error: User Rate Limit Exceededcomputational geometry

от
• Error: User Rate Limit Exceeded

от Phrogz
• Error: User Rate Limit Exceeded

от
• Error: User Rate Limit Exceeded

от
• Error: User Rate Limit Exceeded

• Error: User Rate Limit Exceeded`0`Error: User Rate Limit Exceeded

• Error: User Rate Limit Exceeded

• Error: User Rate Limit Exceeded

от AnT
• Error: User Rate Limit Exceededthis solution might be an interesting starting point.

3 ответа
• 3

## Error: User Rate Limit Exceeded

First find convex hull of your polygon, for this you need to find convex hull of your polygon vertices. And compute convex hull area.

After that, find all intersection of your polygon.

• -2

## Error: User Rate Limit Exceeded

``````class SdPolygon(object):

def __init__(self, points=None):
points = self.parafloat(points)
self.points = points
self.current_points = []
self.sd_polygons = []
self.gene_polygon()

def parafloat(self, points):
"""
为保证准确，将所有的浮点数转化为整数
:return:
"""
para_point = [(int(x), int(y)) for x, y in points]
return para_point

def gene_polygon(self):
for point in self.points:
p0 = Polygon(self.current_points)
self.sd_polygons.append(p0)

"""
将该点加入到current_points 中，倒序遍历current_points中的点，如果能围成多边形，则将所围成的点弹出
:param point:
:return:
"""
if len(self.current_points) < 2:
self.current_points.append(point)
return
cross_point_dict = {}  # 记录线段与其他点的相交点，{0:P1,6:P2}
l0 = Line(Point(point, point), Point(self.current_points[-1], self.current_points[-1]))
for i in range(0, len(self.current_points) - 1):
line = Line(Point(self.current_points[i], self.current_points[i]),
Point(self.current_points[i + 1], self.current_points[i + 1]))
cross_point = self.get_cross_point(l0, line)  # 获取相交点
if self.is_in_two_segment(cross_point, l0, line):  # 如果相交点在两个线段上
cross_point_dict.update({i: cross_point})
flag_dict = {}  # 保存剪下点的信息
cross_points_list = sorted(cross_point_dict.items(), key=lambda item: item, reverse=True)  # [(3,P),(1,P)]
for cross_point_info in cross_points_list:
cross_i, cross_point = cross_point_info, cross_point_info
if flag_dict:  # 对应需要剪下多个多边形的情形，
points = self.current_points[cross_i + 1:flag_dict['index'] + 1]
points.append((flag_dict['point'].x, flag_dict['point'].y))
points.append((cross_point.x, cross_point.y))
p = Polygon(points)
self.sd_polygons.append(p)
else:
points = self.current_points[cross_i + 1:]
points.append((cross_point.x, cross_point.y))
p = Polygon(points)
self.sd_polygons.append(p)  # 将生成的polygon保存
flag_dict.update(index=cross_i, point=cross_point)
if flag_dict:
point_list = self.current_points[:flag_dict['index'] + 1]  # 还未围成多边形的数组
point_list.append((flag_dict['point'].x, flag_dict['point'].y))  # 加上交点
self.current_points = point_list
self.current_points.append(point)

def is_in_segment(self, point, point1, point2):
"""
交点是否在线段上
:param point:(x,y)
:param point1:[(x1,y1),(x2,y2)]
:param point2:
:return:
"""
if point1.x > point2.x:
minx = point2.x
maxx = point1.x
else:
minx = point1.x
maxx = point2.x
if point1.y > point2.y:
miny = point2.y
maxy = point1.y
else:
miny = point1.y
maxy = point2.y
if minx <= point.x <= maxx and miny <= point.y <= maxy:
return True
return False

def is_in_two_segment(self, point, l1, l2):
"""
点 是否在两段 线段中间
:param point:
:param l1:
:param l2:
:return:
"""

def is_same_point(p1, p2):
"""
判断点是否相同
:param p1:
:param p2:
:return:
"""
if abs(p1.x - p2.x) < 0.1 and abs(p1.y - p2.y) < 0.1:
return True
return False

if self.is_in_segment(point, l1.p1, l1.p2) and self.is_in_segment(point, l2.p1, l2.p2):
if (is_same_point(point, l1.p1) or is_same_point(point, l1.p2)) and (
is_same_point(point, l2.p1) or is_same_point(point, l2.p2)):
# 判断是否在两条线段的端点上
return False
return True
return False

def get_line_para(self, line):
"""
规整line
:param line:
:return:
"""
line.a = line.p1.y - line.p2.y
line.b = line.p2.x - line.p1.x
line.c = line.p1.x * line.p2.y - line.p2.x * line.p1.y

def get_cross_point(self, l1, l2):
"""
得到交点
:param l1: 直线Line
:param l2:
:return: 交点坐标Point
"""
self.get_line_para(l1)
self.get_line_para(l2)
d = l1.a * l2.b - l2.a * l1.b
p = Point()
if d == 0:
return p
p.x = ((l1.b * l2.c - l2.b * l1.c) // d)
p.y = ((l1.c * l2.a - l2.c * l1.a) // d)
return p
``````

• 7

## Error: User Rate Limit Exceeded

The Bentley-Ottmann Algorithm

Pseudo-Code: Bentley-Ottmann Algorithm

``````    Initialize event queue EQ = all segment endpoints;
Sort EQ by increasing x and y;
Initialize sweep line SL to be empty;
Initialize output intersection list IL to be empty;

While (EQ is nonempty) {
Let E = the next event from EQ;
If (E is a left endpoint) {
Let segE = E's segment;
Let segA = the segment Above segE in SL;
Let segB = the segment Below segE in SL;
If (I = Intersect( segE with segA) exists)
Insert I into EQ;
If (I = Intersect( segE with segB) exists)
Insert I into EQ;
}
Else If (E is a right endpoint) {
Let segE = E's segment;
Let segA = the segment Above segE in SL;
Let segB = the segment Below segE in SL;
Delete segE from SL;
If (I = Intersect( segA with segB) exists)
If (I is not in EQ already)
Insert I into EQ;
}
Else {  // E is an intersection event
Add E’s intersect point to the output list IL;
Let segE1 above segE2 be E's intersecting segments in SL;
Swap their positions so that segE2 is now above segE1;
Let segA = the segment above segE2 in SL;
Let segB = the segment below segE1 in SL;
If (I = Intersect(segE2 with segA) exists)
If (I is not in EQ already)
Insert I into EQ;
If (I = Intersect(segE1 with segB) exists)
If (I is not in EQ already)
Insert I into EQ;
}
remove E from EQ;
}
return IL;
}
``````