def np_inertia_axis(points, verbose=False): assert len(points) > 0 import numpy as np import openalea.plantgl.all as pgl if type(points) != pgl.Point3Array: points = pgl.Point3Array(points) if verbose: print 'centering points' center = points.getCenter() npoints = pgl.Point3Array(points) if pgl.norm(center) > 1e-5: npoints.translate(- center) if verbose: print 'compute covariance' # compute 1/N*P.P^T # cov = 1./len(points)*np.dot(npoints.T,npoints) cov = pgl.pointset_covariance(npoints) cov = np.array([cov.getRow(i) for i in xrange(3)]) if verbose: print cov if verbose: print "compute eigen vectors" # Find the eigen values and vectors. eig_val, eig_vec = np.linalg.eig(cov) if verbose: for i in xrange(3): print eig_val[i], eig_vec[:, i] eig_vec = np.array(eig_vec).T eig_vec = np.array([eig_vec[i] for i in reversed(pgl.get_sorted_element_order(eig_val))]) eig_val = np.array([eig_val[i] for i in reversed(pgl.get_sorted_element_order(eig_val))]) return eig_val, eig_vec, center
def NURBSCurve(self, ctrlpoints, dimension, **kwds): ctrlpoints = str(ctrlpoints) ctrlpoints = [float(num) for num in ctrlpoints.split(",")] dimension = int(dimension) items, chunk = ctrlpoints, dimension pointArray = zip(*[iter(items)] * chunk) if (dimension == 2): v4array = [] for item in pointArray: v4array.append(pgl.Vector2(item)) parray = pgl.Point3Array(0) for item in v4array: parray.append(Vector3(item,1)) return (pgl.NurbsCurve2D(parray), None) elif (dimension == 3): v4array = [] for item in pointArray: v4array.append(pgl.Vector3(item)) parray = pgl.Point4Array(0) for item in v4array: parray.append(Vector4(item,1)) return (pgl.NurbsCurve(parray), None)
def Polygon(self, vertices, **kwds): """ TODO: Move code to geometry """ points = str(vertices) points = [float(num) for num in points.split(",")] items, chunk = points, 3 p3list = zip(*[iter(items)] * chunk) p2list = project3Dto2D(p3list) pd2list = [] for i in range(len(p2list)): pd2list.append({i: p2list[i]}) indexlist = [] poly_orientation = orientation(p2list) while len(pd2list) >= 3: for cur in range(len(pd2list)): prev = cur - 1 nex = (cur + 1) % len(pd2list) # Wrap around on the ends # By definition, at least there are two ears; # we will iterate at end only if poly_orientation # was incorrect. pcur, pprev, pnex = pd2list[cur].values()[0], pd2list[prev].values()[0], pd2list[nex].values()[0] det = determinant(pcur, pprev, pnex) inside = no_interior(pprev, pcur, pnex, pd2list, poly_orientation) if (det == poly_orientation) and inside: # Same orientation as polygon # No points inside # Add index of this triangle to the index list index = pd2list[prev].keys()[0], pd2list[cur].keys()[0], pd2list[nex].keys()[0] indexlist.append(index) # Remove the triangle from the polygon del(pd2list[cur]) break return (pgl.TriangleSet(pgl.Point3Array(p3list), indexlist), None)
def tgl(): return pgl.TriangleSet( pgl.Point3Array([ pgl.Vector3(1, 0, 0), pgl.Vector3(-0.2, 1, 0), pgl.Vector3(-0.2, -1, 0) ]), pgl.Index3Array([pgl.Index3(0, 1, 2)]))
def genericLeaf(allo_length, allo_surf, **kwds): if kwds.has_key('surface'): surface = kwds['surface'] length = math.sqrt(surface / (allo_length*allo_surf) ) else: length = kwds.get('length', 1) alpha = kwds.get('alpha', 0) color = kwds.get('color', __niceGreen) step = length/10. x = array(arange(step,length,step)) #begin and end are specific y = (-3.0*allo_length*allo_surf) * (x**2/length - x) cos = math.cos(math.radians(alpha/2.0)) sin = math.sin(math.radians(alpha/2.0)) list = [] idxList = [] for i in range(len(x)): list.append(pgl.Vector3(x[i],0,0)) list.append(pgl.Vector3(x[i],y[i]*cos,y[i]*sin)) list.append(pgl.Vector3(x[i],-y[i]*cos,y[i]*sin)) list.append(pgl.Vector3(0,0,0)) list.append(pgl.Vector3(length,0,0)) for i in range(len(x) -1): idxList.append(pgl.Index(3*(i+1), 3*(i+1)+1, 3*i+1, 3*i )) idxList.append(pgl.Index(3*i+2, 3*(i+1)+2, 3*(i+1), 3*i )) idxList.append(pgl.Index(0, 1, len(list)-2 )) idxList.append(pgl.Index(2, 0, len(list)-2 )) idxList.append(pgl.Index(3*(len(x)-1)+1, 3*(len(x)-1), len(list)-1 )) idxList.append(pgl.Index(3*(len(x)-1), 3*(len(x)-1)+2, len(list)-1 )) p3r = pgl.Point3Array(list) ir = pgl.IndexArray(idxList) fs = pgl.FaceSet(p3r, ir) return pgl.Shape(fs, color)
def pgl_inertia_axis(points): import openalea.plantgl.all as pgl if type(points) != pgl.Point3Array: points = pgl.Point3Array(points) center = points.getCenter() u, v, w, s = pgl.Fit.inertiaAxis(points) return s, [u, v, w], center
def Patch(self, heightValues, usize, vsize, zerolevel, scale, water, **kwds): usize = int(usize) vsize = int(vsize) zerolevel = float(zerolevel) scale = float(scale) water = str(water) water = water.lower() == 'true' heightValues = str(heightValues) heightValues = [float(num) for num in heightValues.split(",")] verts = [] faces = [] nu = usize nv = vsize p = (0, 0, 0) for v in range(nv): for u in range(nu): p = heightFieldGetVertex(v*usize + u, usize, vsize, heightValues, zerolevel, scale, water) verts.append(p) n = 0 for v in range(nv): for u in range(nu): if v < nv-1 and u < nu-1: face = (n, n+1, n+1+nu, n+nu) faces.append(face) n = n+1 return pgl.QuadSet(pgl.Point3Array(verts), faces), None
def ptUnion(pointsbyshape,idList=None):#aka ptsum """union des points de la liste ids""" union = pgl.Point3Array() if idList is None: idList = pointsbyshape.keys() for id in idList: union += pointsbyshape[id] return union
def stolon_curve(scale=1.): v2 = pgl.Vector3 ctrls = pgl.Point3Array([ v2(x * scale, y * scale) for x, y in [(0, 0), (1, 3), (3, 5), (4, 2), (5, 4)] ]) crv = pgl.BezierCurve2D(ctrls) return crv
def Supershape(self, a, b, m1, m2, n11, n12, n13, n21, n22, n23, **kwds): a = float(a) b = float(b) m1 = float(m1) m2 = float(m2) n11 = float(n11) n12 = float(n12) n13 = float(n13) n21 = float(n21) n22 = float(n22) n23 = float(n23) verts = [] faces = [] scale = 1.0 Unum = 20 Vnum = 20 Uinc = pi / (Unum/2) Vinc = (pi/2)/(Vnum/2) #fill verts array theta = -pi for i in range (0, Unum + 1): phi = -pi/2 r1 = Superformula(theta, a, b, m1, n11, n12, n13) for j in range(0,Vnum + 1): r2 = Superformula(phi, a, b, m2, n21, n22, n23) x = scale * (r1 * cos(theta) * r2 * cos(phi)) y = scale * (r1 * sin(theta) * r2 * cos(phi)) z = scale * (r2 * sin(phi)) vert = (x,y,z) verts.append(vert) phi = phi + Vinc theta = theta + Uinc #define faces count = 0 for i in range (0, (Vnum + 1) *(Unum)): if count < Vnum: A = i B = i+1 C = (i+(Vnum+1))+1 D = (i+(Vnum+1)) face = (A,B,C,D) faces.append(face) count = count + 1 else: count = 0 return pgl.QuadSet(pgl.Point3Array(verts), faces), None
def to_geom_args(self, conversion=1.0, name=None, _as_obj=False): # pragma: lpy r"""Get arguments for creating a PlantGL geometry. Args: conversion (float, optional): Conversion factor that should be applied to the vertices. Defaults to 1.0. name (str, optional): Name that should be given to the created PlantGL symbol. Defaults to None and is ignored. Returns: tuple: Class, arguments and keyword arguments for PlantGL geometry. """ import openalea.plantgl.all as pgl kwargs = dict() # Add vertices obj_points = [] obj_colors = [] for v in self['vertices']: xarr = conversion * np.array([v[k] for k in ['x', 'y', 'z']]) obj_points.append( pgl.Vector3(np.float64(xarr[0]), np.float64(xarr[1]), np.float64(xarr[2]))) c = [v.get(k, None) for k in ['red', 'green', 'blue']] if None not in c: cast_type = int obj_colors.append( pgl.Color4(cast_type(c[0]), cast_type(c[1]), cast_type(c[2]), cast_type(1))) points = pgl.Point3Array(obj_points) if obj_colors: colors = pgl.Color4Array(obj_colors) kwargs['colorList'] = colors kwargs['colorPerVertex'] = True # Add indices obj_indices = [] index_class = pgl.Index array_class = pgl.IndexArray smb_class = pgl.FaceSet # index_class = pgl.Index3 # array_class = pgl.Index3Array # smb_class = pgl.TriangleSet for f in self['faces']: if _as_obj: f_int = [int(_f['vertex_index']) for _f in f] else: f_int = [int(_f) for _f in f['vertex_index']] obj_indices.append(index_class(*f_int)) indices = array_class(obj_indices) args = (points, indices) return smb_class, args, kwargs
def _common_init(self, **keys): """ """ if len(keys["points"]) != 3: raise Exception( "ATriangle: triangle must be described by 3 points..") self._indexes = [] self._points = pgl.Point3Array(keys["points"]) for i in xrange(1, len(keys["points"])): self._indexes.append(pgl.Index3(0, 1, 2)) self._indexes = pgl.Index3Array(self._indexes)
def stolon_curve(scale=1.): """Generates the stolon as curves :param scale: size of the stolon, defaults to 1. :type scale: float, optional :return: return a curve to for symbolise a stolon :rtype: plf.BezierCurve2D """ v2 = pgl.Vector3 ctrls = pgl.Point3Array([v2(x*scale, y*scale) for x,y in [(0,0), (1,3), (3,5), (4,2), (5,4)]]) crv = pgl.BezierCurve2D(ctrls) return crv
def to_geom_args(self, conversion=1.0, name=None): r"""Get arguments for creating a PlantGL geometry. Args: conversion (float, optional): Conversion factor that should be applied to the vertices. Defaults to 1.0. name (str, optional): Name that should be given to the created PlantGL symbol. Defaults to None and is ignored. Returns: tuple: Class, arguments and keyword arguments for PlantGL geometry. """ import openalea.plantgl.all as pgl kwargs = dict() # Add vertices obj_points = [] for v in self['vertices']: xarr = conversion * np.array(v) obj_points.append(pgl.Vector3(xarr[0], xarr[1], xarr[2])) points = pgl.Point3Array(obj_points) # Add indices obj_indices = [] nind = None index_class = pgl.Index3 array_class = pgl.Index3Array smb_class = pgl.TriangleSet for f in self['faces']: if nind is None: nind = len(f) if nind == 3: pass else: raise ValueError( "No PlantGL class for faces with %d vertices." % nind) else: if len(f) != nind: raise ValueError("Faces do not all contain %d vertices." % nind) f_int = [int(_f) for _f in f] obj_indices.append(index_class(*f_int)) indices = array_class(obj_indices) # Add colors if self['vertex_colors']: obj_colors = [] for c in self['vertex_colors']: assert (len(c) == 3) obj_colors.append(pgl.Color4(c[0], c[1], c[2], 1)) colors = pgl.Color4Array(obj_colors) kwargs['colorList'] = colors kwargs['colorPerVertex'] = True args = (points, indices) return smb_class, args, kwargs
def optimizeAlignementPosition(points, mtg, distanceratio=10, nbtests=10, p_edir=None): from .mtgmanip import mtg2pgltree import openalea.plantgl.all as pgl from .pointprocessing import np_inertia_axis from math import pi, degrees nodes, parents, vertex2node = mtg2pgltree(mtg) dist = pgl.average_distance_to_shape(points, nodes, parents, [0 for i in range(len(nodes))]) print(dist) if p_edir is None: p_eval, p_edir, p_center = np_inertia_axis(points) mtgextent = pgl.Point3Array(list( mtg.property('position').values())).getExtent() def test_shift(cshift, dist, tshift): print('test shift of', cshift, ':', end=' ') nnodes = [p + cshift for p in nodes] ndist = pgl.average_distance_to_shape(points, nnodes, parents, [0 for j in range(len(nodes))]) print(ndist) if ndist < dist: tshift = cshift dist = ndist return dist, tshift for i in range(3): tshift = None unitshift = mtgextent[i] * distanceratio / 1000. for t in range(1, nbtests): cshift = p_edir[i] * t * unitshift dist, tshift = test_shift(cshift, dist, tshift) for t in range(1, nbtests): cshift = -p_edir[i] * t * unitshift dist, tshift = test_shift(cshift, dist, tshift) if not tshift is None: print('select', tshift, dist) npos = dict() for vid, pos in list(mtg.property('position').items()): npos[vid] = pos + tshift mtg.property('position').update(npos)
def to_geom_args(self, conversion=1.0, name=None): r"""Get arguments for creating a PlantGL geometry. Args: conversion (float, optional): Conversion factor that should be applied to the vertices. Defaults to 1.0. name (str, optional): Name that should be given to the created PlantGL symbol. Defaults to None and is ignored. Returns: tuple: Class, arguments and keyword arguments for PlantGL geometry. """ import openalea.plantgl.all as pgl smb_class, args, kwargs = super(ObjDict, self).to_geom_args( conversion=conversion, name=name) index_class = pgl.Index3 array_class = pgl.Index3Array # Texture coords if self.get('texcoords', []): obj_texcoords = [] for t in self['texcoords']: obj_texcoords.append(pgl.Vector2(t[0], t[1])) kwargs['texCoordList'] = pgl.Point2Array(obj_texcoords) if self.get('face_texcoords', []): obj_ftexcoords = [] for t in self['face_texcoords']: if (t is not None) and (t[0] is not None): entry = [int(_t) for _t in t] else: entry = [len(self['texcoords']) for _ in range(3)] obj_ftexcoords.append(index_class(*entry)) kwargs['texCoordIndexList'] = array_class(obj_ftexcoords) # Normals if self.get('normals', []): obj_normals = [] for n in self['normals']: obj_normals.append(pgl.Vector3(n[0], n[1], n[2])) kwargs['normalList'] = pgl.Point3Array(obj_normals) if self.get('face_normals', []): obj_fnormals = [] for n in self['face_normals']: if (n is not None) and (n[0] is not None): entry = [int(_n) for _n in n] else: entry = [len(self['normals']) for _ in range(3)] obj_fnormals.append(index_class(*entry)) kwargs['normalIndexList'] = array_class(obj_fnormals) return smb_class, args, kwargs
def __initialiseContext__(context): import openalea.plantgl.all as pgl width = pgl.NurbsCurve2D( ctrlPointList = pgl.Point3Array([(0, 0.0368034, 1),(0.321038, 0.20082, 1),(0.674863, 0.127049, 1),(1, 0.00418017, 1)]) , ) width.name = "width" panel_0 = ({'active': True, 'visible': True, 'name': 'Functions'},[('Function',width)]) import openalea.plantgl.all as pgl nerve = pgl.NurbsCurve2D( ctrlPointList = pgl.Point3Array([(-0.5, 0, 1),(-0.223915, 0.114315, 1),(0.121756, 0.0370409, 1),(0.467244, -0.216243, 1)]) , ) nerve.name = "nerve" section = pgl.NurbsCurve2D( ctrlPointList = pgl.Point3Array([(-0.5, 0, 1),(-0.195355, -0.24554, 1),(0.203326, -0.162142, 1),(0.5, 0, 1)]) , ) section.name = "section" panel_1 = ({'active': True, 'visible': True, 'name': 'Curve2D'},[('Curve2D',nerve),('Curve2D',section)]) parameterset = [panel_0,panel_1,] context["__functions__"] = [('width',width),] context["__curves__"] = [('nerve',nerve),('section',section),] context["__parameterset__"] = parameterset context["width"] = pgl.QuantisedFunction(width) context["nerve"] = nerve context["section"] = section
def fn(change): if 'new' in change: value = change['new'] if isinstance(param, BaseScalar): param.value = value elif isinstance(param, tuple): if isinstance(param[1], (pgl.NurbsCurve2D, pgl.BezierCurve2D)): param[1].ctrlPointList = pgl.Point3Array( [pgl.Vector3(p[0], p[1], 1) for p in value]) elif isinstance(param[1], pgl.Polyline2D): param[1].pointList = pgl.Point2Array( [pgl.Vector2(p[0], p[1]) for p in value]) lsw.set_parameters(lp.dumps())
def _common_init(self, **keys): """ """ if len(keys["points"]) < 3: raise Exception("ACenterPolygon: Too few points in..") self._indexes = [] self._points = pgl.Point3Array([pgl.Vector3()] + keys["points"]) for i in xrange(1, len(keys["points"])): self._points[0] += self._points[i] self._indexes.append(pgl.Index([0, i, i + 1])) self._points[0] += self._points[len(keys["points"])] self._indexes.append(pgl.Index([0, len(keys["points"]), 1])) self._points[0] = self._points[0] / len(keys["points"]) self._indexes = pgl.IndexArray(self._indexes)
def pgl_surface_mesh(self, grid_size=128, grid_resolution=1, potential_value=0.5, color=[190, 205, 205], transparency=0): points, triangles = self.surface_mesh(grid_size, grid_resolution, potential_value) import openalea.plantgl.all as pgl if color is None: color = [np.random.randint(0, 255) for i in xrange(3)] mat = pgl.Material(tuple(color), diffuse=0.25, transparency=transparency) s = pgl.Scene() s += pgl.Shape( pgl.FaceSet( pgl.Point3Array(points), pgl.Index3Array([[int(i) for i in tr] for tr in triangles])), mat) return s
def mangoLeaf(length=1, alpha=0, color=__niceGreen): x = array(arange(0.1, length, 0.1)) y = (-3 / (length * 5.)) * (x**2 / length - x) cos = math.cos(math.radians(alpha / 2.0)) sin = math.sin(math.radians(alpha / 2.0)) list = [] idxList = [] for i in range(len(x)): list.append(pgl.Vector3(x[i], 0, 0)) list.append(pgl.Vector3(x[i], y[i] * cos, y[i] * sin)) list.append(pgl.Vector3(x[i], -y[i] * cos, y[i] * sin)) list.append(pgl.Vector3(0, 0, 0)) list.append(pgl.Vector3(length, 0, 0)) for i in range(len(x) - 1): idxList.append( pgl.Index(3 * (i + 1), 3 * (i + 1) + 1, 3 * i + 1, 3 * i)) idxList.append( pgl.Index(3 * i + 2, 3 * (i + 1) + 2, 3 * (i + 1), 3 * i)) #idxList.append(pgl.Index(3*i,3*i+1,3*(i+1)+1, 3*(i+1))) #idxList.append(pgl.Index(3*i,3*(i+1),3*(i+1)+2,3*i+2)) idxList.append(pgl.Index(0, 1, len(list) - 2)) idxList.append(pgl.Index(2, 0, len(list) - 2)) idxList.append( pgl.Index(3 * (len(x) - 1) + 1, 3 * (len(x) - 1), len(list) - 1)) idxList.append( pgl.Index(3 * (len(x) - 1), 3 * (len(x) - 1) + 2, len(list) - 1)) #idxList.append(pgl.Index(len(list)-2, 1, 0)) #idxList.append(pgl.Index(len(list)-2, 0, 2)) #idxList.append(pgl.Index(len(list)-1, 3*(len(x)-1), 3*(len(x)-1)+1)) #idxList.append(pgl.Index(len(list)-1, 3*(len(x)-1)+2, 3*(len(x)-1))) p3r = pgl.Point3Array(list) ir = pgl.IndexArray(idxList) fs = pgl.FaceSet(p3r, ir) return pgl.Shape(fs, color)
def scale_and_center(points, mtg): import openalea.plantgl.all as pgl if type(mtg) != pgl.Point3Array: mtgpoints = pgl.Point3Array(list(mtg.property('position').values())) else: mtgpoints = mtg pointextent = pgl.norm(points.getExtent()) mtgextent = pgl.norm(mtgpoints.getExtent()) scaleratio = mtgextent / pointextent m_center = mtgpoints.getCenter() p_center = points.getCenter() from math import log scale = 1. / pow(10, round(log(scaleratio, 10))) def transform(v): return ((v - m_center) * scale) + p_center npos1 = dict([(vid, transform(pos)) for vid, pos in list(mtg.property('position').items())]) mtg.property('position').update(npos1)
def on_param_changed(change): if 'new' in change: value = change['new'] name = change['name'] if isinstance(param, BaseScalar): if name == 'name': param.name = value else: param.value = value elif isinstance(param, tuple): if name == 'value': if isinstance(param[1], (pgl.NurbsCurve2D, pgl.BezierCurve2D)): param[1].ctrlPointList = pgl.Point3Array( [pgl.Vector3(p[0], p[1], 1) for p in value]) elif isinstance(param[1], pgl.Polyline2D): param[1].pointList = pgl.Point2Array( [pgl.Vector2(p[0], p[1]) for p in value]) else: param[1].name = value if self.__auto_apply: self.on_lpy_context_change(self.__lp.dumps()) if self.__auto_save: self.__save()
def to_geom_args(self, conversion=1.0, name=None): # pragma: lpy r"""Get arguments for creating a PlantGL geometry. Args: conversion (float, optional): Conversion factor that should be applied to the vertices. Defaults to 1.0. name (str, optional): Name that should be given to the created PlantGL symbol. Defaults to None and is ignored. Returns: tuple: Class, arguments and keyword arguments for PlantGL geometry. """ import openalea.plantgl.all as pgl smb_class, args, kwargs = super(ObjDict, self).to_geom_args( conversion=conversion, name=name, _as_obj=True) index_class = pgl.Index array_class = pgl.IndexArray # Texture coords if self.get('texcoords', []): obj_texcoords = [] for t in self['texcoords']: obj_texcoords.append( pgl.Vector2(np.float64(t['u']), np.float64(t.get('v', 0.0)))) kwargs['texCoordList'] = pgl.Point2Array(obj_texcoords) obj_ftexcoords = [] for i, f in enumerate(self['faces']): entry = [] for _f in f: if 'texcoord_index' not in _f: if i > 0: warnings.warn( ("'texcoord_index' missing from face" + "%d, texcoord indices will be " + "ignored.") % i) obj_ftexcoords = [] entry = [] break entry.append(int(_f['texcoord_index'])) if not entry: break obj_ftexcoords.append(index_class(*entry)) if obj_ftexcoords: kwargs['texCoordIndexList'] = array_class(obj_ftexcoords) # Normals if self.get('normals', []): obj_normals = [] for n in self['normals']: obj_normals.append( pgl.Vector3(np.float64(n['i']), np.float64(n['j']), np.float64(n['k']))) kwargs['normalList'] = pgl.Point3Array(obj_normals) obj_fnormals = [] for i, f in enumerate(self['faces']): entry = [] for _f in f: if 'normal_index' not in _f: if i > 0: warnings.warn( ("'normal_index' missing from face" + "%d, normal indices will be " + "ignored.") % i) obj_fnormals = [] entry = [] break entry.append(int(_f['normal_index'])) if not entry: break obj_fnormals.append(index_class(*entry)) if obj_fnormals: kwargs['normalIndexList'] = array_class(obj_fnormals) return smb_class, args, kwargs
def createDefaultObject(self, subtype=None): import openalea.plantgl.all as pgl nbP = 4 return pgl.NurbsCurve2D( pgl.Point3Array([(float(i) / (nbP - 1), 0) for i in range(nbP)], 1))
try:
def alignGlobally(points, mtg, verbose=False): import openalea.plantgl.all as pgl import numpy as np from .pointprocessing import np_inertia_axis mtgpoints = pgl.Point3Array(list(mtg.property('position').values())) axispoints = np_inertia_axis(points, verbose=verbose) axismtg = np_inertia_axis(mtgpoints, verbose=verbose) p_eval, p_edir, p_center = axispoints m_eval, m_edir, m_center = axismtg pointextent = pgl.norm(points.getExtent()) mtgextent = pgl.norm(mtgpoints.getExtent()) scaleratio = mtgextent / pointextent from math import log scale = 1. / pow(10, round(log(scaleratio, 10))) normalizeorientation = True checkorientation = True if normalizeorientation: def normalize_frame(edir): a, b = edir[0], edir[1] c = np.cross(a, b) return np.array([a, np.cross(c, a), c]) p_edir = normalize_frame(p_edir) m_edir = normalize_frame(m_edir) if verbose: print('Point center :', p_center) print('MTG center :', m_center) print('Point axis :', p_edir) print('MTG axis :', m_edir) print('Point variance :', p_eval) print('MTG variance :', m_eval) def transform(v, t_edir): v = (v - m_center) nval = [pgl.dot(v, ed) for ed in m_edir] nv = sum([val * ed for val, ed in zip(nval, t_edir)], pgl.Vector3(0, 0, 0)) return (nv + p_center) ppos = mtg.property('position').copy() npos1 = dict([(vid, transform(pos, p_edir)) for vid, pos in list(ppos.items())]) #npos1 = dict([(vid, pos*scale) for vid, pos in ppos.items()]) mtg.property('position').update(npos1) if checkorientation: if verbose: print('check orientation') from .mtgmanip import mtg2pgltree nodes, parents, vertex2node = mtg2pgltree(mtg) dist1 = pgl.average_distance_to_shape(points, nodes, parents, [0 for i in range(len(nodes))]) if verbose: print('check flipped orientation') p_edir2 = np.array( [-p_edir[0], -p_edir[1], np.cross(-p_edir[0], -p_edir[1])]) npos2 = dict([(vid, transform(pos, p_edir2)) for vid, pos in list(ppos.items())]) mtg.property('position').update(npos2) nodes, parents, vertex2node = mtg2pgltree(mtg) dist2 = pgl.average_distance_to_shape(points, nodes, parents, [0 for i in range(len(nodes))]) if verbose: print(dist1, dist2) if dist1 < dist2: if verbose: print('Use first orientation') mtg.property('position').update(npos1) else: if verbose: print('Use flipped orientation')