Source code for genepy3d_gpl.interact.curvesurface

"""Interaction between Curve and Surface objects.
"""

import numpy as np
from genepy3d.obj.points import Points
from genepy3d.obj.curves import Curve
from genepy3d.util.geo import l2
from genepy3d_gpl.interact import pointsurface

[docs] def intersect(crv, surf): """Intersection between curve and surface, using AABB_tree_Triangle_3_soup from CGAL as exposed by CGAL-swig-bindings. Args: crv (Curve): Curve object. surf (Surface): Surface object. Return: List of intersected points and their corresponding curve segments. Examples: .. code-block:: python import numpy as np from genepy3d.obj.curves import Curve from genepy3d.obj.surfaces import Surface from genepy3d_gpl.interact import curvesurface import matplotlib.pyplot as plt # Create a box coors = np.array([[0.,0.,0.],[0.,1.,0.],[0.,1.,1.],[0.,0.,1.],[1.,0.,0.],[1.,1.,0.],[1.,1.,1.],[1.,0.,1.]]) srf = Surface.from_points_qhull(coors) # Create a curve coors = np.array([[-1.5,0.5,0.5],[0,0.5,0.5],[1.5,0.5,0.5]]) crv = Curve(coors) pnts, _ = curvesurface.intersect(crv,srf) # Plot fig = plt.figure() ax = fig.add_subplot(111,projection='3d') srf.plot(ax) crv.plot(ax,show_root=False) pnts.plot(ax,point_args={"color":"r"}); """ ## TODO remove lflag. Not useful. from CGAL.CGAL_Kernel import Point_3, Segment_3, Triangle_3 from CGAL.CGAL_AABB_tree import AABB_tree_Triangle_3_soup plst = [] # intersected point list lflag = [] # intersected line segment flag crvseglst = [] # curve segment where intersected point lying on # get list of triangles from surf triangles = [] for i in range(len(surf.faces)): coors = surf.vertices[surf.faces[i,0]] p1 = Point_3(float(coors[0]), float(coors[1]), float(coors[2])) coors = surf.vertices[surf.faces[i,1]] p2 = Point_3(float(coors[0]), float(coors[1]), float(coors[2])) coors = surf.vertices[surf.faces[i,2]] p3 = Point_3(float(coors[0]), float(coors[1]), float(coors[2])) triangles.append(Triangle_3(p1,p2,p3)) # initialize AABB tree for surf tree = AABB_tree_Triangle_3_soup(triangles) # searching intersection between each curve segment and surf. for i in range(len(crv.coors)-1): # get segment query p1 = Point_3(float(crv.coors[i][0]),float(crv.coors[i][1]),float(crv.coors[i][2])) p1coors = np.array([p1.x(),p1.y(),p1.z()]) p2 = Point_3(float(crv.coors[i+1][0]),float(crv.coors[i+1][1]),float(crv.coors[i+1][2])) segment_query = Segment_3(p1,p2) subpntlst = [] # intersected points subpntdst = [] # distance from intersected points to p1 (for sorting) sublflag = [] # intersected line flag subcrvseglst = [] if tree.do_intersect(segment_query): intersections = [] tree.all_intersections(segment_query,intersections) for inter in intersections: if inter[0].is_Point_3(): p = inter[0].get_Point_3() pcoors = np.array([p.x(),p.y(),p.z()]) subpntdst.append(l2(p1coors,pcoors)) subpntlst.append(pcoors) sublflag.append(False) subcrvseglst.append(i) elif inter[0].is_Segment_3(): l = inter[0].get_Segment_3() for j in [0,1]: p = l.vertex(j) pcoors = np.array([p.x(),p.y(),p.z()]) subpntdst.append(l2(p1coors,pcoors)) subpntlst.append(pcoors) sublflag.append(True) subcrvseglst.append(i) if len(subpntdst)>0: # remove duplicates (strange thing in CGAL) subpntlst, uix = np.unique(np.array(subpntlst),axis=0,return_index=True) subpntdst = np.array(subpntdst)[uix] sublflag = np.array(sublflag)[uix] subcrvseglst = np.array(subcrvseglst)[uix] # sorting sortix = np.argsort(subpntdst) subpntlst = subpntlst[sortix] sublflag = sublflag[sortix] subcrvseglst = subcrvseglst[sortix] plst = plst + subpntlst.tolist() lflag = lflag + sublflag.tolist() crvseglst = crvseglst + subcrvseglst.tolist() # remove duplicates if len(plst)>0: _, uix = np.unique(np.array(plst),axis=0,return_index=True) plst = np.array(plst)[np.sort(uix)] lflag = np.array(lflag)[np.sort(uix)] crvseglst = np.array(crvseglst)[np.sort(uix)] return (Points(plst), crvseglst) else: return (None, None)
[docs] def inonout(crv,surf): """Classify curve segments as being inside/lying on/outside of the surface. Use intersect, which uses AABB_tree_Triangle_3_soup from CGAL as exposed by CGAL-swig-bindings. Args: crv (Curve): Curve object. surf (Surface): Surface object. Returns: List of curves that are inside, onside and outside of the surface. Notes: The surface must be watertight. Examples: .. code-block:: python import numpy as np from genepy3d.obj.curves import Curve from genepy3d.obj.surfaces import Surface from genepy3d_gpl.interact import curvesurface import matplotlib.pyplot as plt # Create a box coors = np.array([[0.,0.,0.],[0.,1.,0.],[0.,1.,1.],[0.,0.,1.],[1.,0.,0.],[1.,1.,0.],[1.,1.,1.],[1.,0.,1.]]) srf = Surface.from_points_qhull(coors) print("Surface is watertight?",srf.is_watertight) # Create a curve coors = np.array([[-1.5,0.5,0.5],[0,0.5,0.5],[1.,1.,1.],[1.,0.5,0.5],[1.5,0.5,0.5]]) crv = Curve(coors) # Compute curve segments lying inside/on/outside of the surface crvin, crvon, crvout = curvesurface.inonout(crv,srf) # Plot fig = plt.figure() ax = fig.add_subplot(111,projection='3d') srf.plot(ax) # Curve segments inside the surface for tmp in crvin: tmp.plot(ax,show_root=False,line_args={"color":"r"}) # Curve segments lying on the surface for tmp in crvon: tmp.plot(ax,show_root=False,line_args={"color":"g"}) # Curve segments outside the surface for tmp in crvout: tmp.plot(ax,show_root=False,line_args={"color":"b"}) """ # get intersection between crv and surf intpnts, crvseglst = intersect(crv,surf) if intpnts is None: # no intersection inflag,_,_ = pointsurface.inonout(Points(crv.coors[[0]]),surf,return_masks=True) if inflag[0]==True: return ([crv],[],[]) else: return ([],[],[crv]) else: incoors, oncoors, outcoors = [], [], [] # add intersected points to curve points (here all points are ordered) fullpntlst = [] for i in range(len(crv.coors)-1): fullpntlst.append(crv.coors[i].tolist()) ix = np.argwhere(crvseglst==i).flatten() if len(ix)!=0: fullpntlst = fullpntlst + intpnts.coors[ix].tolist() fullpntlst.append(crv.coors[-1].tolist()) # remove duplicate _, uix = np.unique(np.array(fullpntlst),axis=0,return_index=True) fullpntlst = np.array(fullpntlst)[np.sort(uix)] # print(fullpntlst) # middle points between two points of fullpntlst checkpntlst = (fullpntlst[:-1]+fullpntlst[1:])/2. # print(checkpntlst) # check middle points lying on the surf inside, onside, outside = pointsurface.inonout(Points(checkpntlst),surf,return_masks=True) # print(inside) # print(onside) # print(outside) # assignment subincoors, suboncoors, suboutcoors = [], [], [] prevflag = "none" # previous curve segment label for i in range(len(fullpntlst)-1): if inside[i]==True: if prevflag == "inside": subincoors = subincoors + fullpntlst[i:i+2].tolist() else: subincoors = [] subincoors = subincoors + fullpntlst[i:i+2].tolist() if (prevflag=="onside")&(len(suboncoors)!=0): _, uix = np.unique(np.array(suboncoors),axis=0,return_index=True) suboncoors = np.array(suboncoors)[np.sort(uix)] oncoors.append(Curve(suboncoors)) elif (prevflag=="outside")&(len(suboutcoors)!=0): _, uix = np.unique(np.array(suboutcoors),axis=0,return_index=True) suboutcoors = np.array(suboutcoors)[np.sort(uix)] outcoors.append(Curve(suboutcoors)) prevflag = "inside" elif onside[i]==True: if prevflag == "onside": suboncoors = suboncoors + fullpntlst[i:i+2].tolist() else: suboncoors = [] suboncoors = suboncoors + fullpntlst[i:i+2].tolist() if (prevflag=="inside")&(len(subincoors)!=0): _, uix = np.unique(np.array(subincoors),axis=0,return_index=True) subincoors = np.array(subincoors)[np.sort(uix)] incoors.append(Curve(subincoors)) elif (prevflag=="outside")&(len(suboutcoors)!=0): _, uix = np.unique(np.array(suboutcoors),axis=0,return_index=True) suboutcoors = np.array(suboutcoors)[np.sort(uix)] outcoors.append(Curve(suboutcoors)) prevflag = "onside" else: if prevflag == "outside": suboutcoors = suboutcoors + fullpntlst[i:i+2].tolist() else: suboutcoors = [] suboutcoors = suboutcoors + fullpntlst[i:i+2].tolist() if (prevflag=="inside")&(len(subincoors)!=0): _, uix = np.unique(np.array(subincoors),axis=0,return_index=True) subincoors = np.array(subincoors)[np.sort(uix)] incoors.append(Curve(subincoors)) elif (prevflag=="onside")&(len(suboncoors)!=0): _, uix = np.unique(np.array(suboncoors),axis=0,return_index=True) suboncoors = np.array(suboncoors)[np.sort(uix)] oncoors.append(Curve(suboncoors)) prevflag = "outside" # last check if (prevflag=="inside")&(len(subincoors)!=0): _, uix = np.unique(np.array(subincoors),axis=0,return_index=True) subincoors = np.array(subincoors)[np.sort(uix)] incoors.append(Curve(subincoors)) elif (prevflag=="onside")&(len(suboncoors)!=0): _, uix = np.unique(np.array(suboncoors),axis=0,return_index=True) suboncoors = np.array(suboncoors)[np.sort(uix)] oncoors.append(Curve(suboncoors)) elif (prevflag=="outside")&(len(suboutcoors)!=0): _, uix = np.unique(np.array(suboutcoors),axis=0,return_index=True) suboutcoors = np.array(suboutcoors)[np.sort(uix)] outcoors.append(Curve(suboutcoors)) return (incoors,oncoors,outcoors)