Skip to content

Commit

Permalink
New algorithm successes
Browse files Browse the repository at this point in the history
  • Loading branch information
YuXHe15 committed Sep 5, 2023
1 parent b2bdbd6 commit 4514e40
Show file tree
Hide file tree
Showing 10 changed files with 611 additions and 94 deletions.
216 changes: 165 additions & 51 deletions amworkflow/src/geometries/composite_geometry.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from amworkflow.src.geometries.simple_geometry import create_edge, create_wire, create_face, create_prism, random_polygon_constructor, angle_of_two_arrays, laterality_indicator, angular_bisector, p_center_of_mass, linear_interpolate
from amworkflow.src.geometries.simple_geometry import create_edge, create_wire, create_face, create_prism, random_polygon_constructor, angle_of_two_arrays, laterality_indicator, angular_bisector, p_center_of_mass, linear_interpolate, Pnt, Segments
from amworkflow.src.geometries.operator import reverse, geom_copy, translate, rotate_face, fuser, hollow_carver, cutter3D, bender
from amworkflow.src.geometries.property import topo_explorer, p_bounding_box
from amworkflow.src.geometries.builder import solid_maker
Expand All @@ -12,7 +12,7 @@
from matplotlib.patches import Polygon
import itertools
import copy as cp

import networkx as nx


