def build_geometry(elements): plants = {} soil = {} indexes = [] print('number of elements', len(elements)) for i, (label, triangle) in enumerate(elements): pid = plant_id(label) if pid not in plants: plants[pid] = {"leaves": {}, "stems": pgl.TriangleSet([], [])} plant = plants[pid] if is_leaf(label): lid = leaf_id(label) leaves = plant['leaves'] if lid not in leaves: leaves[lid] = pgl.TriangleSet([], []) shape = leaves[lid] elif is_stem(label): shape = plant['stems'] else: assert is_soil(label) if "soil" not in soil: soil["soil"] = pgl.TriangleSet([], []) shape = soil["soil"] count = len(shape.pointList) shape.pointList.append(triangle[0]) shape.pointList.append(triangle[1]) shape.pointList.append(triangle[2]) shape.indexList.append(pgl.Index3(count, count + 1, count + 2)) indexes.append((label, count)) return CanestraScene(plants, soil, indexes)
def mesh2shapes(scene): """ Convert all the meshes containing colors into independent shapes. """ if isinstance(scene, pgl.Scene): scene = scene else: # Case caribu scene scene = scene.scene new_scene = pgl.Scene() for shape in scene: g = shape.geometry if isinstance(g, pgl.TriangleSet) and len(g.colorList) > 0: # convert the mesh into shapes with different colors pts = g.pointList indx = g.indexList colors = g.colorList for i, ind in enumerate(indx): new_geom = pgl.TriangleSet([], []) new_geom.indexList.append(pgl.Index3(0, 1, 2)) for k in ind: new_geom.pointList.append(pts[k]) _shape = pgl.Shape(new_geom, pgl.Material(pgl.Color3(colors[i]))) new_scene.add(_shape) else: new_scene.add(shape) return new_scene,
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 Parallelogram(self, length=1., width=0.5, **kwds): length = float(length) width = float(width) # pts = [Vector3(0,0,0), Vector3(length,0,0),Vector3(length, width,0),Vector3(0,width, 0)] pts = [Vector3(0, 0, 0), Vector3(width, 0, 0), Vector3(width, 0, length), Vector3(0, 0, length)] index = [(0, 1, 2), (0, 2, 3)] return (pgl.TriangleSet(pts, index), 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 addSets(pglset1, pglset2, translate=(0, 0, 0)): """ create a new TriangleSet by addition of two existing ones if translate is not None, pglset2 is translated with vector translate """ points = as_tuples(pglset1.pointList) + as_tuples(pglset2.pointList, offset=translate) index = as_tuples(pglset1.indexList) + as_tuples( pglset2.indexList, offset=len(pglset1.pointList)) return pgl.TriangleSet(points, index)
def normal(set): pts = set.pointList indices = set.indexList geoms = [] for index in indices: i1, i2, i3 = index p1, p2, p3 = pts[i1], pts[i2], pts[i3] pt_bary = (p1 + p2 + p3) / 3. n = (p2 - p1) ^ (p3 - p1) geoms.append(pgl.TriangleSet([p1, p2, p3], [(0, 1, 2)])) geoms.append(pgl.Polyline([pt_bary, pt_bary + n])) return geoms
def plot_spline_surface(ctrl_net, points): """ Parameters ========== - ctrl_net : the net of control points (list of list) - points : a set of evaluated points (list of list) """ scene = pgl.Scene() n = len(points) m = len(points[0]) # Compute a mesh (i.e. TriangleSet) for the set of points pointList = [pt for rank in points for pt in rank] indexList = [] for i in range(n - 1): for j in range(m - 1): ii = i * m + j i1 = (ii, ii + 1, ii + m) i2 = (ii + 1, ii + m + 1, ii + m) indexList.append(i1) indexList.append(i2) surf = pgl.Shape(pgl.TriangleSet(pointList, indexList), appearance=pgl.Material((12, 125, 12))) scene.add(surf) # plot the control net n = len(ctrl_net) m = len(ctrl_net[0]) for pts in ctrl_net: crv = pgl.Shape(geometry=pgl.Polyline(pts), appearance=pgl.Material((125, 12, 12))) scene.add(crv) for pt in pts: scene.add( pgl.Shape( pgl.Translated(pgl.Vector3(pt), pgl.Sphere(radius=0.1)))) for i in range(m): pts = [ctrl_net[j][i] for j in range(n)] crv = pgl.Shape(geometry=pgl.Polyline(pts), appearance=pgl.Material((12, 12, 125))) scene.add(crv) pgl.Viewer.display(scene)
def __init__( self, **keys ): """ Default constructor. Parameters: pos : Vector3 convertable the shared translation T of each point creating a surface, axis : Vector3 convertable the shared rotation axis A of each point around. Zero element for the rotation axis is OZ. roll : Vector3 convertable the shared "roll angle" R of each point creating a surface around axis, points : Vector3 convertable tuple the list of *ordered* points positions, """ self._common_init( **keys ) AShape3D.__init__( self, geometry=pgl.TriangleSet( self._points, self._indexes ), axis=axis, **keys )
def slim_cylinder(length, radius_base, radius_top): " Try to construct a cylinder with a low number of triangles. " rb, rt = radius_base, radius_top a1, a2, a3 = 0, 2 * pi / 3., 4 * pi / 3. r = rb p1 = (r * cos(a1), r * sin(a1), 0) p2 = (r * cos(a2), r * sin(a2), 0) p3 = (r * cos(a3), r * sin(a3), 0) r = rt q1 = (r * cos(a1 + pi), r * sin(a1 + pi), length) q2 = (r * cos(a2 + pi), r * sin(a2 + pi), length) q3 = (r * cos(a3 + pi), r * sin(a3 + pi), length) set = pgl.TriangleSet([p1, p2, p3, q1, q2, q3], [(2, 1, 0), (3, 4, 5), (0, 5, 4), (0, 4, 2), (2, 4, 3), (3, 1, 2), (1, 3, 5), (5, 0, 1)]) return set
def from_scene_mesh(scene_mesh, colors=None): plant_color = (0, 180, 0) if colors is None: colors = {k: plant_color for k in scene_mesh} scene = pgl.Scene() for sh_id, mesh in scene_mesh.iteritems(): vertices, faces = mesh if isinstance(colors[sh_id], tuple): r, g, b = colors[sh_id] color_list = [pgl.Color4(r, g, b, 0)] * len(faces) else: color_list = [pgl.Color4(r, g, b, 0) for r, g, b in colors[sh_id]] shape = pgl.TriangleSet(vertices, faces) shape.colorList = color_list shape.colorPerVertex = False shape.id = sh_id scene += shape return scene
def generate_scene(triangle_scene, colors=None, soil=None, soil_colors=None): """ Build a colored PlantGL scene Args: triangle_scene: (dict of list of list of tuples) a {primitive_id: [triangles, ]} dict, each triangle being defined by an ordered triplet of 3-tuple points coordinates. colors: (dict of list of tuples) : a {primitive_id: [colors,]} dict defining colors of primitives in the scene. A color is a (r, g, b) tuple. soil: (list of triangles) : a list of triangles of the soil soil_colors : a list of (r, g, b) tuples defining the colors of the soil triangles Returns: A plantGL scene of colored shapes """ plant_color = (0, 180, 0) soil_color = (170, 85, 0) missing_color = (0, 0, 0) scene = pgl.Scene() if colors is None: colors = { k: [plant_color] * len(triangle_scene[k]) for k in triangle_scene } else: colors = { k: colors.get(k, [missing_color] * len(triangle_scene[k])) for k in triangle_scene } for k, triangles in triangle_scene.items(): shape = pgl.TriangleSet([], []) shape.colorList = [] shape.colorPerVertex = False shape.id = k for i, triangle in enumerate(triangles): shape.pointList.append(pgl.Vector3(triangle[0])) shape.pointList.append(pgl.Vector3(triangle[1])) shape.pointList.append(pgl.Vector3(triangle[2])) shape.indexList.append(pgl.Index3(3 * i, 3 * i + 1, 3 * i + 2)) r, g, b = colors[k][i] shape.colorList.append(pgl.Color4(r, g, b, 0)) scene += shape if soil is not None: if soil_colors is None: soil_colors = [soil_color] * len(soil) sid = max([sh.id for sh in scene]) shape = pgl.TriangleSet([], []) shape.colorList = [] shape.colorPerVertex = False shape.id = sid for i, triangle in enumerate(soil): shape.pointList.append(pgl.Vector3(triangle[0])) shape.pointList.append(pgl.Vector3(triangle[1])) shape.pointList.append(pgl.Vector3(triangle[2])) shape.indexList.append(pgl.Index3(3 * i, 3 * i + 1, 3 * i + 2)) r, g, b = soil_colors[i] shape.colorList.append(pgl.Color4(r, g, b, 0)) scene += shape return scene
def plantgl_shape(points, indices): indices = [map(int, index) for index in indices] return pgl.TriangleSet(points, indices, normalPerVertex=False)