def Volume(self): areas = [c.Area() for c in self.contours2D] # Maximum area is main surface, others cut into it sic = list(npy.argsort(areas))[::-1] # sorted indices of contours p1 = self.axis_point.PlaneProjection3D(self.plane_origin, self.x, self.y) if self.axis_point.PointDistance(p1) != 0: raise NotImplementedError p1_2D = p1.To2D(self.axis_point, self.x, self.y) p2_3D = self.axis_point + volmdlr.Point3D(self.axis.vector) p2 = p2_3D.PlaneProjection3D(self.plane_origin, self.x, self.y) if p2_3D.PointDistance(p2) != 0: raise NotImplementedError p2_2D = p2_3D.To2D(self.plane_origin, self.x, self.y) axis_2D = volmdlr.Line2D(p1_2D, p2_2D) com = self.contours2D[sic[0]].CenterOfMass() rg = axis_2D.PointDistance(com) volume = areas[sic[0]] * rg for i in sic[1:]: com = self.contours2D[i].CenterOfMass() rg = axis_2D.PointDistance(com) volume -= areas[i] * rg return self.angle * volume
angle = i * 2 * math.pi / n_balls center_ball = center_ball1.Rotation(center, x, angle, True) # print(center_ball.vector) primitives.append( primitives3D.Sphere(center_ball, D_balls / 2, 'Ball{}'.format(i + 1))) # inner pi1 = vm.Point2D((-B / 2, d / 2)) pi2 = vm.Point2D((-B / 2, d1 / 2)) pi3 = vm.Point2D((-0.5 * D_balls * math.sin(theta_b), d1 / 2)) pi4 = vm.Point2D((0, y_ball0 - D_balls / 2)) pi5 = vm.Point2D((0.5 * D_balls * math.sin(theta_b), d1 / 2)) pi6 = vm.Point2D((B / 2, d1 / 2)) pi7 = vm.Point2D((B / 2, d / 2)) li1 = vm.Line2D(pi1, pi2) li2 = vm.Line2D(pi2, pi3) ci3 = vm.Arc2D(pi3, pi4, pi5) li4 = vm.Line2D(pi5, pi6) li5 = vm.Line2D(pi6, pi7) li6 = vm.Line2D(pi7, pi1) ci = vm.Contour2D([li1, li2, ci3, li4, li5, li6]) inner = primitives3D.RevolvedProfile(center, x, y, [ci], center, x, math.pi * 2, 'innerring') primitives.append(inner) # outter po1 = vm.Point2D((-B / 2, D / 2)) po2 = vm.Point2D((-B / 2, D1 / 2)) po3 = vm.Point2D((-0.5 * D_balls * math.sin(theta_b), D1 / 2))
""" Distance to lines and projection debug """ import numpy as npy import volmdlr as vm p1 = vm.Point2D(2*npy.random.random(2)-1) p2 = vm.Point2D(2*npy.random.random(2)-1) line = vm.Line2D(p1, p2) line_segment = vm.LineSegment2D(p1, p2) for i in range(100): point = vm.Point2D(4*npy.random.random(2)-2) point_projection_line = line.PointProjection(point) point_projection_line_segment = line_segment.PointProjection(point) assert point_projection_line.PointDistance(point) == line.PointDistance(point) assert point_projection_line_segment.PointDistance(point) == line_segment.PointDistance(point) #fig, ax = line.MPLPlot() #point.MPLPlot(ax=ax)
def OffsetLines(self, line_indexes, offset): """ line_indexes is a list of consecutive line indexes These line should all be aligned line_indexes = 0 being the 1st line if self.close last line_index can be len(self.points)-1 if not, last line_index can be len(self.points)-2 """ new_linesegment2D_points = [] # ============================================================================= # COMPUTES THE DIRECTIVE VECTORS BETWEEN WHICH THE OFFSET WILL BE DRAWN # ============================================================================= dir_vec_1 = None dir_vec_2 = None if line_indexes[0] == 0 and not self.closed: pass else: dir_vec_1 = volmdlr.Vector2D((self.points[line_indexes[0]] - self.points[line_indexes[0]-1])) if line_indexes[-1] == len(self.points)-(2-self.closed): if not self.closed: pass else: dir_vec_2 = volmdlr.Vector2D((self.points[0] - self.points[1])) elif self.closed and line_indexes[-1] == len(self.points)-2: dir_vec_2 = volmdlr.Vector2D((self.points[line_indexes[-1]+1] - self.points[0])) else: dir_vec_2 = volmdlr.Vector2D((self.points[line_indexes[-1]+1] - self.points[line_indexes[-1]+2])) if dir_vec_1 is None: dir_vec_1 = dir_vec_2 if dir_vec_2 is None: dir_vec_2 = dir_vec_1 dir_vec_1.Normalize() dir_vec_2.Normalize() # ============================================================================= # COMPUTES THE ANGLE BETWEEN THE NORMAL VECTOR OF THE SURFACE TO OFFSET AND # THE DIRETIVE VECTOR IN ORDER TO SET THE NEW POINT AT THE RIGHT DISTANCE # ============================================================================= normal_vectors = [] for index in line_indexes: if index == len(self.points)-1: normal_vectors.append(volmdlr.Vector2D(self.points[0]-self.points[index]).NormalVector(unit=True)) else: normal_vectors.append(volmdlr.Vector2D(self.points[index+1]-self.points[index]).NormalVector(unit=True)) dot1 = dir_vec_1.Dot(normal_vectors[0]) dot2 = dir_vec_2.Dot(normal_vectors[-1]) if math.isclose(dot1, 0, abs_tol=1e-9): # call function considering the line before, because the latter and # the first offset segment are parallel return self.OffsetLines([line_indexes[0]-1]+line_indexes, offset) if math.isclose(dot2, 0, abs_tol=1e-9): # call function considering the line after, because the latter and # the last offset segment are parallel return self.OffsetLines(line_indexes+[line_indexes[-1]+1], offset) distance_dir1 = offset / dot1 distance_dir2 = offset / dot2 if len(line_indexes) > 1: intersection = volmdlr.Point2D.LinesIntersection(volmdlr.Line2D(self.points[line_indexes[0]], self.points[line_indexes[0]]+dir_vec_1), volmdlr.Line2D(self.points[line_indexes[-1]+1], self.points[line_indexes[-1]+1]+dir_vec_2)) vec1 = intersection.PointDistance(self.points[line_indexes[0]]) * dir_vec_1 vec2 = intersection.PointDistance(self.points[line_indexes[-1]+1]) * dir_vec_2 # ============================================================================= # COMPUTES THE NEW POINTS AFTER THE OFFSET # ============================================================================= new_points = {} new_points[line_indexes[0]] = self.points[line_indexes[0]] + distance_dir1 * dir_vec_1 for nb, index in enumerate(line_indexes[1:]): coeff_vec_2 = volmdlr.Point2D.PointDistance(self.points[line_indexes[0]], self.points[index]) / volmdlr.Point2D.PointDistance(self.points[line_indexes[0]], self.points[line_indexes[-1]+1]) coeff_vec_1 = 1 - coeff_vec_2 if dir_vec_1.Dot(normal_vectors[nb+1]) < 0: coeff_vec_1 = - coeff_vec_1 if dir_vec_2.Dot(normal_vectors[nb+1]) < 0: coeff_vec_2 = - coeff_vec_2 index_dir_vector = coeff_vec_1 * vec1 + coeff_vec_2 * vec2 index_dot = index_dir_vector.Dot(normal_vectors[nb+1]) index_distance_dir = offset / index_dot new_points[index] = self.points[index] + index_distance_dir * index_dir_vector if self.closed and line_indexes[-1] == len(self.points)-1: new_points[0] = self.points[0] + distance_dir2 * dir_vec_2 else: new_points[line_indexes[-1]+1] = self.points[line_indexes[-1]+1] + distance_dir2 * dir_vec_2 # ============================================================================= # CREATE THE NEW POINTS' LIST # ============================================================================= for i in range(len(self.points)): if i in new_points.keys(): new_linesegment2D_points.append(new_points[i]) else: new_linesegment2D_points.append(self.points[i]) rls2D = RoundedLineSegments2D(new_linesegment2D_points, self.radius, self.closed, adapt_radius=self.adapt_radius) return rls2D
def circle_1_point_2_segments(point, line1, line2): # point will be called I(x_I, y_I) # semgent1 will be [AB] # segment2 will be [CD] I = vm.Vector2D((point[0], point[1])) A = vm.Vector2D((line1.points[0][0], line1.points[0][1])) B = vm.Vector2D((line1.points[1][0], line1.points[1][1])) C = vm.Vector2D((line2.points[0][0], line2.points[0][1])) D = vm.Vector2D((line2.points[1][0], line2.points[1][1])) # CHANGEMENT DE REPAIRE new_u = vm.Vector2D((B-A)) new_u.Normalize() new_v = new_u.NormalVector(unit=True) new_basis = vm.Frame2D(I, new_u, new_v) new_A = new_basis.NewCoordinates(A) new_B = new_basis.NewCoordinates(B) new_C = new_basis.NewCoordinates(C) new_D = new_basis.NewCoordinates(D) # ============================================================================= # LES SEGMENTS DECRIVENT UNE SEULE ET MEME DROITE # => AUCUNE SOLUTION # ============================================================================= if new_C[1] == 0 and new_D[1] == 0: return None, None # ============================================================================= # LES SEGMENTS SONT PARALLELES # => 1 SOLUTION # ============================================================================= elif math.isclose(line1.DirectionVector(unit=True).Dot(line2.NormalVector(unit=True)), 0, abs_tol=1e-06): segments_distance = abs(new_C[1] - new_A[1]) r = segments_distance / 2 new_circle_center = vm.Point2D((0, r)) circle_center = new_basis.OldCoordinates(new_circle_center) circle = vm.Circle2D(circle_center, r) return circle, None # ============================================================================= # LES SEGMENTS SONT PERPENDICULAIRES # => 2 SOLUTIONS # ============================================================================= elif math.isclose(line1.DirectionVector(unit=True).Dot(line2.DirectionVector(unit=True)), 0, abs_tol=1e-06): line_AB = vm.Line2D(vm.Point2D(new_A), vm.Point2D(new_B)) line_CD = vm.Line2D(vm.Point2D(new_C), vm.Point2D(new_D)) new_pt_K = vm.Point2D.LinesIntersection(line_AB ,line_CD) r = abs(new_pt_K[0]) new_circle_center1 = vm.Point2D((0, r)) new_circle_center2 = vm.Point2D((0, -r)) circle_center1 = new_basis.OldCoordinates(new_circle_center1) circle_center2 = new_basis.OldCoordinates(new_circle_center2) circle1 = vm.Circle2D(circle_center1, r) circle2 = vm.Circle2D(circle_center2, r) return circle1, circle2 # ============================================================================= # LES SEGMENTS SONT QUELCONQUES # => 2 SOLUTIONS # ============================================================================= else: line_AB = vm.Line2D(vm.Point2D(new_A), vm.Point2D(new_B)) line_CD = vm.Line2D(vm.Point2D(new_C), vm.Point2D(new_D)) new_pt_K = vm.Point2D.LinesIntersection(line_AB ,line_CD) pt_K = vm.Point2D(new_basis.OldCoordinates(new_pt_K)) # CHANGEMENT DE REPERE: new_u2 = vm.Vector2D(pt_K-I) new_u2.Normalize() new_v2 = new_u2.NormalVector(unit=True) new_basis2 = vm.Frame2D(I, new_u2, new_v2) new_A = new_basis2.NewCoordinates(A) new_B = new_basis2.NewCoordinates(B) new_C = new_basis2.NewCoordinates(C) new_D = new_basis2.NewCoordinates(D) new_pt_K = new_basis2.NewCoordinates(pt_K) teta1 = math.atan2(new_C[1], new_C[0] - new_pt_K[0]) teta2 = math.atan2(new_D[1], new_D[0] - new_pt_K[0]) if teta1 < 0: teta1 += math.pi if teta2 < 0: teta2 += math.pi if not math.isclose(teta1, teta2, abs_tol=1e-08): if math.isclose(teta1, math.pi, abs_tol=1e-08) or math.isclose(teta1, 0., abs_tol=1e-08): teta = teta2 elif math.isclose(teta2, math.pi, abs_tol=1e-08) or math.isclose(teta2, 0., abs_tol=1e-08): teta = teta1 else: teta = teta1 r1 = new_pt_K[0] * math.sin(teta) / (1 + math.cos(teta)) r2 = new_pt_K[0] * math.sin(teta) / (1 - math.cos(teta)) new_circle_center1 = vm.Point2D((0, -r1)) new_circle_center2 = vm.Point2D((0, r2)) circle_center1 = new_basis2.OldCoordinates(new_circle_center1) circle_center2 = new_basis2.OldCoordinates(new_circle_center2) if new_basis.NewCoordinates(circle_center1)[1] > 0: circle1 = vm.Circle2D(circle_center1, r1) circle2 = vm.Circle2D(circle_center2, r2) else: circle1 = vm.Circle2D(circle_center2, r2) circle2 = vm.Circle2D(circle_center1, r1) return circle1, circle2
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Wed Mar 8 10:58:19 2017 @author: steven """ import volmdlr as vm p1 = vm.Point2D((1,1.45)) p2 = vm.Point2D((0.4,0.1)) l1 = vm.Line2D(p1, p2) p3 = vm.Point2D((-1,0)) p4 = vm.Point2D((1,-0.5)) l2 = vm.Line2D(p3, p4) p5,bl1,bl2 = vm.Point2D.LinesIntersection(l1, l2,True) p6=vm.Point2D.MiddlePoint(p1,p3) p7=vm.Point2D.LineProjection(p6, l1) p8=vm.Point2D.LineProjection(p6, l2) c=vm.CompositePrimitive2D([l1, l2, p5, p6, p7 ,p8]) c.MPLPlot()