def polygon_maker(side_num: int,
Expand Down Expand Up @@ -373,28 +373,31 @@ def find_intersect(lines: np.ndarray) -> np.ndarray:
L1 = (pt2 - pt1) / np.linalg.norm(pt2 - pt1)
L2 = (pt4 - pt3) / np.linalg.norm(pt4 - pt3)
V1 = pt4 - pt1
if np.linalg.norm(L1 - L2, 1) < 1e-8:
D1 = np.linalg.norm(V1)
if np.isclose(np.dot(L1, L2),0) or np.isclose(np.dot(L1, L2),-1):
parallel = True
print("Two lines are parallel.")
return np.full((3,1), np.nan)
indicate = np.linalg.det(np.array([V1, L1, L2]))
if np.abs(indicate) < 1e-8:
coplanarity = True
coplanarity = True
else:
print("lines are not in the same plane.")
return np.full((3,1), np.nan)
return np.full((1,3), np.nan)
if coplanarity and not parallel:
pt5_pt4 = np.linalg.norm(np.cross(V1, L1))
theta = np.arccos(np.dot(L1, L2))
o_pt5 = pt5_pt4 / np.tan(theta)
o_pt4 = pt5_pt4 / np.sin(theta)
pt1_pt4 = np.linalg.norm(V1)
V1_n = V1 / pt1_pt4
cos_beta = np.dot(V1_n, L1)
pt1_pt5 = pt1_pt4 * cos_beta
o_pt1 = pt1_pt5 - o_pt5
o = L1 * o_pt1 + pt1
return o
if np.isclose(D1,0):
return pt1
else:
pt5_pt4 = np.linalg.norm(np.cross(V1, L1))
theta = np.arccos(np.dot(L1, L2))
o_pt5 = pt5_pt4 / np.tan(theta)
o_pt4 = pt5_pt4 / np.sin(theta)
V1_n = V1 / D1
cos_beta = np.dot(V1_n, L1)
pt1_pt5 = D1 * cos_beta
pt1_o = pt1_pt5 - o_pt5
o = L1 * pt1_o + pt1
return o

def index2array(ind: list, array: np.ndarray):
real_array = []
Expand Down Expand Up @@ -529,7 +532,7 @@ def deter_dum(line: np.ndarray):

class CreateWallByPoints():
def __init__(self, pts: list, th: float, height: float):
self.pts = [np.array(list(i.Coord())) if isinstance(i, gp_Pnt) else np.array(i) for i in pts]
self.coords = [np.array(list(i.Coord())) if isinstance(i, gp_Pnt) else np.array(i) for i in pts]
self.height = height
self.is_loop = False
self.R = None
Expand All @@ -540,17 +543,17 @@ def __init__(self, pts: list, th: float, height: float):
self.vecs = []
self.dir_vecs = []
self.ths = []
self.lft_pts = []
self.rgt_pts = []
self.lft_coords = []
self.rgt_coords = []
self.loops_h = []
self.loops = []
self.fc_set = []
self.poly: TopoDS_Shape

def create_polygon(self):
if not self.is_loop:
gp_pts_lft = [gp_Pnt(i[0],i[1],i[2]) for i in self.lft_pts]
gp_pts_rgt = [gp_Pnt(i[0],i[1],i[2]) for i in self.rgt_pts]
gp_pts_lft = [gp_Pnt(i[0],i[1],i[2]) for i in self.lft_coords]
gp_pts_rgt = [gp_Pnt(i[0],i[1],i[2]) for i in self.rgt_coords]
self.gp_pts = gp_pts_lft + gp_pts_rgt
self.poly = random_polygon_constructor(self.gp_pts)
else:
Expand All @@ -572,9 +575,9 @@ def create_polygon(self):
def Shape(self):
if self.overlap:
self.create_sides()
for i in range(len(self.lft_pts)-1):
opts = self.lft_pts
ipts = self.rgt_pts
for i in range(len(self.lft_coords)-1):
opts = self.lft_coords
ipts = self.rgt_coords
opt1 = gp_Pnt(opts[i][0], opts[i][1], opts[i][2])
opt2 = gp_Pnt(opts[i+1][0], opts[i+1][1], opts[i+1][2])
ipt2 = gp_Pnt(ipts[i][0], ipts[i][1], ipts[i][2])
Expand All @@ -600,18 +603,18 @@ def Shape(self):

def create_sides(self):
if self.R is not None:
self.pts = polygon_interpolater(self.pts, self.interpolate)
self.pts = bender(self.pts, self.R)
self.pts = [i for i in self.pts]
self.coords = polygon_interpolater(self.coords, self.interpolate)
self.coords = bender(self.coords, self.R)
self.coords = [i for i in self.coords]
self.th *= 0.5
for i,p in enumerate(self.pts):
if i != len(self.pts) - 1:
a1 = self.pts[i+1] - self.pts[i]
for i,p in enumerate(self.coords):
if i != len(self.coords) - 1:
a1 = self.coords[i+1] - self.coords[i]
if i == 0:
if self.is_close:
dr = angular_bisector(self.pts[-1] - p, a1)
dr = angular_bisector(self.coords[-1] - p, a1)
# ang = angle_of_two_arrays(dir_vecs[i-1],dr)
ang2 = angle_of_two_arrays(laterality_indicator(p - self.pts[-1], True), dr)
ang2 = angle_of_two_arrays(laterality_indicator(p - self.coords[-1], True), dr)
ang_th = ang2
if ang2 > np.pi / 2:
dr *= -1
Expand All @@ -630,7 +633,7 @@ def create_sides(self):
nth = np.abs(self.th / np.cos(ang_th))
else:
if self.is_close:
a1 = self.pts[0] - self.pts[i]
a1 = self.coords[0] - self.coords[i]
dr = angular_bisector(-self.vecs[i-1], a1)
ang2 = angle_of_two_arrays(laterality_indicator(self.vecs[i-1], True), dr)
ang_th = ang2
Expand All @@ -644,31 +647,31 @@ def create_sides(self):
self.vecs.append(a1)
self.ths.append(nth)
self.dir_vecs.append(dr)
self.lft_pts.append(dr * nth + p)
self.lft_coords.append(dr * nth + p)
if self.overlap:
self.rgt_pts.append(-dr * nth + p)
self.rgt_coords.append(-dr * nth + p)
if self.is_close:
self.lft_pts.append(self.lft_pts[0])
self.lft_coords.append(self.lft_coords[0])
if not self.overlap:
for i,p in enumerate(self.pts[::-1]):
for i,p in enumerate(self.coords[::-1]):
dr = -self.dir_vecs[::-1][i]
nth = self.ths[::-1][i]
self.rgt_pts.append(dr * nth + p)
self.rgt_coords.append(dr * nth + p)
if self.is_close:
self.rgt_pts.append(self.rgt_pts[0])
self.pts.append(self.pts[0])
self.rgt_coords.append(self.rgt_coords[0])
self.coords.append(self.coords[0])

def create_loop(self):
if self.R is not None:
mxpt, mnpt = p_bounding_box(self.lft_pts+self.rgt_pts)
self.lft_pts = self.break_overlap(self.lft_pts)
self.rgt_pts = self.break_overlap(self.rgt_pts)
loops_lft_pt_i, peak_lft_pt_i = self.find_loop(self.lft_pts)
loops_rgt_pt_i, peak_rgt_pt_i = self.find_loop(self.rgt_pts)
mxpt, mnpt = p_bounding_box(self.lft_coords+self.rgt_coords)
self.lft_coords = self.break_overlap(self.lft_coords)
self.rgt_coords = self.break_overlap(self.rgt_coords)
loops_lft_pt_i, peak_lft_pt_i = self.find_loop(self.lft_coords)
loops_rgt_pt_i, peak_rgt_pt_i = self.find_loop(self.rgt_coords)
if (len(loops_lft_pt_i+peak_lft_pt_i)>0) or (len(loops_rgt_pt_i+peak_rgt_pt_i)>0):
self.is_loop = True
self.loops_lft = index2array(loops_lft_pt_i, self.lft_pts)
self.loops_rgt = index2array(loops_rgt_pt_i, self.rgt_pts)
self.loops_lft = index2array(loops_lft_pt_i, self.lft_coords)
self.loops_rgt = index2array(loops_rgt_pt_i, self.rgt_coords)
self.loops = self.loops_lft+self.loops_rgt
self.loops_h = self.find_topology(self.loops)

Expand Down Expand Up @@ -803,9 +806,9 @@ def visualize(self, plot_type: str) -> None:
plt.show()
elif plot_type == "linear":
plt.figure(figsize=(8, 6)) # Optional: Set the figure size
output1 = np.array(self.lft_pts)
output2 = np.array(self.rgt_pts)
talist = np.array(self.pts).T
output1 = np.array(self.lft_coords)
output2 = np.array(self.rgt_coords)
talist = np.array(self.coords).T
toutput1 = output1.T
toutput2 = output2.T
x1 = talist[0]
Expand All @@ -830,4 +833,115 @@ def visualize(self, plot_type: str) -> None:
plt.legend()
plt.axis('equal')
plt.grid(True) # Optional: Add grid lines
plt.show()
plt.show()

class CreateWallByPointsUpdate():
def __init__(self, coords: list, th: float, height: float):
self.coords = [np.array(list(i.Coord())) if isinstance(i, gp_Pnt) else np.array(i) for i in coords]
self.height = height
self.R = None
self.interpolate = 6
self.th = th
self.is_close = True
self.vecs = []
self.dir_vecs = []
self.ths = []
self.lft_coords = []
self.rgt_coords = []
self.side_coords: list
self.create_sides()
self.pnts = Segments(self.side_coords)
self.G = nx.from_dict_of_lists(self.pnts.pts_digraph, create_using=nx.DiGraph)
self.all_loops = list(nx.simple_cycles(self.G))
self.loops = self.get_loops()

def create_sides(self):
if self.R is not None:
self.coords = polygon_interpolater(self.coords, self.interpolate)
self.coords = bender(self.coords, self.R)
self.coords = [i for i in self.coords]
self.th *= 0.5
for i,p in enumerate(self.coords):
if i != len(self.coords) - 1:
a1 = self.coords[i+1] - self.coords[i]
if i == 0:
if self.is_close:
dr = angular_bisector(self.coords[-1] - p, a1)
# ang = angle_of_two_arrays(dir_vecs[i-1],dr)
ang2 = angle_of_two_arrays(laterality_indicator(p - self.coords[-1], True), dr)
ang_th = ang2
if ang2 > np.pi / 2:
dr *= -1
ang_th = np.pi - ang2
nth = np.abs(self.th / np.cos(ang_th))
else:
dr = laterality_indicator(a1, True)
nth = self.th
else:
dr = angular_bisector(-self.vecs[i-1], a1)
ang2 = angle_of_two_arrays(laterality_indicator(self.vecs[i-1], True), dr)
ang_th = ang2
if ang2 > np.pi / 2:
dr *= -1
ang_th = np.pi - ang2
nth = np.abs(self.th / np.cos(ang_th))
else:
if self.is_close:
a1 = self.coords[0] - self.coords[i]
dr = angular_bisector(-self.vecs[i-1], a1)
ang2 = angle_of_two_arrays(laterality_indicator(self.vecs[i-1], True), dr)
ang_th = ang2
if ang2 > np.pi / 2:
dr *= -1
ang_th = np.pi - ang2
nth = np.abs(self.th / np.cos(ang_th))
else:
dr = laterality_indicator(a1, True)
nth = self.th
self.vecs.append(a1)
self.ths.append(nth)
self.dir_vecs.append(dr)
self.lft_coords.append(dr * nth + p)
self.rgt_coords.append(-dr * nth + p)
if self.is_close:
self.lft_coords.append(self.lft_coords[0])
self.rgt_coords.append(self.rgt_coords[0])
self.rgt_coords = self.rgt_coords[::-1]
self.coords.append(self.coords[0])
else:
self.rgt_coords = self.rgt_coords[::-1]
self.side_coords = self.lft_coords + self.rgt_coords + self.lft_coords[0]

def visualize(self):
# Extract the x and y coordinates and IDs
a = self.pnts.pts_index
x = [coord[0] for coord in a.values()]
y = [coord[1] for coord in a.values()]
ids = list(a.keys()) # Get the point IDs

# Create a scatter plot in 2D
plt.figure()
plt.scatter(x, y)

# Annotate points with IDs
for i, (xi, yi) in enumerate(zip(x, y)):
plt.annotate(f'{ids[i]}', (xi, yi), fontsize=12, ha='right')

# Set labels and title
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('2D Scatter Plot with Annotations')

# Show the plot
plt.show()

def get_loops(self):
return [i for i in self.all_loops if len(i) > 2]

def visualize_graph(self):
layout = nx.spring_layout(self.G)
# Draw the nodes and edges
nx.draw(self.G, pos=layout, with_labels=True, node_color='skyblue', font_size=10, node_size=500)
plt.title("NetworkX Graph Visualization")
plt.show()

68 changes: 67 additions & 1 deletion amworkflow/src/geometries/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,70 @@ def shortest_distance_line_line(line1, line2):
# print(pti1, pti2)
# print(np.dot(s1,pti2 - pti1), np.dot(s2,pti2 - pti1))
distance = np.linalg.norm(pti1 - pti2)
return distance, np.array([pti1, pti2])
return distance, np.array([pti1, pti2])

def check_parallel_line_line(line1: np.ndarray, line2: np.ndarray) -> tuple:
parallel = False
colinear = False
pt1, pt2 = line1
pt3, pt4 = line2
def generate_link():
t1 = np.random.randint(1,4)* 0.1
t2 = np.random.randint(5,9) * 0.1
pt12 = (1-t1)*pt1+t1*pt2
pt34 = (1-t2)*pt3+t2*pt4
norm_L3 = np.linalg.norm(pt34 - pt12)
while np.isclose(norm_L3,0):
t1 = np.random.randint(1,4)* 0.1
t2 = np.random.randint(5,9) * 0.1
pt12 = (1-t1)*pt1+t1*pt2
pt34 = (1-t2)*pt3+t2*pt4
norm_L3 = np.linalg.norm(pt34 - pt12)
return pt12, pt34
pt12, pt34 = generate_link()
L1 = (pt2 - pt1) / np.linalg.norm(pt2 - pt1)
L2 = (pt4 - pt3) / np.linalg.norm(pt4 - pt3)
L3 = (pt34 - pt12) / np.linalg.norm(pt34 - pt12)
if np.isclose(np.linalg.norm(np.cross(L1, L2)), 0):
parallel = True
if np.isclose(np.linalg.norm(np.cross(L1, L3)), 0) and parallel:
colinear = True
return parallel, colinear

def check_overlap(line1: np.ndarray, line2: np.ndarray) -> np.ndarray:
A, B = line1
C, D = line2
s = B - A
dist_s = np.linalg.norm(s)
norm_s = s / dist_s
c = C - A
dist_c = np.linalg.norm(c)
if np.isclose(dist_c, 0):
lmbda_c = 0
else:
norm_c = c / dist_c
sign_c = -1 if np.isclose(np.sum(norm_c + norm_s), 0) else 1
lmbda_c = sign_c * dist_c / dist_s
d = D - A
dist_d = np.linalg.norm(d)
if np.isclose(dist_d, 0):
lmbda_d = 0
else:
norm_d = d / dist_d
sign_d = -1 if np.isclose(np.sum(norm_d + norm_s), 0) else 1
lmbda_d = sign_d * dist_d / dist_s
indicator = np.zeros(4)
direction_cd = lmbda_d - lmbda_c
smaller = min(lmbda_c, lmbda_d)
larger = max(lmbda_c, lmbda_d)
pnt_list = np.array([A,B,C,D])
if lmbda_c < 1 and lmbda_c > 0:
indicator[2] = 1
if lmbda_d < 1 and lmbda_d > 0:
indicator[3] = 1
if 0 <larger and 0 > smaller:
indicator[0] = 1
if 1 < larger and 1 > smaller:
indicator[1] = 1
return np.where(indicator == 1)[0], np.unique(pnt_list[np.where(indicator == 1)[0]], axis=0)

Loading

0 comments on commit 4514e40

Please sign in to comment.