summaryrefslogtreecommitdiff
path: root/lib/stitches/LineStringSampling.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stitches/LineStringSampling.py')
-rw-r--r--lib/stitches/LineStringSampling.py446
1 files changed, 245 insertions, 201 deletions
diff --git a/lib/stitches/LineStringSampling.py b/lib/stitches/LineStringSampling.py
index 434c6bbf..07106515 100644
--- a/lib/stitches/LineStringSampling.py
+++ b/lib/stitches/LineStringSampling.py
@@ -1,4 +1,3 @@
-from sys import path
from shapely.geometry.polygon import LineString
from shapely.geometry import Point
from shapely.ops import substring
@@ -8,33 +7,41 @@ from enum import IntEnum
from ..stitches import constants
from ..stitches import PointTransfer
-#Used to tag the origin of a rastered point
+# Used to tag the origin of a rastered point
+
+
class PointSource(IntEnum):
- #MUST_USE = 0 # Legacy
+ # MUST_USE = 0 # Legacy
REGULAR_SPACING = 1 # introduced to not exceed maximal stichting distance
- #INITIAL_RASTERING = 2 #Legacy
- EDGE_NEEDED = 3 # point which must be stitched to avoid to large deviations to the desired path
- #NOT_NEEDED = 4 #Legacy
- #ALREADY_TRANSFERRED = 5 #Legacy
- #ADDITIONAL_TRACKING_POINT_NOT_NEEDED = 6 #Legacy
- #EDGE_RASTERING_ALLOWED = 7 #Legacy
- #EDGE_PREVIOUSLY_SHIFTED = 8 #Legacy
- ENTER_LEAVING_POINT = 9 #Whether this point is used to enter or leave a child
- SOFT_EDGE_INTERNAL = 10 #If the angle at a point is <= constants.limiting_angle this point is marked as SOFT_EDGE
- HARD_EDGE_INTERNAL = 11 #If the angle at a point is > constants.limiting_angle this point is marked as HARD_EDGE (HARD_EDGES will always be stitched)
- PROJECTED_POINT = 12 #If the point was created by a projection (transferred point) of a neighbor it is marked as PROJECTED_POINT
- REGULAR_SPACING_INTERNAL = 13 # introduced to not exceed maximal stichting distance
- #FORBIDDEN_POINT_INTERNAL=14 #Legacy
- SOFT_EDGE = 15 #If the angle at a point is <= constants.limiting_angle this point is marked as SOFT_EDGE
- HARD_EDGE = 16 #If the angle at a point is > constants.limiting_angle this point is marked as HARD_EDGE (HARD_EDGES will always be stitched)
- FORBIDDEN_POINT=17 #Only relevant for desired interlacing - non-shifted point positions at the next neighbor are marked as forbidden
- REPLACED_FORBIDDEN_POINT=18 #If one decides to avoid forbidden points new points to the left and to the right as replacement are created
- DIRECT = 19 #Calculated by next neighbor projection
- OVERNEXT = 20 #Calculated by overnext neighbor projection
+ # INITIAL_RASTERING = 2 #Legacy
+ # point which must be stitched to avoid to large deviations to the desired path
+ EDGE_NEEDED = 3
+ # NOT_NEEDED = 4 #Legacy
+ # ALREADY_TRANSFERRED = 5 #Legacy
+ # ADDITIONAL_TRACKING_POINT_NOT_NEEDED = 6 #Legacy
+ # EDGE_RASTERING_ALLOWED = 7 #Legacy
+ # EDGE_PREVIOUSLY_SHIFTED = 8 #Legacy
+ ENTER_LEAVING_POINT = 9 # Whether this point is used to enter or leave a child
+ # If the angle at a point is <= constants.limiting_angle this point is marked as SOFT_EDGE
+ SOFT_EDGE_INTERNAL = 10
+ # If the angle at a point is > constants.limiting_angle this point is marked as HARD_EDGE (HARD_EDGES will always be stitched)
+ HARD_EDGE_INTERNAL = 11
+ # If the point was created by a projection (transferred point) of a neighbor it is marked as PROJECTED_POINT
+ PROJECTED_POINT = 12
+ REGULAR_SPACING_INTERNAL = 13 # introduced to not exceed maximal stichting distance
+ # FORBIDDEN_POINT_INTERNAL=14 #Legacy
+ SOFT_EDGE = 15 # If the angle at a point is <= constants.limiting_angle this point is marked as SOFT_EDGE
+ # If the angle at a point is > constants.limiting_angle this point is marked as HARD_EDGE (HARD_EDGES will always be stitched)
+ HARD_EDGE = 16
+ FORBIDDEN_POINT = 17 # Only relevant for desired interlacing - non-shifted point positions at the next neighbor are marked as forbidden
+ # If one decides to avoid forbidden points new points to the left and to the right as replacement are created
+ REPLACED_FORBIDDEN_POINT = 18
+ DIRECT = 19 # Calculated by next neighbor projection
+ OVERNEXT = 20 # Calculated by overnext neighbor projection
# Calculates the angles between adjacent edges at each interior point
-#Note that the first and last values in the return array are zero since for the boundary points no angle calculations were possible
+# Note that the first and last values in the return array are zero since for the boundary points no angle calculations were possible
def calculate_line_angles(line):
Angles = np.zeros(len(line.coords))
for i in range(1, len(line.coords)-1):
@@ -42,44 +49,47 @@ def calculate_line_angles(line):
vec2 = np.array(line.coords[i+1])-np.array(line.coords[i])
vec1length = np.linalg.norm(vec1)
vec2length = np.linalg.norm(vec2)
- #if vec1length <= 0:
+ # if vec1length <= 0:
# print("HIER FEHLER")
-
- #if vec2length <=0:
+
+ # if vec2length <=0:
# print("HIER FEHLEr")
- assert(vec1length >0)
- assert(vec2length >0)
- scalar_prod=np.dot(vec1, vec2)/(vec1length*vec2length)
- scalar_prod = min(max(scalar_prod,-1),1)
- #if scalar_prod > 1.0:
+ assert(vec1length > 0)
+ assert(vec2length > 0)
+ scalar_prod = np.dot(vec1, vec2)/(vec1length*vec2length)
+ scalar_prod = min(max(scalar_prod, -1), 1)
+ # if scalar_prod > 1.0:
# scalar_prod = 1.0
- #elif scalar_prod < -1.0:
+ # elif scalar_prod < -1.0:
# scalar_prod = -1.0
Angles[i] = math.acos(scalar_prod)
return Angles
-#Rasters a line between start_distance and end_distance.
-#Input:
-#-line: The line to be rastered
-#-start_distance: The distance along the line from which the rastering should start
-#-end_distance: The distance along the line until which the rastering should be done
-#-maxstitch_distance: The maximum allowed stitch distance
-#-stitching_direction: =1 is stitched along line direction, =-1 if stitched in reversed order. Note that
+# Rasters a line between start_distance and end_distance.
+# Input:
+# -line: The line to be rastered
+# -start_distance: The distance along the line from which the rastering should start
+# -end_distance: The distance along the line until which the rastering should be done
+# -maxstitch_distance: The maximum allowed stitch distance
+# -stitching_direction: =1 is stitched along line direction, =-1 if stitched in reversed order. Note that
# start_distance > end_distance for stitching_direction = -1
-#-must_use_points_deque: deque with projected points on line from its neighbors. An item of the deque
-#is setup as follows: ((projected point on line, LineStringSampling.PointSource), priority=distance along line)
-#index of point_origin is the index of the point in the neighboring line
-#-abs_offset: used offset between to offsetted curves
-#Output:
-#-List of tuples with the rastered point coordinates
-#-List which defines the point origin for each point according to the PointSource enum.
-def raster_line_string_with_priority_points(line, start_distance, end_distance, maxstitch_distance, stitching_direction, must_use_points_deque, abs_offset):
+# -must_use_points_deque: deque with projected points on line from its neighbors. An item of the deque
+# is setup as follows: ((projected point on line, LineStringSampling.PointSource), priority=distance along line)
+# index of point_origin is the index of the point in the neighboring line
+# -abs_offset: used offset between to offsetted curves
+# Output:
+# -List of tuples with the rastered point coordinates
+# -List which defines the point origin for each point according to the PointSource enum.
+
+
+def raster_line_string_with_priority_points(line, start_distance, end_distance, maxstitch_distance,
+ stitching_direction, must_use_points_deque, abs_offset):
if (abs(end_distance-start_distance) < constants.line_lengh_seen_as_one_point):
return [line.interpolate(start_distance).coords[0]], [PointSource.HARD_EDGE]
assert (stitching_direction == -1 and start_distance >= end_distance) or (
stitching_direction == 1 and start_distance <= end_distance)
-
+
deque_points = list(must_use_points_deque)
linecoords = line.coords
@@ -92,7 +102,8 @@ def raster_line_string_with_priority_points(line, start_distance, end_distance,
deque_points[i] = (deque_points[i][0],
line.length-deque_points[i][1])
else:
- deque_points = deque_points[::-1] #Since points with highest priority (=distance along line) are first (descending sorted)
+ # Since points with highest priority (=distance along line) are first (descending sorted)
+ deque_points = deque_points[::-1]
# Remove all points from the deque which do not fall in the segment [start_distance; end_distance]
while (len(deque_points) > 0 and deque_points[0][1] <= start_distance+min(maxstitch_distance/20, constants.point_spacing_to_be_considered_equal)):
@@ -107,95 +118,109 @@ def raster_line_string_with_priority_points(line, start_distance, end_distance,
path_coords = substring(aligned_line,
start_distance, end_distance)
- #aligned line is a line without doubled points. I had the strange situation in which the offset "start_distance" from the line beginning resulted in a starting point which was
- # already present in aligned_line causing a doubled point. A double point is not allowed in the following calculations so we need to remove it:
- if abs(path_coords.coords[0][0]-path_coords.coords[1][0])<constants.eps and abs(path_coords.coords[0][1]-path_coords.coords[1][1])<constants.eps:
+ # aligned line is a line without doubled points.
+ # I had the strange situation in which the offset "start_distance" from the line beginning
+ # resulted in a starting point which was already present in aligned_line causing a doubled point.
+ # A double point is not allowed in the following calculations so we need to remove it:
+ if (abs(path_coords.coords[0][0]-path_coords.coords[1][0]) < constants.eps and
+ abs(path_coords.coords[0][1]-path_coords.coords[1][1]) < constants.eps):
path_coords.coords = path_coords.coords[1:]
- if abs(path_coords.coords[-1][0]-path_coords.coords[-2][0])<constants.eps and abs(path_coords.coords[-1][1]-path_coords.coords[-2][1])<constants.eps:
+ if (abs(path_coords.coords[-1][0]-path_coords.coords[-2][0]) < constants.eps and
+ abs(path_coords.coords[-1][1]-path_coords.coords[-2][1]) < constants.eps):
path_coords.coords = path_coords.coords[:-1]
angles = calculate_line_angles(path_coords)
current_distance = start_distance
- #Next we merge the line points and the projected (deque) points into one list
+ # Next we merge the line points and the projected (deque) points into one list
merged_point_list = []
dq_iter = 0
- for point,angle in zip(path_coords.coords,angles):
- #if abs(point[0]-40.4) < 0.2 and abs(point[1]-2.3)< 0.2:
+ for point, angle in zip(path_coords.coords, angles):
+ # if abs(point[0]-40.4) < 0.2 and abs(point[1]-2.3)< 0.2:
# print("GEFUNDEN")
current_distance = start_distance+path_coords.project(Point(point))
while dq_iter < len(deque_points) and deque_points[dq_iter][1] < current_distance:
- #We want to avoid setting points at soft edges close to forbidden points
+ # We want to avoid setting points at soft edges close to forbidden points
if deque_points[dq_iter][0].point_source == PointSource.FORBIDDEN_POINT:
- #Check whether a previous added point is a soft edge close to the forbidden point
- if (merged_point_list[-1][0].point_source == PointSource.SOFT_EDGE_INTERNAL and
+ # Check whether a previous added point is a soft edge close to the forbidden point
+ if (merged_point_list[-1][0].point_source == PointSource.SOFT_EDGE_INTERNAL and
abs(merged_point_list[-1][1]-deque_points[dq_iter][1] < abs_offset*constants.factor_offset_forbidden_point)):
item = merged_point_list.pop()
- merged_point_list.append((PointTransfer.projected_point_tuple(point=item[0].point, point_source=\
- PointSource.FORBIDDEN_POINT),item[1]))
+ merged_point_list.append((PointTransfer.projected_point_tuple(
+ point=item[0].point, point_source=PointSource.FORBIDDEN_POINT), item[1]))
else:
merged_point_list.append(deque_points[dq_iter])
- dq_iter+=1
- #Check whether the current point is close to a forbidden point
- if (dq_iter < len(deque_points) and
+ dq_iter += 1
+ # Check whether the current point is close to a forbidden point
+ if (dq_iter < len(deque_points) and
deque_points[dq_iter-1][0].point_source == PointSource.FORBIDDEN_POINT and
angle < constants.limiting_angle and
- abs(deque_points[dq_iter-1][1]-current_distance) < abs_offset*constants.factor_offset_forbidden_point):
+ abs(deque_points[dq_iter-1][1]-current_distance) < abs_offset*constants.factor_offset_forbidden_point):
point_source = PointSource.FORBIDDEN_POINT
else:
if angle < constants.limiting_angle:
point_source = PointSource.SOFT_EDGE_INTERNAL
else:
point_source = PointSource.HARD_EDGE_INTERNAL
- merged_point_list.append((PointTransfer.projected_point_tuple(point=Point(point), point_source=point_source),current_distance))
+ merged_point_list.append((PointTransfer.projected_point_tuple(
+ point=Point(point), point_source=point_source), current_distance))
result_list = [merged_point_list[0]]
-
- #General idea: Take one point of merged_point_list after another into the current segment until this segment is not simplified to a straight line by shapelys simplify method.
- #Then, look at the points within this segment and choose the best fitting one (HARD_EDGE > OVERNEXT projected point > DIRECT projected point) as termination of this segment
+
+ # General idea: Take one point of merged_point_list after another into the current segment until this segment is not simplified
+ # to a straight line by shapelys simplify method.
+ # Then, look at the points within this segment and choose the best fitting one
+ # (HARD_EDGE > OVERNEXT projected point > DIRECT projected point) as termination of this segment
# and start point for the next segment (so we do not always take the maximum possible length for a segment)
segment_start_index = 0
segment_end_index = 1
forbidden_point_list = []
- while segment_end_index < len(merged_point_list):
- #if abs(merged_point_list[segment_end_index-1][0].point.coords[0][0]-67.9) < 0.2 and abs(merged_point_list[segment_end_index-1][0].point.coords[0][1]-161.0)< 0.2:
+ while segment_end_index < len(merged_point_list):
+ # if abs(merged_point_list[segment_end_index-1][0].point.coords[0][0]-67.9) < 0.2 and
+ # abs(merged_point_list[segment_end_index-1][0].point.coords[0][1]-161.0)< 0.2:
# print("GEFUNDEN")
- #Collection of points for the current segment
+ # Collection of points for the current segment
current_point_list = [merged_point_list[segment_start_index][0].point]
-
+
while segment_end_index < len(merged_point_list):
- segment_length = merged_point_list[segment_end_index][1]-merged_point_list[segment_start_index][1]
+ segment_length = merged_point_list[segment_end_index][1] - \
+ merged_point_list[segment_start_index][1]
if segment_length > maxstitch_distance+constants.point_spacing_to_be_considered_equal:
- new_distance = merged_point_list[segment_start_index][1]+maxstitch_distance
- merged_point_list.insert(segment_end_index,(PointTransfer.projected_point_tuple(point=aligned_line.interpolate(new_distance), point_source=\
- PointSource.REGULAR_SPACING_INTERNAL),new_distance))
- if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-12.2) < 0.2 and abs(merged_point_list[segment_end_index][0].point.coords[0][1]-0.9)< 0.2:
- print("GEFUNDEN")
- segment_end_index+=1
+ new_distance = merged_point_list[segment_start_index][1] + \
+ maxstitch_distance
+ merged_point_list.insert(segment_end_index, (PointTransfer.projected_point_tuple(
+ point=aligned_line.interpolate(new_distance), point_source=PointSource.REGULAR_SPACING_INTERNAL), new_distance))
+ # if (abs(merged_point_list[segment_end_index][0].point.coords[0][0]-12.2) < 0.2 and
+ # abs(merged_point_list[segment_end_index][0].point.coords[0][1]-0.9) < 0.2):
+ # print("GEFUNDEN")
+ segment_end_index += 1
break
- #if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-93.6) < 0.2 and abs(merged_point_list[segment_end_index][0].point.coords[0][1]-122.7)< 0.2:
+ # if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-93.6) < 0.2 and
+ # abs(merged_point_list[segment_end_index][0].point.coords[0][1]-122.7)< 0.2:
# print("GEFUNDEN")
-
- current_point_list.append(merged_point_list[segment_end_index][0].point)
- simplified_len = len(LineString(current_point_list).simplify(constants.factor_offset_remove_dense_points*abs_offset,preserve_topology=False).coords)
- if simplified_len > 2: #not all points have been simplified - so we need to add it
+
+ current_point_list.append(
+ merged_point_list[segment_end_index][0].point)
+ simplified_len = len(LineString(current_point_list).simplify(
+ constants.factor_offset_remove_dense_points*abs_offset, preserve_topology=False).coords)
+ if simplified_len > 2: # not all points have been simplified - so we need to add it
break
- if merged_point_list[segment_end_index][0].point_source ==PointSource.HARD_EDGE_INTERNAL:
- segment_end_index+=1
+ if merged_point_list[segment_end_index][0].point_source == PointSource.HARD_EDGE_INTERNAL:
+ segment_end_index += 1
break
- segment_end_index+=1
+ segment_end_index += 1
- segment_end_index-=1
+ segment_end_index -= 1
- #Now we choose the best fitting point within this segment
+ # Now we choose the best fitting point within this segment
index_overnext = -1
index_direct = -1
index_hard_edge = -1
- iter = segment_start_index+1
+ iter = segment_start_index+1
while (iter <= segment_end_index):
if merged_point_list[iter][0].point_source == PointSource.OVERNEXT:
index_overnext = iter
@@ -208,48 +233,48 @@ def raster_line_string_with_priority_points(line, start_distance, end_distance,
segment_end_index = index_hard_edge
else:
if index_overnext != -1:
- if (index_direct != -1 and index_direct > index_overnext and
- (merged_point_list[index_direct][1]-merged_point_list[index_overnext][1]) >=
- constants.factor_segment_length_direct_preferred_over_overnext*
+ if (index_direct != -1 and index_direct > index_overnext and
+ (merged_point_list[index_direct][1]-merged_point_list[index_overnext][1]) >=
+ constants.factor_segment_length_direct_preferred_over_overnext *
(merged_point_list[index_overnext][1]-merged_point_list[segment_start_index][1])):
- #We allow to take the direct projected point instead of the overnext projected point if it would result in a
- #significant longer segment length
+ # We allow to take the direct projected point instead of the overnext projected point if it would result in a
+ # significant longer segment length
segment_end_index = index_direct
else:
segment_end_index = index_overnext
elif index_direct != -1:
segment_end_index = index_direct
- #Usually OVERNEXT and DIRECT points are close to each other and in some cases both were selected as segment edges
- #If they are too close (<abs_offset) we remove one of it
+ # Usually OVERNEXT and DIRECT points are close to each other and in some cases both were selected as segment edges
+ # If they are too close (<abs_offset) we remove one of it
if (((merged_point_list[segment_start_index][0].point_source == PointSource.OVERNEXT and
merged_point_list[segment_end_index][0].point_source == PointSource.DIRECT) or
(merged_point_list[segment_start_index][0].point_source == PointSource.DIRECT and
merged_point_list[segment_end_index][0].point_source == PointSource.OVERNEXT)) and
- abs(merged_point_list[segment_end_index][1] - merged_point_list[segment_start_index][1]) < abs_offset):
+ abs(merged_point_list[segment_end_index][1] - merged_point_list[segment_start_index][1]) < abs_offset):
result_list.pop()
result_list.append(merged_point_list[segment_end_index])
- #To have a chance to replace all forbidden points afterwards
+ # To have a chance to replace all forbidden points afterwards
if merged_point_list[segment_end_index][0].point_source == PointSource.FORBIDDEN_POINT:
forbidden_point_list.append(len(result_list)-1)
segment_start_index = segment_end_index
- segment_end_index+=1
+ segment_end_index += 1
- return_point_list = [] #[result_list[0][0].point.coords[0]]
- return_point_source_list = []#[result_list[0][0].point_source]
+ return_point_list = [] # [result_list[0][0].point.coords[0]]
+ return_point_source_list = [] # [result_list[0][0].point_source]
- #Currently replacement of forbidden points not satisfying
- #result_list = replace_forbidden_points(aligned_line, result_list, forbidden_point_list,abs_offset)
+ # Currently replacement of forbidden points not satisfying
+ # result_list = replace_forbidden_points(aligned_line, result_list, forbidden_point_list,abs_offset)
- #Finally we create the final return_point_list and return_point_source_list
+ # Finally we create the final return_point_list and return_point_source_list
for i in range(len(result_list)):
return_point_list.append(result_list[i][0].point.coords[0])
- #if abs(result_list[i][0].point.coords[0][0]-91.7) < 0.2 and abs(result_list[i][0].point.coords[0][1]-106.15)< 0.2:
+ # if abs(result_list[i][0].point.coords[0][0]-91.7) < 0.2 and abs(result_list[i][0].point.coords[0][1]-106.15)< 0.2:
# print("GEFUNDEN")
if result_list[i][0].point_source == PointSource.HARD_EDGE_INTERNAL:
- point_source = PointSource.HARD_EDGE
+ point_source = PointSource.HARD_EDGE
elif result_list[i][0].point_source == PointSource.SOFT_EDGE_INTERNAL:
point_source = PointSource.SOFT_EDGE
elif result_list[i][0].point_source == PointSource.REGULAR_SPACING_INTERNAL:
@@ -261,132 +286,145 @@ def raster_line_string_with_priority_points(line, start_distance, end_distance,
return_point_source_list.append(point_source)
-
assert(len(return_point_list) == len(return_point_source_list))
- #return remove_dense_points(returnpointlist, returnpointsourcelist, maxstitch_distance,abs_offset)
+ # return remove_dense_points(returnpointlist, returnpointsourcelist, maxstitch_distance,abs_offset)
return return_point_list, return_point_source_list
-#Rasters a line between start_distance and end_distance.
-#Input:
-#-line: The line to be rastered
-#-start_distance: The distance along the line from which the rastering should start
-#-end_distance: The distance along the line until which the rastering should be done
-#-maxstitch_distance: The maximum allowed stitch distance
-#-stitching_direction: =1 is stitched along line direction, =-1 if stitched in reversed order. Note that
+# Rasters a line between start_distance and end_distance.
+# Input:
+# -line: The line to be rastered
+# -start_distance: The distance along the line from which the rastering should start
+# -end_distance: The distance along the line until which the rastering should be done
+# -maxstitch_distance: The maximum allowed stitch distance
+# -stitching_direction: =1 is stitched along line direction, =-1 if stitched in reversed order. Note that
# start_distance > end_distance for stitching_direction = -1
-#-must_use_points_deque: deque with projected points on line from its neighbors. An item of the deque
-#is setup as follows: ((projected point on line, LineStringSampling.PointSource), priority=distance along line)
-#index of point_origin is the index of the point in the neighboring line
-#-abs_offset: used offset between to offsetted curves
-#Output:
-#-List of tuples with the rastered point coordinates
-#-List which defines the point origin for each point according to the PointSource enum.
+# -must_use_points_deque: deque with projected points on line from its neighbors. An item of the deque
+# is setup as follows: ((projected point on line, LineStringSampling.PointSource), priority=distance along line)
+# index of point_origin is the index of the point in the neighboring line
+# -abs_offset: used offset between to offsetted curves
+# Output:
+# -List of tuples with the rastered point coordinates
+# -List which defines the point origin for each point according to the PointSource enum.
+
+
def raster_line_string_with_priority_points_graph(line, maxstitch_distance, stitching_direction, must_use_points_deque, abs_offset, offset_by_half):
if (line.length < constants.line_lengh_seen_as_one_point):
return [line.coords[0]], [PointSource.HARD_EDGE]
-
+
deque_points = list(must_use_points_deque)
linecoords = line.coords
- if stitching_direction==-1:
+ if stitching_direction == -1:
linecoords = linecoords[::-1]
for i in range(len(deque_points)):
deque_points[i] = (deque_points[i][0],
line.length-deque_points[i][1])
else:
- deque_points = deque_points[::-1] #Since points with highest priority (=distance along line) are first (descending sorted)
+ # Since points with highest priority (=distance along line) are first (descending sorted)
+ deque_points = deque_points[::-1]
# Ordering in priority queue:
# (point, LineStringSampling.PointSource), priority)
- aligned_line = LineString(linecoords) #might be different from line for stitching_direction=-1
+ # might be different from line for stitching_direction=-1
+ aligned_line = LineString(linecoords)
angles = calculate_line_angles(aligned_line)
- #For the first and last point we cannot calculate an angle. Set it to above the limit to make it a hard edge
+ # For the first and last point we cannot calculate an angle. Set it to above the limit to make it a hard edge
angles[0] = 1.1*constants.limiting_angle
- angles[-1] = 1.1*constants.limiting_angle
+ angles[-1] = 1.1*constants.limiting_angle
current_distance = 0.0
- #Next we merge the line points and the projected (deque) points into one list
+ # Next we merge the line points and the projected (deque) points into one list
merged_point_list = []
dq_iter = 0
- for point,angle in zip(aligned_line.coords,angles):
- #if abs(point[0]-52.9) < 0.2 and abs(point[1]-183.4)< 0.2:
+ for point, angle in zip(aligned_line.coords, angles):
+ # if abs(point[0]-52.9) < 0.2 and abs(point[1]-183.4)< 0.2:
# print("GEFUNDEN")
current_distance = aligned_line.project(Point(point))
while dq_iter < len(deque_points) and deque_points[dq_iter][1] < current_distance:
- #We want to avoid setting points at soft edges close to forbidden points
+ # We want to avoid setting points at soft edges close to forbidden points
if deque_points[dq_iter][0].point_source == PointSource.FORBIDDEN_POINT:
- #Check whether a previous added point is a soft edge close to the forbidden point
- if (merged_point_list[-1][0].point_source == PointSource.SOFT_EDGE_INTERNAL and
+ # Check whether a previous added point is a soft edge close to the forbidden point
+ if (merged_point_list[-1][0].point_source == PointSource.SOFT_EDGE_INTERNAL and
abs(merged_point_list[-1][1]-deque_points[dq_iter][1] < abs_offset*constants.factor_offset_forbidden_point)):
item = merged_point_list.pop()
- merged_point_list.append((PointTransfer.projected_point_tuple(point=item[0].point, point_source=\
- PointSource.FORBIDDEN_POINT),item[1]))
+ merged_point_list.append((PointTransfer.projected_point_tuple(
+ point=item[0].point, point_source=PointSource.FORBIDDEN_POINT), item[1]))
else:
merged_point_list.append(deque_points[dq_iter])
- dq_iter+=1
- #Check whether the current point is close to a forbidden point
- if (dq_iter < len(deque_points) and
+ dq_iter += 1
+ # Check whether the current point is close to a forbidden point
+ if (dq_iter < len(deque_points) and
deque_points[dq_iter-1][0].point_source == PointSource.FORBIDDEN_POINT and
angle < constants.limiting_angle and
- abs(deque_points[dq_iter-1][1]-current_distance) < abs_offset*constants.factor_offset_forbidden_point):
+ abs(deque_points[dq_iter-1][1]-current_distance) < abs_offset*constants.factor_offset_forbidden_point):
point_source = PointSource.FORBIDDEN_POINT
else:
if angle < constants.limiting_angle:
point_source = PointSource.SOFT_EDGE_INTERNAL
else:
point_source = PointSource.HARD_EDGE_INTERNAL
- merged_point_list.append((PointTransfer.projected_point_tuple(point=Point(point), point_source=point_source),current_distance))
+ merged_point_list.append((PointTransfer.projected_point_tuple(
+ point=Point(point), point_source=point_source), current_distance))
result_list = [merged_point_list[0]]
-
- #General idea: Take one point of merged_point_list after another into the current segment until this segment is not simplified to a straight line by shapelys simplify method.
- #Then, look at the points within this segment and choose the best fitting one (HARD_EDGE > OVERNEXT projected point > DIRECT projected point) as termination of this segment
+
+ # General idea: Take one point of merged_point_list after another into the current segment until this segment is not simplified
+ # to a straight line by shapelys simplify method.
+ # Then, look at the points within this segment and choose the best fitting one
+ # (HARD_EDGE > OVERNEXT projected point > DIRECT projected point) as termination of this segment
# and start point for the next segment (so we do not always take the maximum possible length for a segment)
segment_start_index = 0
segment_end_index = 1
forbidden_point_list = []
- while segment_end_index < len(merged_point_list):
- #if abs(merged_point_list[segment_end_index-1][0].point.coords[0][0]-67.9) < 0.2 and abs(merged_point_list[segment_end_index-1][0].point.coords[0][1]-161.0)< 0.2:
+ while segment_end_index < len(merged_point_list):
+ # if abs(merged_point_list[segment_end_index-1][0].point.coords[0][0]-67.9) < 0.2 and
+ # abs(merged_point_list[segment_end_index-1][0].point.coords[0][1]-161.0)< 0.2:
# print("GEFUNDEN")
- #Collection of points for the current segment
+ # Collection of points for the current segment
current_point_list = [merged_point_list[segment_start_index][0].point]
-
+
while segment_end_index < len(merged_point_list):
- segment_length = merged_point_list[segment_end_index][1]-merged_point_list[segment_start_index][1]
+ segment_length = merged_point_list[segment_end_index][1] - \
+ merged_point_list[segment_start_index][1]
if segment_length > maxstitch_distance+constants.point_spacing_to_be_considered_equal:
- new_distance = merged_point_list[segment_start_index][1]+maxstitch_distance
- merged_point_list.insert(segment_end_index,(PointTransfer.projected_point_tuple(point=aligned_line.interpolate(new_distance), point_source=\
- PointSource.REGULAR_SPACING_INTERNAL),new_distance))
- #if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-12.2) < 0.2 and abs(merged_point_list[segment_end_index][0].point.coords[0][1]-0.9)< 0.2:
+ new_distance = merged_point_list[segment_start_index][1] + \
+ maxstitch_distance
+ merged_point_list.insert(segment_end_index, (PointTransfer.projected_point_tuple(
+ point=aligned_line.interpolate(new_distance), point_source=PointSource.REGULAR_SPACING_INTERNAL), new_distance))
+ # if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-12.2) < 0.2 and 7
+ # abs(merged_point_list[segment_end_index][0].point.coords[0][1]-0.9)< 0.2:
# print("GEFUNDEN")
- segment_end_index+=1
+ segment_end_index += 1
break
- #if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-34.4) < 0.2 and abs(merged_point_list[segment_end_index][0].point.coords[0][1]-6.2)< 0.2:
+ # if abs(merged_point_list[segment_end_index][0].point.coords[0][0]-34.4) < 0.2 and
+ # abs(merged_point_list[segment_end_index][0].point.coords[0][1]-6.2)< 0.2:
# print("GEFUNDEN")
-
- current_point_list.append(merged_point_list[segment_end_index][0].point)
- simplified_len = len(LineString(current_point_list).simplify(constants.factor_offset_remove_dense_points*abs_offset,preserve_topology=False).coords)
- if simplified_len > 2: #not all points have been simplified - so we need to add it
+
+ current_point_list.append(
+ merged_point_list[segment_end_index][0].point)
+ simplified_len = len(LineString(current_point_list).simplify(
+ constants.factor_offset_remove_dense_points*abs_offset, preserve_topology=False).coords)
+ if simplified_len > 2: # not all points have been simplified - so we need to add it
break
- if merged_point_list[segment_end_index][0].point_source ==PointSource.HARD_EDGE_INTERNAL:
- segment_end_index+=1
+ if merged_point_list[segment_end_index][0].point_source == PointSource.HARD_EDGE_INTERNAL:
+ segment_end_index += 1
break
- segment_end_index+=1
+ segment_end_index += 1
- segment_end_index-=1
+ segment_end_index -= 1
- #Now we choose the best fitting point within this segment
+ # Now we choose the best fitting point within this segment
index_overnext = -1
index_direct = -1
index_hard_edge = -1
- iter = segment_start_index+1
+ iter = segment_start_index+1
while (iter <= segment_end_index):
if merged_point_list[iter][0].point_source == PointSource.OVERNEXT:
index_overnext = iter
@@ -406,48 +444,49 @@ def raster_line_string_with_priority_points_graph(line, maxstitch_distance, stit
index_less_preferred = index_overnext
if index_preferred != -1:
- if (index_less_preferred != -1 and index_less_preferred > index_preferred and
- (merged_point_list[index_less_preferred][1]-merged_point_list[index_preferred][1]) >=
- constants.factor_segment_length_direct_preferred_over_overnext*
+ if (index_less_preferred != -1 and index_less_preferred > index_preferred and
+ (merged_point_list[index_less_preferred][1]-merged_point_list[index_preferred][1]) >=
+ constants.factor_segment_length_direct_preferred_over_overnext *
(merged_point_list[index_preferred][1]-merged_point_list[segment_start_index][1])):
- #We allow to take the direct projected point instead of the overnext projected point if it would result in a
- #significant longer segment length
+ # We allow to take the direct projected point instead of the overnext projected point if it would result in a
+ # significant longer segment length
segment_end_index = index_less_preferred
else:
segment_end_index = index_preferred
elif index_less_preferred != -1:
segment_end_index = index_less_preferred
- #Usually OVERNEXT and DIRECT points are close to each other and in some cases both were selected as segment edges
- #If they are too close (<abs_offset) we remove one of it
+ # Usually OVERNEXT and DIRECT points are close to each other and in some cases both were selected as segment edges
+ # If they are too close (<abs_offset) we remove one of it
if (((merged_point_list[segment_start_index][0].point_source == PointSource.OVERNEXT and
merged_point_list[segment_end_index][0].point_source == PointSource.DIRECT) or
(merged_point_list[segment_start_index][0].point_source == PointSource.DIRECT and
merged_point_list[segment_end_index][0].point_source == PointSource.OVERNEXT)) and
- abs(merged_point_list[segment_end_index][1] - merged_point_list[segment_start_index][1]) < abs_offset):
+ abs(merged_point_list[segment_end_index][1] - merged_point_list[segment_start_index][1]) < abs_offset):
result_list.pop()
result_list.append(merged_point_list[segment_end_index])
- #To have a chance to replace all forbidden points afterwards
+ # To have a chance to replace all forbidden points afterwards
if merged_point_list[segment_end_index][0].point_source == PointSource.FORBIDDEN_POINT:
forbidden_point_list.append(len(result_list)-1)
segment_start_index = segment_end_index
- segment_end_index+=1
+ segment_end_index += 1
- return_point_list = [] #[result_list[0][0].point.coords[0]]
- return_point_source_list = []#[result_list[0][0].point_source]
+ return_point_list = [] # [result_list[0][0].point.coords[0]]
+ return_point_source_list = [] # [result_list[0][0].point_source]
- #Currently replacement of forbidden points not satisfying
- result_list = replace_forbidden_points(aligned_line, result_list, forbidden_point_list,abs_offset)
+ # Currently replacement of forbidden points not satisfying
+ result_list = replace_forbidden_points(
+ aligned_line, result_list, forbidden_point_list, abs_offset)
- #Finally we create the final return_point_list and return_point_source_list
+ # Finally we create the final return_point_list and return_point_source_list
for i in range(len(result_list)):
return_point_list.append(result_list[i][0].point.coords[0])
- #if abs(result_list[i][0].point.coords[0][0]-91.7) < 0.2 and abs(result_list[i][0].point.coords[0][1]-106.15)< 0.2:
+ # if abs(result_list[i][0].point.coords[0][0]-91.7) < 0.2 and abs(result_list[i][0].point.coords[0][1]-106.15)< 0.2:
# print("GEFUNDEN")
if result_list[i][0].point_source == PointSource.HARD_EDGE_INTERNAL:
- point_source = PointSource.HARD_EDGE
+ point_source = PointSource.HARD_EDGE
elif result_list[i][0].point_source == PointSource.SOFT_EDGE_INTERNAL:
point_source = PointSource.SOFT_EDGE
elif result_list[i][0].point_source == PointSource.REGULAR_SPACING_INTERNAL:
@@ -459,44 +498,49 @@ def raster_line_string_with_priority_points_graph(line, maxstitch_distance, stit
return_point_source_list.append(point_source)
-
assert(len(return_point_list) == len(return_point_source_list))
- #return remove_dense_points(returnpointlist, returnpointsourcelist, maxstitch_distance,abs_offset)
+ # return remove_dense_points(returnpointlist, returnpointsourcelist, maxstitch_distance,abs_offset)
return return_point_list, return_point_source_list
+
def replace_forbidden_points(line, result_list, forbidden_point_list_indices, abs_offset):
- current_index_shift = 0 #since we add and remove points in the result_list, we need to adjust the indices stored in forbidden_point_list_indices
+ # since we add and remove points in the result_list, we need to adjust the indices stored in forbidden_point_list_indices
+ current_index_shift = 0
for index in forbidden_point_list_indices:
- #if abs(result_list[index][0].point.coords[0][0]-40.7) < 0.2 and abs(result_list[index][0].point.coords[0][1]-1.3)< 0.2:
+ # if abs(result_list[index][0].point.coords[0][0]-40.7) < 0.2 and abs(result_list[index][0].point.coords[0][1]-1.3)< 0.2:
# print("GEFUNDEN")
- index+=current_index_shift
- distance_left = result_list[index][0].point.distance(result_list[index-1][0].point)/2.0
- distance_right = result_list[index][0].point.distance(result_list[(index+1)%len(result_list)][0].point)/2.0
+ index += current_index_shift
+ distance_left = result_list[index][0].point.distance(
+ result_list[index-1][0].point)/2.0
+ distance_right = result_list[index][0].point.distance(
+ result_list[(index+1) % len(result_list)][0].point)/2.0
while distance_left > constants.point_spacing_to_be_considered_equal and distance_right > constants.point_spacing_to_be_considered_equal:
new_point_left_proj = result_list[index][1]-distance_left
if new_point_left_proj < 0:
new_point_left_proj += line.length
new_point_right_proj = result_list[index][1]+distance_right
if new_point_right_proj > line.length:
- new_point_right_proj-=line.length
+ new_point_right_proj -= line.length
point_left = line.interpolate(new_point_left_proj)
point_right = line.interpolate(new_point_right_proj)
- forbidden_point_distance = result_list[index][0].point.distance(LineString([point_left, point_right]))
+ forbidden_point_distance = result_list[index][0].point.distance(
+ LineString([point_left, point_right]))
if forbidden_point_distance < constants.factor_offset_remove_dense_points*abs_offset:
del result_list[index]
- result_list.insert(index, (PointTransfer.projected_point_tuple(point=point_right, point_source=\
- PointSource.REPLACED_FORBIDDEN_POINT),new_point_right_proj))
- result_list.insert(index, (PointTransfer.projected_point_tuple(point=point_left, point_source=\
- PointSource.REPLACED_FORBIDDEN_POINT),new_point_left_proj))
- current_index_shift+=1
+ result_list.insert(index, (PointTransfer.projected_point_tuple(
+ point=point_right, point_source=PointSource.REPLACED_FORBIDDEN_POINT), new_point_right_proj))
+ result_list.insert(index, (PointTransfer.projected_point_tuple(
+ point=point_left, point_source=PointSource.REPLACED_FORBIDDEN_POINT), new_point_left_proj))
+ current_index_shift += 1
break
else:
- distance_left/=2.0
- distance_right/=2.0
+ distance_left /= 2.0
+ distance_right /= 2.0
return result_list
+
if __name__ == "__main__":
- line = LineString([(0,0), (1,0), (2,1),(3,0),(4,0)])
+ line = LineString([(0, 0), (1, 0), (2, 1), (3, 0), (4, 0)])
print(calculate_line_angles(line)*180.0/math.pi)