def main(context, vaxis, gpAxis): axisdict = {"X": 0, "Y": 1, "Z": 2} mesh = bpy.context.object bm = bmesh.from_edit_mesh(mesh.data) axis = axisdict[vaxis] gpaxis = axisdict[gpAxis] for vertice in bm.verts: if vertice.select: imen = -1000 imay = 1000 punto = vertice.co + mesh.location jj = [ point.co for point in bpy.context.scene.grease_pencil.layers. active.frames[0].strokes[0].points ] for point in bpy.context.scene.grease_pencil.layers.active.frames[ 0].strokes[-1].points: if point.co[gpaxis] < punto[gpaxis] and point.co[gpaxis] > imen: imen = point.co[gpaxis] men = point.co if point.co[gpaxis] > punto[gpaxis] and point.co[gpaxis] < imay: imay = point.co[gpaxis] may = point.co try: may men except: print("wrong projection axis!") break if axis == 0: try: vertice.co = (intersect_line_line( men, may, punto, (punto[0] + 1, punto[1], punto[2]))[0][0] - mesh.location[0], vertice.co.y, vertice.co.z) except: pass if axis == 1: try: vertice.co = (vertice.co.x, intersect_line_line(men, may, punto, (punto[0], punto[1] + 1, punto[2]))[0][1] - mesh.location[1], vertice.co.z) except: pass if axis == 2: try: vertice.co = (vertice.co.x, vertice.co.y, intersect_line_line(men, may, punto, (punto[0], punto[1], punto[2] + 1))[0][2] - mesh.location[2]) except: pass bmesh.update_edit_mesh(mesh.data)
def main(context, vaxis, gpAxis): axisdict = {"X": 0, "Y": 1, "Z": 2} mesh = bpy.context.object bm = bmesh.from_edit_mesh(mesh.data) axis = axisdict[vaxis] gpaxis = axisdict[gpAxis] for vertice in bm.verts: if vertice.select: imen = -1000 imay = 1000 punto = vertice.co + mesh.location jj = [point.co for point in bpy.context.object.grease_pencil.layers.active.frames[0].strokes[0].points] for point in bpy.context.object.grease_pencil.layers.active.frames[0].strokes[-1].points: if point.co[gpaxis] < punto[gpaxis] and point.co[gpaxis] > imen: imen = point.co[gpaxis] men = point.co if point.co[gpaxis] > punto[gpaxis] and point.co[gpaxis] < imay: imay = point.co[gpaxis] may = point.co try: may men except: print("wrong projection axis!") break if axis == 0: try: vertice.co = ( intersect_line_line(men, may, punto, (punto[0] + 1, punto[1], punto[2]))[0][0] - mesh.location[0], vertice.co.y, vertice.co.z, ) except: pass if axis == 1: try: vertice.co = ( vertice.co.x, intersect_line_line(men, may, punto, (punto[0], punto[1] + 1, punto[2]))[0][1] - mesh.location[1], vertice.co.z, ) except: pass if axis == 2: try: vertice.co = ( vertice.co.x, vertice.co.y, intersect_line_line(men, may, punto, (punto[0], punto[1], punto[2] + 1))[0][2] - mesh.location[2], ) except: pass bmesh.update_edit_mesh(mesh.data)
def make_corner_straight(bm, verts, p1, p2): v1 = verts[0] v2 = verts[1] face = get_face_with_verts(verts) if face is not None and len(face.edges) == 6: done = False loop_a = None loop_b = None for vert in verts: face_loops = get_face_loops_for_vert(vert, face) for loop in face_loops: if loop.vert in verts: loop_a = loop if loop.link_loop_next.link_loop_next.vert in verts: loop_b = loop.link_loop_next done = True break if done: break if loop_a is not None and loop_b is not None: edge_a = loop_a.link_loop_prev.link_loop_prev.edge edge_b = loop_b.link_loop_next.link_loop_next.edge isect_point = intersect_line_line(p1, p2, edge_b.verts[0].co, edge_b.verts[1].co) if isect_point is not None: isect_point = isect_point[0] else: isect_point = intersect_line_line( p1, p2, edge_a.verts[0].co, edge_a.verts[1].co)[0] center_vert_co, _ = intersect_point_line( v2.co, isect_point, v1.co) #p1.lerp(p2, 0.5) # Make the corner geometry center_vert: BMVert = bm.verts.new( center_vert_co ) #bmesh.ops.create_vert(bm, co=center_vert_co)["vert"][0] connect_vert = get_vertex_shared_by_edges([edge_a, edge_b]) new_edge_a = bm.edges.new([verts[0], center_vert]) new_edge_b = bm.edges.new([verts[1], center_vert]) new_edge_c = bm.edges.new([center_vert, connect_vert]) bmesh.utils.face_split_edgenet( face, [new_edge_a, new_edge_b, new_edge_c]) bm.faces.ensure_lookup_table() bm.edges.ensure_lookup_table() bm.verts.ensure_lookup_table()
def main(context): shape_ob = context.active_object sel_spl = [spl for spl in get_selected_bezier_splines(shape_ob) if not spl.use_cyclic_u] if sel_spl == None or len(sel_spl) == 0 or len(sel_spl) > 2: print ("wrong selection") return # case of one endpoint selected if len(sel_spl) == 1: sel_pts = selected_endpoints(sel_spl[0]) if len(sel_pts) == 2: p1, p1_handle = sel_pts p1_extend = get_max_extent_2d(p1, p1_handle, get_shape_bounds(shape_ob)) p2 = nearest_point(p1, get_intersections(p1, p1_extend, shape_ob)) # case of two endpoints selected on the same spline elif len(sel_pts) == 4: p2 = intersect_line_line(sel_pts[1], sel_pts[0], sel_pts[3], sel_pts[2])[0] else: print ("wrong selection") return # case of two endpoints selected on seperate splines if len(sel_spl) == 2: sel_pts = selected_endpoints(sel_spl[0]) + selected_endpoints(sel_spl[1]) p2 = intersect_line_line(sel_pts[1], sel_pts[0], sel_pts[3], sel_pts[2])[0] # add point to spline(s) if p2 == None: print ("no extension found") else: print ("extended point found on: ", p2) if len(sel_spl) == 1: if len(sel_pts) == 2: bpy.ops.curve.handle_type_set(type='ALIGNED') bpy.ops.curve.vertex_add(location=(p2.to_3d()+bpy.context.object.location)) bpy.ops.curve.handle_type_set(type='AUTOMATIC') elif len(sel_pts) == 4: bpy.ops.curve.handle_type_set(type='ALIGNED') bpy.ops.curve.vertex_add() sel_spl[0].bezier_points[0].co = p2.to_3d() sel_spl[0].bezier_points[-1].co = p2.to_3d() bpy.ops.curve.handle_type_set(type='AUTOMATIC') elif len(sel_spl) == 2: bpy.ops.curve.handle_type_set(type='ALIGNED') bpy.ops.curve.vertex_add() if sel_spl[0].bezier_points[0].select_control_point: sel_spl[0].bezier_points[0].co = p2.to_3d() else: sel_spl[0].bezier_points[-1].co = p2.to_3d() if sel_spl[1].bezier_points[0].select_control_point: sel_spl[1].bezier_points[0].co = p2.to_3d() else: sel_spl[1].bezier_points[-1].co = p2.to_3d() bpy.ops.curve.handle_type_set(type='AUTOMATIC')
def generate_3PT_mode_1(pts, obj, nv): origin = obj.location mw = obj.matrix_world V = Vector nv = max(3, nv) # construction v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2]) edge1_mid = v1.lerp(v2, 0.5) edge2_mid = v3.lerp(v4, 0.5) axis = geometry.normal(v1, v2, v4) mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis) # triangle edges v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid r = geometry.intersect_line_line(v1_, v2_, v3_, v4_) if r: p1, _ = r cp = mw * p1 bpy.context.scene.cursor_location = cp layer = get_layer() generate_gp3d_stroke(layer, p1, v1, axis, mw, origin, nv) else: print('not on a circle')
def sectEdges(self, context): obj = bpy.context.object if obj.mode != 'EDIT': self.report({"INFO"}, "Works in edit mode only") return me = obj.data bm = bmesh.from_edit_mesh(me) edges = [e for e in bm.edges if e.select] if len(edges) != 2: self.report({"INFO"}, "Select exactly two edges") return mytool = context.scene.my_tool [[v1, v2], [v3, v4]] = [[v.co for v in e.verts] for e in edges] if v1 == v3 or v1 == v4 or v2 == v3 or v2 == v4: self.report({"INFO"}, "Edges are not independent") return iv = geometry.intersect_line_line(v1, v2, v3, v4) if not iv: self.report({"INFO"}, "Edges do not intersect") return iv = (iv[0] + iv[1]) / 2 if not pointOnEdge(iv, v1, v2) or not pointOnEdge(iv, v3, v4): self.report({"WARNING"}, "Intersection not on edges") if mytool.delFaces: vn = bm.verts.new(iv) for e in edges: bm.edges.new((e.verts[0], vn)) bm.edges.new((e.verts[1], vn)) bm.edges.remove(e) bmesh.update_edit_mesh(me) elif mytool.keepFaces: fac = (iv - v1).length / (v2 - v1).length ev1 = bmesh.utils.edge_split(edges[0], edges[0].verts[0], fac) fac = (iv - v3).length / (v4 - v3).length ev2 = bmesh.utils.edge_split(edges[1], edges[1].verts[0], fac) bmesh.ops.pointmerge(bm, verts=(ev1[1], ev2[1]), merge_co=iv) bmesh.update_edit_mesh(me) elif mytool.addVertex: bm.verts.new(iv) bmesh.update_edit_mesh(me) if mytool.setCursor: context.scene.cursor.location = obj.matrix_world @ iv
def xsect_spline(sp_a, sp_b, _hubs, precision): pt_a_prev = pt_b_prev = None EPS_SPLINE = min(sp_a.length, sp_b.length) / precision pt_a_prev = sp_a.points[0] for a, pt_a in enumerate(sp_a.points[1:]): pt_b_prev = sp_b.points[0] for b, pt_b in enumerate(sp_b.points[1:]): # Now we have 2 edges # print(pt_a, pt_a_prev, pt_b, pt_b_prev) xsect = intersect_line_line(pt_a, pt_a_prev, pt_b, pt_b_prev) if xsect is not None: if (xsect[0] - xsect[1]).length <= EPS_SPLINE: f = intersect_point_line(xsect[1], pt_a, pt_a_prev)[1] # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE: # for some reason doesnt work so well, same below if f >= 0.0 and f <= 1.0: f = intersect_point_line(xsect[0], pt_b, pt_b_prev)[1] # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE: if f >= 0.0 and f <= 1.0: # This wont happen often co = xsect[0].lerp(xsect[1], 0.5) hub = get_hub(co, _hubs, EPS_SPLINE) sp_a.hubs.append((a, hub)) sp_b.hubs.append((b, hub)) pt_b_prev = pt_b pt_a_prev = pt_a
def execute(self, context): BlenderFake.forceUpdate() obj = bpy.context.active_object mat = obj.matrix_world se = [e for e in obj.data.edges if (e.select == 1)] e1v1 = obj.data.vertices[se[0].vertices[0]].co e1v2 = obj.data.vertices[se[0].vertices[1]].co e2v1 = obj.data.vertices[se[1].vertices[0]].co e2v2 = obj.data.vertices[se[1].vertices[1]].co qq = geometry.intersect_line_line (e1v1, e1v2, e2v1, e2v2) q = None if len(qq)==0: #print ("lx 0") return {'CANCELLED'} if len(qq)==1: #print ("lx 1") q = qq[0] if len(qq)==2: cc = context.scene.cursor_control cc.cycleLinexCoice(2) q = qq[cc.linexChoice] #q = geometry.intersect_line_line (e1v1, e1v2, e2v1, e2v2)[qc] * mat #i2 = geometry.intersect_line_line (e2v1, e2v2, e1v1, e1v2)[0] * mat cc.setCursor(mat*q) return {'FINISHED'}
def intersect_line_line(v1, v2, v3, v4, threshold=1e-6): """三次元での直線同士の交差判定。平行だった場合、中間地点を求める。 二次元が与えられたら三次元に拡張する。 parallel_threshold: 平行であるとする閾値 """ v1 = v1.to_3d() v2 = v2.to_3d() v3 = v3.to_3d() v4 = v4.to_3d() vec1 = v2 - v1 vec2 = v4 - v3 # 両方点 if vec1.length == 0.0 and vec2.length == 0.0: return None # v1-v2が直線、v3-v4が点 elif vec2.length == 0.0: return (v3 - v1).project(vec1) + v1, v3 # v1-v2が点、v3-v4が直線 elif vec1.length == 0.0: return v1, (v1 - v3).project(vec2) + v3 # 平行 elif vec1.normalized().cross(v3 - v1).length < threshold and \ vec1.normalized().cross(v4 - v1).length < threshold: d1 = vec1.dot(v3 - v1) d2 = vec1.dot(v4 - v1) if d1 > d2: d1, d2 = d2, d1 v3, v4 = v4, v3 vec2.negate() # v3,v4が両方v1側 or v3がv1側, v4がv1-v2間 if d2 <= 0 or (d1 <= 0 and 0 <= d2 <= vec1.length): mid = (v1 + v4) / 2 # v3,v4が両方v2側 or v3がv1-v2間, v4がv2側 elif d1 >= vec1.length or \ (0 <= d1 <= vec1.length and d2 >= vec1.length): mid = (v2 + v3) / 2 # v3,v4がv1-v2間 elif 0 <= d1 <= vec1.length and 0 <= d2 <= vec1.length: mid = (v2 + v3) / 2 # v1,v2がv3-v4間 else: mid = (v1 + v4) / 2 isect1 = (mid - v1).project(vec1) + v1 isect2 = (mid - v3).project(vec2) + v3 return isect1, isect2 else: result = geom.intersect_line_line(v1, v2, v3, v4) if result is not None: # isect1, isect2 = result # if not math.isnan(isect1[0]) and not math.isnan(isect2[0]): # return isect1, isect2 return result return None
def closest_extrude_Point(self, p2D : Point2D) -> Point: r = self.drawing.Point2D_to_Ray(p2D) p,_ = intersect_line_line( self.extrude_pt0, self.extrude_pt1, r.o, r.o + r.d, ) return Point(p)
def angleEnlarge(c0, c1, c2, w): try: t = w[0] # variable width except: w = [w, w] # uniform offset c0 = Vector(c0) c1 = Vector(c1) c2 = Vector(c2) v0 = c1 - c0 v1 = c2 - c1 sz, rot = readVec(v0) b = writeVec(w[0], rot - 90) b = b + c0 c = b + v0 sz, rot = readVec(v1) d = writeVec(w[1], rot - 90) d = d + c1 e = d + v1 # TODO line_line always returns a tuple (never a None like line_2d) interlist = geometry.intersect_line_line(b, c, d, e) print(interlist) if type(interlist) != type(None): return interlist[0] else: return c
def execute(self, context): BlenderFake.forceUpdate() obj = bpy.context.active_object mat = obj.matrix_world se = [e for e in obj.data.edges if (e.select == 1)] e1v1 = obj.data.vertices[se[0].vertices[0]].co e1v2 = obj.data.vertices[se[0].vertices[1]].co e2v1 = obj.data.vertices[se[1].vertices[0]].co e2v2 = obj.data.vertices[se[1].vertices[1]].co qq = geometry.intersect_line_line(e1v1, e1v2, e2v1, e2v2) q = None if len(qq) == 0: #print ("lx 0") return {'CANCELLED'} if len(qq) == 1: #print ("lx 1") q = qq[0] if len(qq) == 2: cc = context.scene.cursor_control cc.cycleLinexCoice(2) q = qq[cc.linexChoice] #q = geometry.intersect_line_line (e1v1, e1v2, e2v1, e2v2)[qc] * mat #i2 = geometry.intersect_line_line (e2v1, e2v2, e1v1, e1v2)[0] * mat cc.setCursor(mat * q) return {'FINISHED'}
def generate_3PT_mode_1_(pts, obj): origin = obj.location transform_matrix = obj.matrix_local V = Vector # construction v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2]) edge1_mid = v1.lerp(v2, 0.5) edge2_mid = v3.lerp(v4, 0.5) axis = geometry.normal(v1, v2, v4) mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis) # triangle edges v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid r = geometry.intersect_line_line(v1_, v2_, v3_, v4_) if r: p1, _ = r # cp = transform_matrix * (p1 + origin) cp = transform_matrix * p1 bpy.context.scene.cursor_location = cp # generate_gp3d_stroke(cp, axis, obj, radius=(p1-v1).length) else: print('not on a circle')
def solve_curvature(p1, p2, n1, n2, fac, fallback): """ Add a nice circular curvature on """ from mathutils.geometry import (intersect_line_line, ) p1_a = p1 + n1 p2_a = p2 - n2 isect = intersect_line_line(p1, p1_a, p2, p2_a, ) if isect: corner = isect[0].lerp(isect[1], 0.5) else: corner = None if corner: p1_first_order = p1.lerp(corner, fac) p2_first_order = corner.lerp(p2, fac) co = p1_first_order.lerp(p2_first_order, fac) return co else: # cant interpolate. just return interpolated value return fallback.copy() # p1.lerp(p2, fac)
def get_new_position(position_vectors, source): source_points = np.array(source.points) x_min = np.min(source_points[:, 0]) x_max = np.max(source_points[:, 0]) y_min = np.min(source_points[:, 1]) y_max = np.max(source_points[:, 1]) z_min = np.min(source_points[:, 2]) z_max = np.max(source_points[:, 2]) source_center = np.array(source.get_center()) my_source_center = np.array([x_min + (x_max - x_min) / 2, y_min + (y_max - y_min) / 2, z_min + (z_max - z_min) / 2]) shift2mycenter = np.subtract(source_center, my_source_center) print('my_source_center: {}'.format(my_source_center)) print('diff from source of: {}'.format(shift2mycenter)) points = [] for i, line0 in enumerate(position_vectors[:-1]): for line1 in position_vectors[i+1:]: p0, p1 = intersect_line_line(line0[0], line0[1], line1[0], line1[1]) p0 = np.array(p0) p1 = np.array(p1) center_point = p0 + (np.subtract(p1, p0)/2) points.append(center_point) points = np.array(points) position = np.mean(points, axis=0) position = position+shift2mycenter return position
def getIntersection(pointsLeft, pointsRight): pL = np.array(pointsLeft) pR = np.array(pointsRight) camCenterRight = np.transpose(camWorldCenterRight)[0] camCenterLeft = np.transpose(camWorldCenterLeft)[0] # calcul du point sur l'object en applicant la pseudo-inverse de la camera sur le point trouvé plus-haut leftObject = (np.linalg.pinv(camLeft) @ pL) rightObject = (np.linalg.pinv(camRight) @ pR) # conversion des np.array en mathutils.Vector pour l'utilisation de la methode d'intersection leftEndVec = arrayToVector(leftObject) rightEndVec = arrayToVector(rightObject) leftStartVec = arrayToVector(camCenterLeft) rightStartVec = arrayToVector(camCenterRight) # affichage des lignes reliant centre à point objet ''' draw3DLine(camCenterLeft,leftObject) draw3DLine(camCenterRight,rightObject) plt.show() ''' # utilisation de mathutils.geometry.intersect_line_line pour trouver l'intersection des lingnes passant par les 2 # points. return pygeo.intersect_line_line(leftStartVec, leftEndVec, rightStartVec, rightEndVec)
def generate_3PT(pts, obj, nv, mode=1): mw = obj.matrix_world V = Vector nv = max(3, nv) # construction v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2]) edge1_mid = v1.lerp(v2, 0.5) edge2_mid = v3.lerp(v4, 0.5) axis = geometry.normal(v1, v2, v4) mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis) # triangle edges v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid r = geometry.intersect_line_line(v1_, v2_, v3_, v4_) if r: p1, _ = r cp = mw * p1 bpy.context.scene.cursor_location = cp if mode == 0: pass elif mode == 1: generate_bmesh_repr(p1, v1, axis, nv) else: print('not on a circle')
def solve_curvature(p1, p2, n1, n2, fac, fallback): """ Add a nice circular curvature on """ from mathutils.geometry import ( intersect_line_line, ) p1_a = p1 + n1 p2_a = p2 - n2 isect = intersect_line_line( p1, p1_a, p2, p2_a, ) if isect: corner = isect[0].lerp(isect[1], 0.5) else: corner = None if corner: p1_first_order = p1.lerp(corner, fac) p2_first_order = corner.lerp(p2, fac) co = p1_first_order.lerp(p2_first_order, fac) return co else: # cant interpolate. just return interpolated value return fallback.copy() # p1.lerp(p2, fac)
def get_ideal_position(empty_name): # Set Maximum Distance max_distance = 1000 # Get Empty Positions main_c = camera_position_array[empty_name + '.R'] sub_c = camera_position_array[empty_name + '.L'] # Vector to Target Point From Camera target_vector = (sub_c - camera_position ).normalized() * max_distance # Get Line A = get_mirrored_vector(camera_position, empty_position, normal) B = get_mirrored_vector( camera_position + (main_c - camera_position).normalized() * max_distance, empty_position, normal) # Calculate Intersection intersection = intersect_line_line( camera_position, target_vector, A, B) mirrored_intersection = get_mirrored_vector( Vector(intersection[1]), empty_position, normal) # Here, You have to get position on the screen insect = intersect_line_plane( camera_position, Vector(intersection[1]), Vector((0, -8 + distance, 0)), Vector((0, 1, 0))) # If it's not intersecting, just return ridiculous value if (insect is None): insect = Vector((100, 100, 100)) return mirrored_intersection, (insect - sub_c).length
def get_slide_vector_intersection(self, context): view_origin = region_2d_to_origin_3d(context.region, context.region_data, self.mousepos) view_dir = region_2d_to_vector_3d(context.region, context.region_data, self.mousepos) i = intersect_line_line(view_origin, view_origin + view_dir, self.origin, self.target_avg) return i[1]
def slide_snap(self, context, hitobj, hitlocation, hitindex): ''' slide snap to edges of all edit mode objects ''' # get hitface from the cached bmesh hitbm = self.snap_bms[hitobj.name] hitface = hitbm.faces[hitindex] # hit location in hitobj's local space hitmx = hitobj.matrix_world hit = hitmx.inverted() @ hitlocation # get closest edge edge = min([(e, (hit - intersect_point_line(hit, e.verts[0].co, e.verts[1].co)[0]).length, (hit - get_center_between_verts(*e.verts)).length) for e in hitface.edges], key=lambda x: (x[1] * x[2]) / x[0].calc_length())[0] # set snap coords for view3d drawing self.snap_coords = [hitmx @ v.co for v in edge.verts] # get snap coords in active's local space snap_coords = [self.mx.inverted_safe() @ co for co in self.snap_coords] # init proximity and ortho coords for view3d drawing self.snap_proximity_coords = [] self.snap_ortho_coords = [] # get intersection of individual slide dirs and snap coords for v, data in self.verts.items(): init_co = data['co'] target = data['target'] snap_dir = (snap_coords[0] - snap_coords[1]).normalized() slide_dir = (init_co - target.co).normalized() # check for parallel and almost parallel snap edges, do nothing in this case if abs(slide_dir.dot(snap_dir)) > 0.999: v.co = init_co # with a smaller dot product, interseect_line_line will produce a guaranteed hit else: i = intersect_line_line(init_co, target.co, *snap_coords) v.co = i[1 if self.is_diverging else 0] if i else init_co # add coords to draw the slide 'edges' if v.co != target.co: self.coords.extend([v.co, target.co]) # add proximity coords if i[1] != snap_coords[0]: self.snap_proximity_coords.extend([i[1], snap_coords[0]]) # add ortho coords if v.co != i[1]: self.snap_ortho_coords.extend([v.co, i[1]]) self.bm.normal_update() bmesh.update_edit_mesh(self.active.data)
def __init__(self, wall, o): self.wall = wall self.o = o # get neighbor EMPTYs for <o> o2 = wall.getCornerEmpty(o) self.o2 = o2 o1 = wall.getPrevious(o2) self.o1 = o1 context = wall.context # temporarily remove drivers for the segment EMPTY object o.driver_remove("location") # get neighbor EMPTYs for <o1> and <o2> e1 = wall.getPrevious(o1) attached1 = None if e1 else wall.getReferencesForAttached(o1) self.attached1 = attached1 e2 = wall.getNext(o2) attached2 = None if e2 else wall.getReferencesForAttached(o2) self.attached2 = attached2 # vectors if e1: v1 = o1.location - e1.location elif attached1: v1 = attached1[1].location - attached1[0].location if e2: v2 = e2.location - o2.location elif attached2: v2 = attached2[1].location - attached2[0].location p = None if (e1 or attached1) and (e2 or attached2): # check if v1 and v2 are parallel if v1.normalized().cross(v2.normalized()).length < zero2: # orient <o> along v1, which gives the same effect as orienting <o> along v2 dy, dx = v1.y, v1.x else: # point where the lines defined by v1 and v2 intersect l1 = (e1, o1) if e1 else attached1 l2 = (o2, e2) if e2 else attached2 p = intersect_line_line(l1[0].location, l1[1].location, l2[0].location, l2[1].location)[0] # orient <o> along the line defined by <o> and <p> dy, dx = o.location.y - p.y, o.location.x - p.x elif e1 or attached1 or e2 or attached2: _v = v1 if e1 or attached1 else v2 # orient <o> along <_v> dy, dx = _v.y, _v.x else: # orient <o> along the normal to the wall segment defined by <o> dy, dx = o1.location.x - o2.location.x, o2.location.y - o1.location.y o.rotation_euler[2] = math.atan2(dy, dx) context.scene.update() # adding drivers for o1 and o2 addMoverDrivers(o1, o, p) addMoverDrivers(o2, o, p) makeActiveSelected(context, o)
def orthoCenter(cls, fv): try: h0 = G3.closestP2L(fv[0], fv[1], fv[2]) h1 = G3.closestP2L(fv[1], fv[0], fv[2]) #h2 = G3.closestP2L(fm[2], fm[0], fm[1]) return geometry.intersect_line_line(fv[0], h0, fv[1], h1)[0] except (RuntimeError, TypeError): return None
def orthoCenter(cls, fv): try: h0 = G3.closestP2L(fv[0], fv[1], fv[2]) h1 = G3.closestP2L(fv[1], fv[0], fv[2]) #h2 = G3.closestP2L(fm[2], fm[0], fm[1]) return geometry.intersect_line_line (fv[0], h0, fv[1], h1)[0] except(RuntimeError, TypeError): return None
def __init__(self, wall, o): self.wall = wall self.o = o # get neighbor EMPTYs for <o> o2 = wall.getCornerEmpty(o) self.o2 = o2 o1 = wall.getPrevious(o2) self.o1 = o1 context = wall.context # temporarily remove drivers for the segment EMPTY object o.driver_remove("location") # get neighbor EMPTYs for <o1> and <o2> e1 = wall.getPrevious(o1) attached1 = None if e1 else wall.getReferencesForAttached(o1) self.attached1 = attached1 e2 = wall.getNext(o2) attached2 = None if e2 else wall.getReferencesForAttached(o2) self.attached2 = attached2 # vectors if e1: v1 = o1.location - e1.location elif attached1: v1 = attached1[1].location - attached1[0].location if e2: v2 = e2.location - o2.location elif attached2: v2 = attached2[1].location - attached2[0].location p = None if (e1 or attached1) and (e2 or attached2): # check if v1 and v2 are parallel if v1.normalized().cross(v2.normalized()).length < zero2: # orient <o> along v1, which gives the same effect as orienting <o> along v2 dy, dx = v1.y, v1.x else: # point where the lines defined by v1 and v2 intersect l1 = (e1, o1) if e1 else attached1 l2 = (o2, e2) if e2 else attached2 p = intersect_line_line(l1[0].location, l1[1].location, l2[0].location, l2[1].location)[0] # orient <o> along the line defined by <o> and <p> dy, dx = o.location.y-p.y, o.location.x-p.x elif e1 or attached1 or e2 or attached2: _v = v1 if e1 or attached1 else v2 # orient <o> along <_v> dy, dx = _v.y, _v.x else: # orient <o> along the normal to the wall segment defined by <o> dy, dx = o1.location.x-o2.location.x, o2.location.y-o1.location.y o.rotation_euler[2] = math.atan2(dy, dx) context.scene.update() # adding drivers for o1 and o2 addMoverDrivers(o1, o, p) addMoverDrivers(o2, o, p) makeActiveSelected(context, o)
def getIntersection(x, y): BMEdge = bmesh.types.BMEdge x1, x2 = (x.verts[0].co, x.verts[1].co) if isinstance(x, BMEdge) else (x[0], x[1]) y1, y2 = (y.verts[0].co, y.verts[1].co) if isinstance(y, BMEdge) else (y[0], y[1]) if angle_2vec3(x1-x2, y1-y2) < 0.002: return None else: vec = geometry.intersect_line_line(x1, x2, y1, y2) return (vec[0] + vec[1]) / 2
def make_corner_alt(self, bm, verts, fac=0.5): face = get_face_with_verts(verts) if face is not None and len(face.edges) == 6: done = False loop_a = None loop_b = None for vert in verts: face_loops = get_face_loops_for_vert(vert, face) for loop in face_loops: if loop.vert in verts: loop_a = loop if loop.link_loop_next.link_loop_next.vert in verts: loop_b = loop.link_loop_next done = True break if done: break if loop_a is not None and loop_b is not None: edge_a = loop_a.link_loop_prev.link_loop_prev.edge edge_b = loop_b.link_loop_next.link_loop_next.edge vert_a = loop_a.vert vert_b = loop_b.edge.other_vert(loop_b.vert) edge_a_point, _ = intersect_point_line(vert_b.co, edge_a.verts[0].co, edge_a.verts[1].co) edge_b_point, _ = intersect_point_line(vert_a.co, edge_b.verts[0].co, edge_b.verts[1].co) isect_point = intersect_line_line(edge_a_point, vert_b.co, edge_b_point, vert_a.co) if isect_point is not None: center_vert_co = isect_point[0] shared_vert = get_vertex_shared_by_edges( [loop_a.edge, loop_b.edge]) connect_vert = get_vertex_shared_by_edges([edge_a, edge_b]) center_vert_co = center_vert_co.lerp(connect_vert.co, fac) # Make the corner geometry center_vert: BMVert = bmesh.ops.create_vert( bm, co=center_vert_co)["vert"][0] bm.faces.ensure_lookup_table() bm.edges.ensure_lookup_table() bm.verts.ensure_lookup_table() new_edge_a = bm.edges.new([vert_a, center_vert]) new_edge_b = bm.edges.new([vert_b, center_vert]) new_edge_c = bm.edges.new([center_vert, connect_vert]) bmesh.utils.face_split_edgenet( face, [new_edge_a, new_edge_b, new_edge_c])
def getIntersection(x, y): BMEdge = bmesh.types.BMEdge x1, x2 = (x.verts[0].co, x.verts[1].co) if isinstance(x, BMEdge) else (x[0], x[1]) y1, y2 = (y.verts[0].co, y.verts[1].co) if isinstance(y, BMEdge) else (y[0], y[1]) if angle_2vec3(x1 - x2, y1 - y2) < 0.002: return None else: vec = geometry.intersect_line_line(x1, x2, y1, y2) return (vec[0] + vec[1]) / 2
def grad_f_ed(ed, p, last_face): #walk around non manifold edges if len(ed.link_faces) == 1: minv = min(ed.verts, key = geos.get) return minv.co, minv, None f = [fc for fc in ed.link_faces if fc !=last_face][0] g = gradient_face(f, geos) L = f.calc_perimeter() #test for vert intersection for v in f.verts: v_inter, pct = intersect_point_line(v.co, p, p-L*g) delta = v.co - v_inter if delta.length < epsilon: print('intersect vert') return v.co, v, None tests = [e for e in f.edges if e != ed] for e in tests: v0, v1 = intersect_line_line(e.verts[0].co, e.verts[1].co, p, p-L*g) V = v0 - e.verts[0].co edV = e.verts[1].co - e.verts[0].co Vi = v0 - p if V.length - edV.length > epsilon: #print('intersects outside segment') continue elif V.dot(edV) < 0: #print('intersects behind') continue elif Vi.dot(g) > 0: #remember we watnt to travel DOWN the gradient #print('shoots out the face, not across the face') continue else: #print('regular face edge crossing') return v0, e, f #we didn't intersect across an edge, or on a vert, #therefore, we should travel ALONG the edge vret = min(ed.verts, key = geos.get) return vret.co, vret, None
def grad_f_ed(ed, p, last_face): # walk around non manifold edges if len(ed.link_faces) == 1: minv = min(ed.verts, key=geos.get) return minv.co, minv, None f = [fc for fc in ed.link_faces if fc != last_face][0] g = gradient_face(f, geos) L = f.calc_perimeter() # test for vert intersection for v in f.verts: v_inter, pct = intersect_point_line(v.co, p, p - L * g) delta = v.co - v_inter if delta.length < epsilon: print("intersect vert") return v.co, v, None tests = [e for e in f.edges if e != ed] for e in tests: v0, v1 = intersect_line_line(e.verts[0].co, e.verts[1].co, p, p - L * g) V = v0 - e.verts[0].co edV = e.verts[1].co - e.verts[0].co Vi = v0 - p if V.length - edV.length > epsilon: # print('intersects outside segment') continue elif V.dot(edV) < 0: # print('intersects behind') continue elif Vi.dot(g) > 0: # remember we watnt to travel DOWN the gradient # print('shoots out the face, not across the face') continue else: # print('regular face edge crossing') return v0, e, f # we didn't intersect across an edge, or on a vert, # therefore, we should travel ALONG the edge vret = min(ed.verts, key=geos.get) return vret.co, vret, None
def persp_fac_to_world_fac(self, fac, inverted_perspective_matrix, v1, v2): """v1,v2はpersp座標""" v3 = v1 + (v2 - v1) * fac v4 = v3.copy() v3[2] = 0.0 v4[2] = 0.5 vec1 = mul_persp(inverted_perspective_matrix, v1) vec2 = mul_persp(inverted_perspective_matrix, v2) vec3 = mul_persp(inverted_perspective_matrix, v3) vec4 = mul_persp(inverted_perspective_matrix, v4) i1, i2 = geo.intersect_line_line(vec1, vec2, vec3, vec4) vec12 = vec2 - vec1 return vec12.dot(i1 - vec1) / vec12.length ** 2
def add_vertex_to_intersection(bm, edges): bm_deselect_all(bm) if len(edges) == 2: [[v1, v2], [v3, v4]] = [[v.co for v in e.verts] for e in edges] iv = geometry.intersect_line_line(v1, v2, v3, v4) if iv: iv = (iv[0] + iv[1]) / 2 bm.verts.new(iv) bm.verts.ensure_lookup_table() bm.verts[-1].select = True
def line_from_edge_intersect(edge1, edge2): """Get New Line from Intersections. Prepares input for sending to intersect_line_line Args: edge1, edge2: tuples containing 2 vectors. Returns: Output of intersect_line_line. """ [p1, p2], [p3, p4] = edge1, edge2 return intersect_line_line(p1, p2, p3, p4)
def createOutline(curve, outline): for spline in curve.data.splines[:]: p = spline.bezier_points out = [] n = ((p[0].handle_right - p[0].co).normalized() - (p[0].handle_left - p[0].co).normalized()).normalized() n = Vector((-n[1], n[0], n[2])) o = p[0].co + outline * n out.append(o) for i in range(1, len(p)): n = ((p[i].handle_right - p[i].co).normalized() - (p[i].handle_left - p[i].co).normalized()).normalized() n = Vector((-n[1], n[0], n[2])) o = intersect_line_line(out[-1], (out[-1] + p[i].co - p[i - 1].co), p[i].co, p[i].co + n)[0] out.append(o) curve.data.splines.new('BEZIER') if spline.use_cyclic_u: curve.data.splines[-1].use_cyclic_u = True p_out = curve.data.splines[-1].bezier_points p_out.add(len(out) - 1) for i in range(len(out)): p_out[i].handle_left_type = 'FREE' p_out[i].handle_right_type = 'FREE' p_out[i].co = out[i] if i < len(out) - 1: l = (p[i + 1].co - p[i].co).length l2 = (out[i] - out[i + 1]).length if i == 0: p_out[i].handle_left = out[i] + ( (p[i].handle_left - p[i].co) * l2 / l) if i < len(out) - 1: p_out[i + 1].handle_left = out[i + 1] + ( (p[i + 1].handle_left - p[i + 1].co) * l2 / l) p_out[i].handle_right = out[i] + ( (p[i].handle_right - p[i].co) * l2 / l) for i in range(len(p)): p_out[i].handle_left_type = p[i].handle_left_type p_out[i].handle_right_type = p[i].handle_right_type return
def generate_3PT_mode_1(pts=None, num_verts=20, make_edges=False): ''' Arc from start - throught - Eend - call this function only if you have 3 pts, - do your error checking before passing to it. ''' num_verts -= 1 verts, edges = [], [] V = Vector # construction v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2]) edge1_mid = v1.lerp(v2, 0.5) edge2_mid = v3.lerp(v4, 0.5) axis = geometry.normal(v1, v2, v4) mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis) # triangle edges v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid r = geometry.intersect_line_line(v1_, v2_, v3_, v4_) if r: # do arc p1, _ = r # find arc angle. a = (v1 - p1).angle((v4 - p1), 0) s = (2 * math.pi) - a interior_angle = (v1 - v2).angle(v4 - v3, 0) if interior_angle > 0.5 * math.pi: s = math.pi + 2 * (0.5 * math.pi - interior_angle) for i in range(num_verts + 1): mat_rot = mathutils.Matrix.Rotation(((s / num_verts) * i), 4, axis) vec = ((v4 - p1) * mat_rot) + p1 verts.append(vec[:]) else: # do straight line step_size = 1 / num_verts verts = [v1_.lerp(v4_, i * step_size)[:] for i in range(num_verts + 1)] if make_edges: edges = [(n, n + 1) for n in range(len(verts) - 1)] return verts, edges
def grad_v(v): ''' walk down from a vert ''' eds = [ed for ed in v.link_edges if geos[ed.other_vert(v)] <= geos[v]] if len(eds) == 0: print('lowest vert or local minima') return None, None, None fs = set() for ed in eds: fs.update(ed.link_faces) minf = min(fs, key=lambda x: sum([geos[vrt] for vrt in x.verts])) for ed in minf.edges: if v not in ed.verts: g = gradient_face(minf, geos) L = minf.calc_perimeter() v0, v1 = intersect_line_line(ed.verts[0].co, ed.verts[1].co, v.co, v.co - L * g) V = v0 - ed.verts[0].co edV = ed.verts[1].co - ed.verts[0].co if V.length - edV.length > epsilon: continue #print('intersects outside segment') elif V.dot(edV) < 0: #print('intersects behind') continue else: #print('regular edge crossing') return v0, ed, minf #we were not able to walk through a face print('must walk on edge') vs = [ed.other_vert(v) for ed in eds] minv = min(vs, key=geos.get) if geos[minv] > geos[v]: print('Found smallest geodesic already') return None, None, None return minv.co, minv, None
def center_of_circumscribed_circle_tri(v1, v2, v3): """三角形の外接円の中心点を求める""" if v1 != v2 and v2 != v3 and v3 != v1: # 垂直二等分線の交差点を求める v12 = v2 - v1 v13 = v3 - v1 med12 = (v1 + v2) / 2 med13 = (v1 + v3) / 2 per12 = v13 - v13.project(v12) per13 = v12 - v12.project(v13) inter = geom.intersect_line_line(med12, med12 + per12, med13, med13 + per13) if inter: return (inter[0] + inter[1]) / 2 return None
def add_vertex_to_intersection(): obj = bpy.context.object me = obj.data bm = bmesh.from_edit_mesh(me) edges = [e for e in bm.edges if e.select] if len(edges) == 2: [[v1, v2], [v3, v4]] = [[v.co for v in e.verts] for e in edges] iv = geometry.intersect_line_line(v1, v2, v3, v4) iv = (iv[0] + iv[1]) / 2 bm.verts.new(iv) bmesh.update_edit_mesh(me)
def get_intersection_dictionary(cm, bm, edge_indices): bm.verts.ensure_lookup_table() bm.edges.ensure_lookup_table() permutations = get_valid_permutations(cm, bm, edge_indices) k = defaultdict(list) d = defaultdict(list) for edges in permutations: vert_vectors = cm.vectors_from_edges_tuple(bm, edges) v1, v2, v3, v4 = vert_vectors # Edges obviously can not intersect if their bounding # boxes do not intersect if (max(v1.x, v2.x) < min(v3.x, v4.x) or max(v1.y, v2.y) < min(v3.y, v4.y) or max(v1.z, v2.z) < min(v3.z, v4.z)): continue if (max(v3.x, v4.x) < min(v1.x, v2.x) or max(v3.y, v4.y) < min(v1.y, v2.y) or max(v3.z, v4.z) < min(v1.z, v2.z)): continue # Edges can not intersect if they do not lie in # the same plane if not cm.is_coplanar(vert_vectors): continue points = intersect_line_line(*vert_vectors) # some can be skipped. (NaN, None, not on both edges) if can_skip(cm, points, vert_vectors): continue # reaches this point only when an intersection happens on both edges. [k[edge].append(points[0]) for edge in edges] # k will contain a dict of edge indices and points found on those edges. for edge_idx, unordered_points in k.items(): tv1, tv2 = bm.edges[edge_idx].verts v1 = bm.verts[tv1.index].co v2 = bm.verts[tv2.index].co ordered_points = order_points((v1, v2), unordered_points) d[edge_idx].extend(ordered_points) return d
def grad_v(v): """ walk down from a vert """ eds = [ed for ed in v.link_edges if geos[ed.other_vert(v)] <= geos[v]] if len(eds) == 0: print("lowest vert or local minima") return None, None, None fs = set() for ed in eds: fs.update(ed.link_faces) minf = min(fs, key=lambda x: sum([geos[vrt] for vrt in x.verts])) for ed in minf.edges: if v not in ed.verts: g = gradient_face(minf, geos) L = minf.calc_perimeter() v0, v1 = intersect_line_line(ed.verts[0].co, ed.verts[1].co, v.co, v.co - L * g) V = v0 - ed.verts[0].co edV = ed.verts[1].co - ed.verts[0].co if V.length - edV.length > epsilon: continue # print('intersects outside segment') elif V.dot(edV) < 0: # print('intersects behind') continue else: # print('regular edge crossing') return v0, ed, minf # we were not able to walk through a face print("must walk on edge") vs = [ed.other_vert(v) for ed in eds] minv = min(vs, key=geos.get) if geos[minv] > geos[v]: print("Found smallest geodesic already") return None, None, None return minv.co, minv, None
def centerOfSphere(cls, fv): try: if len(fv)==3: return G3.circumCenter(fv) # Equator if len(fv)==4: fv3 = [fv[0],fv[1],fv[2]] c1 = G3.circumCenter(fv) n1 = G3.ThreePnormal(fv) fv3 = [fv[1],fv[2],fv[3]] c2 = G3.circumCenter(fv3) n2 = G3.ThreePnormal(fv3) d1 = c1+n1 d2 = c2+n2 return geometry.intersect_line_line (c1, d1, c2, d2)[0] except(RuntimeError, TypeError): return None
def SegmentIntersect(A, B, C, D, point=True, more=False, pdeb=False): A, B, C, D = Vectors([A, B, C, D]) # "l,dAB=readVec(B-A) # l,dBA=readVec(A-B) # l,dCD=readVec(D-C) dec = 0.03 # if cfloat(dAB,'not',dCD,dec) and cfloat(dBA,'not',dCD,dec) : if parallel(A, B, C, D, False) == False: if (signedarea(A, B, C) * signedarea(A, B, D) <= 0) and (signedarea(C, D, A) * signedarea(C, D, B) <= 0): # inter=LineIntersect(A,B,C,D) inter = geometry.intersect_line_line(A, B, C, D) # if (AB)=(CD) : return none # if type(inter)!=type(tuple()) : # if pdeb :print 'nonetype' # return False # if (AB)=(CD) bis : return -1.#IND # elif str(inter[0][0])=='-1.#IND' : # if pdeb :print '-1#IND' # return False # if (AB)=(CD) : return none if type(inter) != type(tuple()) or str(inter[0][0]) == "nan": if pdeb: dprint("parrallel") return False # inter is equal to A,B,C or D : shall we include them ? elif point == False and ( cfloat(inter[0], "eq", A, dec) or cfloat(inter[0], "eq", B, dec) or cfloat(inter[0], "eq", C, dec) or cfloat(inter[0], "eq", D, dec) ): if pdeb: dprint("canceled : %s is an extremity" % inter[0]) return False # ok else: return inter elif pdeb: dprint("segments") # segments doesn't cross ( parralel or merged ) elif more: if pdeb: dprint("parallels") return False, True return False
def generate_3PT_mode_1(pts, obj, nv): origin = obj.location mw = obj.matrix_world V = Vector nv = max(3, nv) # construction v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2]) edge1_mid = v1.lerp(v2, 0.5) edge2_mid = v3.lerp(v4, 0.5) axis = geometry.normal(v1, v2, v4) mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis) # triangle edges v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid r = geometry.intersect_line_line(v1_, v2_, v3_, v4_) if r: p1, _ = r cp = mw * p1 bpy.context.scene.cursor_location = cp layer = get_layer() generate_gp3d_stroke(layer, p1, v1, axis, mw, origin, nv) ''' # f = [i for i in dir(bpy.context) if 'gpencil' in i] active_gpencil_frame active_gpencil_layer editable_gpencil_layers editable_gpencil_strokes gpencil_data gpencil_data_owner visible_gpencil_layers ''' #bpy.context.active_gpencil_layer = layer #print(bpy.context.gpencil_data) scn = bpy.context.scene scn.grease_pencil = bpy.data.grease_pencil['tc_circle_000'] else: print('not on a circle')
def createOutline(curve, outline): for spline in curve.data.splines[:]: p = spline.bezier_points out = [] n = ((p[0].handle_right-p[0].co).normalized()-(p[0].handle_left-p[0].co).normalized()).normalized() n = Vector((-n[1], n[0], n[2])) o = p[0].co+outline*n out.append(o) for i in range(1,len(p)): n = ((p[i].handle_right-p[i].co).normalized()-(p[i].handle_left-p[i].co).normalized()).normalized() n = Vector((-n[1], n[0], n[2])) o = intersect_line_line(out[-1], (out[-1]+p[i].co-p[i-1].co), p[i].co, p[i].co+n)[0] out.append(o) curve.data.splines.new('BEZIER') if spline.use_cyclic_u: curve.data.splines[-1].use_cyclic_u = True p_out = curve.data.splines[-1].bezier_points p_out.add(len(out)-1) for i in range(len(out)): p_out[i].handle_left_type = 'FREE' p_out[i].handle_right_type = 'FREE' p_out[i].co = out[i] if i<len(out)-1: l = (p[i+1].co-p[i].co).length l2 = (out[i]-out[i+1]).length if i==0: p_out[i].handle_left = out[i] + ((p[i].handle_left-p[i].co)*l2/l) if i<len(out)-1: p_out[i+1].handle_left = out[i+1] + ((p[i+1].handle_left-p[i+1].co)*l2/l) p_out[i].handle_right = out[i] + ((p[i].handle_right-p[i].co)*l2/l) for i in range(len(p)): p_out[i].handle_left_type = p[i].handle_left_type p_out[i].handle_right_type = p[i].handle_right_type return
def edgeIntersect(context, operator): from mathutils.geometry import intersect_line_line obj = context.active_object if obj.type != "MESH": operator.report({"ERROR"}, "Object must be a mesh") return None edges = [] mesh = obj.data verts = mesh.vertices is_editmode = obj.mode == "EDIT" if is_editmode: bpy.ops.object.mode_set(mode="OBJECT") for e in mesh.edges: if e.select: edges.append(e) if len(edges) > 2: break if is_editmode: bpy.ops.object.mode_set(mode="EDIT") if len(edges) != 2: operator.report({"ERROR"}, "Operator requires exactly 2 edges to be selected") return line = intersect_line_line( verts[edges[0].vertices[0]].co, verts[edges[0].vertices[1]].co, verts[edges[1].vertices[0]].co, verts[edges[1].vertices[1]].co, ) if line is None: operator.report({"ERROR"}, "Selected edges do not intersect") return point = line[0].lerp(line[1], 0.5) context.scene.cursor_location = obj.matrix_world * point
def start_grad_f(f, p): g = gradient_face(f, geos) L = f.calc_perimeter() # test for vert intersection for v in f.verts: v_inter, pct = intersect_point_line(v.co, p, p - L * g) delta = v.co - v_inter if delta.length < epsilon: print("intersects vert") return v, v.co, None for e in f.edges: v0, v1 = intersect_line_line(e.verts[0].co, e.verts[1].co, p, p - L * g) V = v0 - e.verts[0].co edV = e.verts[1].co - e.verts[0].co Vi = v0 - p if V.length - edV.length > epsilon: # print('intersects outside segment') continue elif V.dot(edV) < 0: # print('intersects behind') continue elif Vi.dot(g) > 0: # remember we watnt to travel DOWN the gradient # print('shoots out the face, not across the face') continue else: # print('regular face edge crossing') return v0, e, f # we didn't intersect across an edge, or on a vert, # therefore, we should travel ALONG the edge vret = min(f.verts, key=geos.get) return vret.co, vret, None
def add_vertex_to_intersection(): obj = bpy.context.object me = obj.data bm = bmesh.from_edit_mesh(me) edges = [e for e in bm.edges if e.select] if len(edges) == 2: [[v1, v2], [v3, v4]] = [[v.co for v in e.verts] for e in edges] iv = geometry.intersect_line_line(v1, v2, v3, v4) iv = (iv[0] + iv[1]) / 2 bm.verts.new(iv) # precaution? if hasattr(bm.verts, "ensure_lookup_table"): bm.verts.ensure_lookup_table() # bm.edges.ensure_lookup_table() bm.verts[-1].select = True bmesh.update_edit_mesh(me)
def generate_3PT(pts, obj, nv, mode=0): origin = obj.location mw = obj.matrix_world V = Vector nv = max(3, nv) # construction v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2]) edge1_mid = v1.lerp(v2, 0.5) edge2_mid = v3.lerp(v4, 0.5) axis = geometry.normal(v1, v2, v4) mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis) # triangle edges v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid r = geometry.intersect_line_line(v1_, v2_, v3_, v4_) if r: p1, _ = r cp = mw * p1 bpy.context.scene.cursor_location = cp if mode == 0: layer = get_layer() generate_gp3d_stroke(layer, p1, v1, axis, mw, origin, nv) scn = bpy.context.scene scn.grease_pencil = bpy.data.grease_pencil['tc_circle_000'] elif mode == 1: generate_bmesh_repr(p1, v1, axis, nv) else: print('not on a circle')
def linkLayers(layer1, layer2): for i in range(0, len(layer1)): nextI = (i + 1)%len(layer1) nextII = (i + 2)%len(layer1) a = mathutils.Vector((layer2[i]['hinge3'].matrix_world[0][3] , layer2[i]['y'], layer2[i]['hinge3'].matrix_world[2][3])) b = mathutils.Vector((layer2[nextI]['hinge1'].matrix_world[0][3] , layer2[i]['y'], layer2[nextI]['hinge1'].matrix_world[2][3])) c = mathutils.Vector((layer1[nextI]['hinge3'].matrix_world[0][3] , layer2[i]['y'], layer1[nextI]['hinge3'].matrix_world[2][3])) d = mathutils.Vector((layer1[nextII]['hinge1'].matrix_world[0][3], layer2[i]['y'], layer1[nextII]['hinge1'].matrix_world[2][3])) print(a, b, c, d) (v1, v2) = intersect_line_line(a, b, c, d) print (v1, v2) bpy.ops.object.select_all(action='DESELECT') bpy.types.SpaceView3D.cursor_location = (0,0,0) bpy.ops.object.add(type='EMPTY') hinge = bpy.context.scene.objects.active hinge.name = ("mid hinge") hinge.location = v1 hinge.rotation_euler = (tau/4,0,0) bpy.ops.rigidbody.constraint_add(type='HINGE') hinge.rigid_body_constraint.disable_collisions = False hinge.rigid_body_constraint.object1 = layer1[nextI]['bar1'] hinge.rigid_body_constraint.object2 = layer2[nextI]['bar2'] hinge.select = False
def is_parallel(v1, v2, v3, v4): result = intersect_line_line(v1, v2, v3, v4) return result == None
def execute(self, context): bpy.ops.object.editmode_toggle() bm = bmesh.new() bm.from_mesh(bpy.context.active_object.data) bVerts = bm.verts bEdges = bm.edges edges = [] vectors = [] for e in bEdges: if e.select: edges.append(e) # Until I can figure out a better way of handeling it: if len(edges) < 2: bpy.ops.object.editmode_toggle() self.report({'ERROR_INVALID_INPUT'}, "You must select two edges.") return {'CANCELLED'} verts = [edges[0].verts[0], edges[0].verts[1], edges[1].verts[0], edges[1].verts[1]] cos = intersect_line_line(verts[0].co, verts[1].co, verts[2].co, verts[3].co) # If the two edges are parallel: if cos == None: self.report({'WARNING'}, "Selected lines are parallel: results may be unpredictable.") vectors.append(verts[0].co - verts[1].co) vectors.append(verts[0].co - verts[2].co) vectors.append(vectors[0].cross(vectors[1])) vectors.append(vectors[2].cross(vectors[0])) vectors.append(-vectors[3]) else: # Warn the user if they have not chosen two planar edges: if not is_same_co(cos[0], cos[1]): self.report({'WARNING'}, "Selected lines are not planar: results may be unpredictable.") # This makes the +/- behavior predictable: if (verts[0].co - cos[0]).length < (verts[1].co - cos[0]).length: verts[0], verts[1] = verts[1], verts[0] if (verts[2].co - cos[0]).length < (verts[3].co - cos[0]).length: verts[2], verts[3] = verts[3], verts[2] vectors.append(verts[0].co - verts[1].co) vectors.append(verts[2].co - verts[3].co) # Normal of the plane formed by vector1 and vector2: vectors.append(vectors[0].cross(vectors[1])) # Possible directions: vectors.append(vectors[2].cross(vectors[0])) vectors.append(vectors[1].cross(vectors[2])) # Set the length: vectors[3].length = self.length vectors[4].length = self.length # Perform any additional rotations: matrix = Matrix.Rotation(radians(90 + self.angle), 3, vectors[2]) vectors.append(matrix * -vectors[3]) # vectors[5] matrix = Matrix.Rotation(radians(90 - self.angle), 3, vectors[2]) vectors.append(matrix * vectors[4]) # vectors[6] vectors.append(matrix * vectors[3]) # vectors[7] matrix = Matrix.Rotation(radians(90 + self.angle), 3, vectors[2]) vectors.append(matrix * -vectors[4]) # vectors[8] # Perform extrusions and displacements: # There will be a total of 8 extrusions. One for each vert of each edge. # It looks like an extrusion will add the new vert to the end of the verts # list and leave the rest in the same location. # ----------- EDIT ----------- # It looks like I might be able to do this with in "bpy.data" with the ".add" # function. # ------- BMESH UPDATE ------- # BMesh uses ".new()" for v in range(len(verts)): vert = verts[v] if (v == 0 and self.vert1) or (v == 1 and self.vert2) or (v == 2 and self.vert3) or (v == 3 and self.vert4): if self.pos: new = bVerts.new() new.co = vert.co - vectors[5 + (v // 2) + ((v % 2) * 2)] bEdges.new((vert, new)) if self.neg: new = bVerts.new() new.co = vert.co + vectors[5 + (v // 2) + ((v % 2) * 2)] bEdges.new((vert, new)) bm.to_mesh(bpy.context.active_object.data) bpy.ops.object.editmode_toggle() return {'FINISHED'}
def intersect_line_line(v1, v2, v3, v4, threshold=1e-6): """ 三次元での直線同士の交差判定。平行だった場合、中間地点を求める。 二次元が与えられたら三次元に拡張する。 parallel_threshold: 平行であるとする閾値 """ v1 = v1.to_3d() v2 = v2.to_3d() v3 = v3.to_3d() v4 = v4.to_3d() vec1 = v2 - v1 vec2 = v4 - v3 # 両方点 if vec1.length == 0.0 and vec2.length == 0.0: return None # v1-v2が直線、v3-v4が点 elif vec2.length == 0.0: return (v3 - v1).project(vec1) + v1, v3 # v1-v2が点、v3-v4が直線 elif vec1.length == 0.0: return v1, (v1 - v3).project(vec2) + v3 # 平行 elif vec1.normalized().cross(v3 - v1).length < threshold and \ vec1.normalized().cross(v4 - v1).length < threshold: d1 = vec1.dot(v3 - v1) d2 = vec1.dot(v4 - v1) if d1 > d2: d1, d2 = d2, d1 v3, v4 = v4, v3 vec2.negate() # v3,v4が両方v1側 or v3がv1側, v4がv1-v2間 if d2 <= 0 or (d1 <= 0 and 0 <= d2 <= vec1.length): mid = (v1 + v4) / 2 # v3,v4が両方v2側 or v3がv1-v2間, v4がv2側 elif d1 >= vec1.length or \ (0 <= d1 <= vec1.length and d2 >= vec1.length): mid = (v2 + v3) / 2 # v3,v4がv1-v2間 elif 0 <= d1 <= vec1.length and 0 <= d2 <= vec1.length: mid = (v2 + v3) / 2 # v1,v2がv3-v4間 else: mid = (v1 + v4) / 2 isect1 = (mid - v1).project(vec1) + v1 isect2 = (mid - v3).project(vec2) + v3 return isect1, isect2 else: result = geom.intersect_line_line(v1, v2, v3, v4) if result is not None: # isect1, isect2 = result # if not math.isnan(isect1[0]) and not math.isnan(isect2[0]): # return isect1, isect2 return result return None