Ejemplo n.º 1
0
def test_scene(s):
    tesselator = pgl.Tesselator()
    d = s.todict()
    for pid, pgl_objects in d.iteritems():
        for shape in pgl_objects:
            if not shape.apply(tesselator):
                print(pid)
Ejemplo n.º 2
0
def get_height(scene_geometry):
    """ Calculate the height of objects in the scene
    
    Find the coordinates of the points that compose the object and 
    compute the mean of the height coordinates, for each object
    in the scene.
    
    Parameters
    ----------
    scene_geometry: dict([id, geometry])
        Dictionnary of geometries of objects in the scene.
    """
    heights = {}
    tesselator = pgl.Tesselator()
    for vid, shapes in scene_geometry.items():
        S = []
        H = []
        if not _is_iterable(shapes):
            shapes = [shapes]
        for shape in shapes:
            shape.apply(tesselator)
            mesh = tesselator.triangulation
            itri = list(range(mesh.indexListSize()))
            H += [mesh.faceCenter(i)[2] for i in itri]
        heights.update({vid: H})
    return heights
Ejemplo n.º 3
0
def as_scene_mesh(pgl_scene):
    """ Transform a PlantGL scene / PlantGL shape dict to a scene_mesh"""
    tesselator = pgl.Tesselator()

    if isinstance(pgl_scene, pgl.Scene):
        sm = {}

        def _concat_mesh(mesh1,mesh2):
            v1, f1 = mesh1
            v2, f2 = mesh2
            v = numpy.array(v1.tolist() + v2.tolist())
            offset = len(v1)
            f = numpy.array(f1.tolist() + [[i + offset, j + offset, k + offset] for i, j, k
                               in f2.tolist()])
            return v, f

        for pid, pgl_objects in pgl_scene.todict().iteritems():
            sm[pid] = reduce(_concat_mesh, [shape_mesh(pgl_object, tesselator) for pgl_object in
                           pgl_objects])
        return sm
    elif isinstance(pgl_scene, dict):
        return {sh_id: shape_mesh(sh,tesselator) for sh_id, sh in
                pgl_scene.iteritems()}
    else:
        return pgl_scene
Ejemplo n.º 4
0
def get_source_leaf_and_max_height(g,
                                   position='center',
                                   relative_height=2. / 3):
    tesselator = pgl.Tesselator()
    bbc = pgl.BBoxComputer(tesselator)
    leaves = get_leaves(g, label='LeafElement')
    centroids = g.property('centroid')
    geometries = g.property('geometry')
    targets = list(leaf for leaf in leaves if leaf in geometries.iterkeys())
    for vid in targets:
        if is_iterable(geometries[vid]):
            bbc.process(pgl.Scene(geometries[vid]))
        else:
            bbc.process(pgl.Scene([pgl.Shape(geometries[vid])]))
        center = bbc.result.getCenter()
        centroids[vid] = center
    zmax = max(centroids.items(), key=lambda x: x[1][2])[1][2]
    distances = {
        vid: pgl.norm(centroids[vid] - (0, 0, relative_height * zmax))
        for vid in centroids
    }
    if position == 'center':
        return min(distances.items(), key=lambda x: x[1])[0], zmax
    elif position == 'border':
        return max(distances.items(), key=lambda x: x[1])[0], zmax
Ejemplo n.º 5
0
def get_area_and_normal(scene_geometry):
    def _surf(ind, pts):
        A, B, C = [pts[i] for i in ind]
        return pgl.norm(pgl.cross(B - A, C - A)) / 2.0

    def _normal(ind, pts):
        A, B, C = [pts[i] for i in ind]
        n = pgl.cross(B - A, C - A)
        return n.normed()

    tesselator = pgl.Tesselator()
    areas = {}
    normals = {}
    for vid, shapes in scene_geometry.items():
        S = []
        norm = []
        if not _is_iterable(shapes):
            shapes = [shapes]
        for shape in shapes:
            shape.apply(tesselator)
            mesh = tesselator.triangulation
            itri = list(range(mesh.indexListSize()))
            pts = mesh.pointList
            S += [_surf(mesh.indexAt(i), pts) for i in itri]
            norm += [_normal(mesh.indexAt(i), pts) for i in itri]
        areas.update({vid: S})
        normals.update({vid: norm})
    return areas, normals
Ejemplo n.º 6
0
 def get_leaf_height(self, leaf_geom):
     from openalea.plantgl import all as pgl
     tesselator = pgl.Tesselator()
     bbc = pgl.BBoxComputer(tesselator)
     if self.is_iterable(leaf_geom):
         bbc.process(pgl.Scene(leaf_geom))
     else:
         bbc.process(pgl.Scene([pgl.Shape(leaf_geom)]))
     return bbc.result.getCenter()[2]
Ejemplo n.º 7
0
def domain3D(domain2D, scene):
    t = pgl.Tesselator()
    bbc = pgl.BBoxComputer(t)
    bbc.process(scene)
    bbox = bbc.result

    z_base = bbox.getZMin()
    z_top = bbox.getZMax()
    domain3D = (domain2D[0] + (z_base, ), domain2D[1] + (z_top, ))
    return domain3D
Ejemplo n.º 8
0
def pgl_to_triangles(pgl_object, tesselator=None):
    triangles = []
    if tesselator is None:
        tesselator = pgl.Tesselator()
    pgl_object.apply(tesselator)
    mesh = tesselator.triangulation
    if mesh:
        pts = numpy.array(mesh.pointList, ndmin=2)
        indices = numpy.array(mesh.indexList, ndmin=2)
        triangles = [_triangle(itri, pts) for itri in indices]
    return triangles
Ejemplo n.º 9
0
def pgl_to_triangles(pgl_object, tesselator=None):
    triangles = []
    if tesselator is None:
        tesselator = pgl.Tesselator()
    pgl_object.apply(tesselator)
    mesh = tesselator.triangulation
    if mesh:
        indices = mesh.indexList
        pts = list(map(tuple, mesh.pointList))
        triangles = [(pts[itri[0]], pts[itri[1]], pts[itri[2]])
                     for itri in indices]
    return triangles
Ejemplo n.º 10
0
def surfPerTriangle(sc):
  """return an array of center, surface cople for every triangle in the scene"""
  res = []
  t = pgl.Tesselator()
  for sh in sc:
    sh.geometry.apply(t)
    d = t.triangulation
    for i in range(d.indexListSize()):
      center = (d.pointAt(i,0)+d.pointAt(i,1)+d.pointAt(i,2))/3
      surf = pgl.surface (d.pointAt(i,0),d.pointAt(i,1),d.pointAt(i,2))
      res += [(center,surf)]
  return res 
Ejemplo n.º 11
0
 def __init__(self, camera = {'type':'perspective', 'distance':1., 'fov':45.,  'xc':0., 'yc':0., 'azimuth':0, 'zenith':0.}, image_width = 320, image_height = 280, background = (0,0,0), light_position = (10,0,10), light_color=(1,1,1), working_dir = None):
     """ Setup a Povray instance
     
     :Parameters:
         - camera: a dict of parameters for positioning the camera
             - distance: distance from the position of the camera to the look_at point
             - fov : angle corresponding to the width of the image
             - xc, yc : coordinates of the center of the scene
             - azimuth: angle in degree around the vertical axis. az=0. is equialent to have the width of the image align to X direction of the scene
             - zenith: angle between the view direction and the vertical
         - image_width: width of the final image in pixel
         - image_height: height of the final image in pixel
         - working_dir: A directory for storing povary files. If None, (default),  a temporary directory will be created and removed onece the instance is deleted
         
     """
 
     try: 
         if working_dir is not None:
             self.wdir=path(path(working_dir).abspath())
             if not self.wdir.exists():
                 self.wdir.mkdir() 
             self.cleanup_wdir = False
         else:
             # build a temporary directory
             self.wdir = path(tempfile.mkdtemp())
             self.cleanup_wdir = True
     except:
         raise PovRayError("PovRay can't create its working directory : check for read/write permission or security level")
     
     if platform.system() is 'Windows':
         self.cmdline = 'pvengine +FN +I%s +H%d +W%d -d /exit'
     else:
         self.cmdline = 'povray +FN +I%s +H%d +W%d'
         
     
     self.image_width = image_width
     self.image_height = image_height
     self.camera = camera
     self.light_position = light_position
     self.light_color = light_color
     self.background = background
     
     self.soil = False
     self.rendered_image_path = None
     self.tesselator = pgl.Tesselator()
     
     #to be removed once cv_camera has been properly integrated
     self.user_camera = None
Ejemplo n.º 12
0
def StemElement_mesh(length, diameter_base, diameter_top, classic=False):
    """ Compute mesh for a stem element
        - classic indicates
    """
    if classic:
        solid = True
        diameter = diameter_base
        slices = 6  # 6 is the minimal number of slices for a correct computation of star (percentage error lower than 5)
        stem = pgl.Tapered(diameter_base / 2., diameter_top / 2.,
                           pgl.Cylinder(1., length, solid, slices))
        tessel = pgl.Tesselator()
        stem.apply(tessel)
        mesh = tessel.triangulation
    else:
        mesh = slim_cylinder(length, diameter_base / 2., diameter_top / 2.)

    return mesh
Ejemplo n.º 13
0
def bbox(pgl_scene, scene_unit='m'):
    """ Bounding box of a pgl scene"""
    tesselator = pgl.Tesselator()
    bbc = pgl.BBoxComputer(tesselator)
    bbc.process(pgl_scene)
    box = bbc.result
    xmin, ymin, zmin = box.getXMin(), box.getYMin(), box.getZMin()
    xmax, ymax, zmax = box.getXMax(), box.getYMax(), box.getZMax()
    if scene_unit != 'm':
        units = {'mm': 0.001, 'cm': 0.01, 'dm': 0.1, 'm': 1, 'dam': 10,
                 'hm': 100,
                 'km': 1000}
        convert = units.get(scene_unit, 1)
        xmin, ymin, zmin = numpy.array((xmin, ymin, zmin)) * convert
        xmax, ymax, zmax = numpy.array((xmax, ymax, zmax)) * convert

    return (xmin, ymin, zmin), (xmax, ymax, zmax)
Ejemplo n.º 14
0
def get_source_leaf(g, position_source=2./3):
    tesselator = pgl.Tesselator()
    bbc = pgl.BBoxComputer(tesselator)
    leaves = get_leaves(g, label='LeafElement')
    centroids = g.property('centroid')
    geometries = g.property('geometry')
    targets = list(leaf for leaf in leaves if leaf in geometries.iterkeys())
    for vid in targets:
        if isinstance(geometries[vid], collections.Iterable):
            bbc.process(pgl.Scene(geometries[vid]))
        else:
            bbc.process(pgl.Scene([pgl.Shape(geometries[vid])]))
        center = bbc.result.getCenter()
        centroids[vid] = center
    zmax = max(centroids.items(), key=lambda x:x[1][2])[1][2]
    distances = {vid:pgl.norm(centroids[vid]-(0,0,position_source*zmax)) for vid in centroids}
    return min(distances.items(), key=lambda x:x[1])[0]
Ejemplo n.º 15
0
def surfPerLeaf(sc):
  """return an array of center, surface cople for every leaf in the scene"""
  res = []
  t = pgl.Tesselator()
  for sh in sc:
    sh.geometry.apply(t)
    d = t.triangulation
    res2=[]
    lcenter = pgl.Vector3( 0,0,0 )
    for i in range(d.indexListSize()):
      lcenter += (d.pointAt(i,0)+d.pointAt(i,1)+d.pointAt(i,2))/3
      surf = pgl.surface (d.pointAt(i,0),d.pointAt(i,1),d.pointAt(i,2)) #where in openalea.plantgl ??
      res2 += [surf]
    lcenter /= len( res2 )
    lsurf=sum( res2 )
    res+=[ ( lcenter, lsurf ) ]
  return res 
Ejemplo n.º 16
0
    def leaves_in_grid(self, g, label='LeafElement'):
        geometries = g.property('geometry')
        centroids = g.property('centroid')
        tesselator = pgl.Tesselator()
        bbc = pgl.BBoxComputer(tesselator)
        leaves = get_leaves(g, label=label)
        leaves = [l for l in leaves if l in geometries]

        # Get centroids
        def centroid(vid):
            if is_iterable(geometries[vid]):
                bbc.process(pgl.Scene(geometries[vid]))
            else:
                bbc.process(pgl.Scene([pgl.Shape(geometries[vid])]))
            center = bbc.result.getCenter()
            centroids[vid] = center

        if len(leaves) > 0:
            for vid in leaves:
                centroid(vid)

            # Define grid (horizontal layers)
            zs = [c[2] for c in centroids.itervalues()]
            minz = min(zs)
            maxz = max(zs) + self.layer_thickness
            layers = {
                l: []
                for l in np.arange(minz, maxz, self.layer_thickness)
            }

            # Distribute leaves in layers
            for vid, coords in centroids.iteritems():
                z = coords[2]
                ls = layers.keys()
                i_layer = np.where(
                    map(
                        lambda x: x <= z < x + self.layer_thickness
                        if z != maxz - self.layer_thickness else x <= z <= x +
                        self.layer_thickness, ls))[0]
                if len(i_layer) > 0.:
                    layers[ls[i_layer]].append(vid)

            self.layers = layers
        else:
            self.layers = {}
Ejemplo n.º 17
0
def mtg_to_cscene(g, property_name='geometry'):
    """Build a caribu-compatible scene from a mtg encoding geometries

    Args:
        g: an openalea.mtg.mtg.MTG instance
        property_name: (str) the name of the property in g where plantGL geometries are encoded

    Returns:
        a {primitive_id: [triangles,]} dict.A triangle is a 3-tuple of 3-tuples points coordinates
        primitive_id is the vertex id.

    """
    geometry = g.property(property_name)
    tesselator = pgl.Tesselator()
    cscene = {}
    for pid in geometry:
        cscene[pid] = pgl_to_triangles(geometry[pid], tesselator)

    return cscene
Ejemplo n.º 18
0
def scene_to_cscene(scene):
    """ Build a caribu-compatible scene from a PlantGl scene

    Args:
        scene: an openalea.plantgl.all.Scene instance

    Returns:
        a {primitive_id: [triangles,]} dict.A triangle is a 3-tuple of 3-tuples points coordinates
        primitive_id is taken as the index of the shape in the scene shape list.

    """

    cscene = {}
    tesselator = pgl.Tesselator()
    for pid, pgl_objects in scene.todict().iteritems():
        tri_list = sum([
            pgl_to_triangles(pgl_object, tesselator)
            for pgl_object in pgl_objects
        ], [])
        if len(tri_list) > 0:
            cscene[pid] = tri_list
    return cscene
Ejemplo n.º 19
0
def test_pgl_scene():
    g = potted_syrah()
    bc = pgl.BBoxComputer(pgl.Tesselator())

    s = energy.pgl_scene(g)
    bc.process(s)
    bbox = bc.boundingbox
    zmin, zmax = bbox.getZMin(),bbox.getZMax()
    assert zmax > zmin > 0

    s = energy.pgl_scene(g, flip=True)
    bc.process(s)
    bbox = bc.boundingbox
    zmin, zmax = bbox.getZMin(),bbox.getZMax()
    assert 0 > zmax > zmin

    # check that original scene is still z >0
    s = energy.pgl_scene(g)
    bc.process(s)
    bbox = bc.boundingbox
    zmin, zmax = bbox.getZMin(), bbox.getZMax()
    assert zmax > zmin > 0
Ejemplo n.º 20
0
""" Gather different strategies for modeling dispersal of fungus propagules.
Ejemplo n.º 21
0
def my_distance(n, sectors):
    """ Compute the distance with infectable sectors. """
    if 'distance' not in n._g._properties:
        n._g.add_property('distance')
    tesselator = pgl.Tesselator()
    bbc = pgl.BBoxComputer(tesselator)

    def base(geom):
        if geom:
            pts = geom.pointList
            if pts:
                n = len(pts)
                assert n % 2 == 0
                return 1 / 2 * (pts[0] + pts[n / 2])

    def top(geom):
        if geom:
            pts = geom.pointList
            if pts:
                n = len(pts)
                assert n % 2 == 0
                return 1 / 2 * (pts[n / 2 - 1] + pts[-1])

    def bbox_distance(g1, g2):

        bbc.process(pgl.Scene([g1]))
        bbox1 = bbc.result
        bbc.process(pgl.Scene([g2]))
        bbox2 = bbc.result

        # TODO bbox.lowerLeftCorner, bbox.upperRightCorner
        return bbox1.distance(bbox2)

    def mesh_distance(g1, g2):
        pts1 = g1.pointList
        pts2 = g2.pointList
        if pts1 and pts2:
            d = maxint
            for pt in pts2:
                p1, i = pts1.findClosest(pt)
                # TODO: To Fix
                d = pgl.norm(pt - p1)
                return d
        else:
            return maxint

    def lovel_distance(g1, g2):
        p1 = base(g1)
        p2 = top(g2)
        return pgl.norm(p2 - p1)

    def opt_distance(n1, n2):
        g1 = n1.geometry
        g2 = n2.geometry
        if not g1 or not g2:
            return maxint
        if DISTANCE == 'BOX':
            return bbox_distance(g1, g2)
        elif DISTANCE == 'LOVEL':
            return lovel_distance(g1, g2)
        elif DISTANCE == 'MESH':
            return mesh_distance(g1, g2)

    dists = [opt_distance(n, source) for source in sectors]
    dist = min(dists) if dists else maxint

    if not n.distance:
        n.distance = []
    if dist != maxint:
        n.distance.append((n.age, dist))

    print n, dist
    if dist <= 1:
        n.color = 0, 0, 255
Ejemplo n.º 22
0
 def __init__(self, database, seed=None):
     #self.database = database
     self.database = []
     self.tessel = pgl.Tesselator()
     self.seed = seed
Ejemplo n.º 23
0
    def fit_grid(self, z_adaptive=False):
        """ Find grid parameters that fit the scene in the RATP grid
        """

        # fit regular grid to scene
        if self.scene is None:
            nbx, nby, nbz = self.grid_shape
            dx, dy, dz = self.grid_resolution  # already in meter
            xo, yo, zo = 0, 0, 0  # origin
        else:
            # Find the bounding box that fit the scene
            tesselator = pgl.Tesselator()
            bbc = pgl.BBoxComputer(tesselator)
            bbc.process(self.scene)
            bbox = bbc.result
            zsoil = self.z_soil
            if zsoil is None:
                zsoil = bbox.getZMin()

            if self.domain is None:
                xo = bbox.getXMin() * self.convert  # origin
                yo = bbox.getYMin() * self.convert
            else:
                xo = self.domain[0][0] * self.convert
                yo = self.domain[0][1] * self.convert
            zo = zsoil * self.convert

            if self.grid_resolution is not None and self.grid_shape is not None:
                nbx, nby, nbz = self.grid_shape
                dx, dy, dz = self.grid_resolution  # already in meter
            else:
                if self.domain is None:
                    xmax = bbox.getXMax() * self.convert
                    ymax = bbox.getYMax() * self.convert
                else:
                    xmax = self.domain[1][0] * self.convert
                    ymax = self.domain[1][1] * self.convert
                zmax = bbox.getZMax() * self.convert
                if self.grid_resolution is None:
                    nbx, nby, nbz = self.grid_shape
                    if self.domain is None:
                        if nbx > 1:
                            dx = (xmax - xo) / float(
                                nbx - 1
                            )  # use nbx -1 to ensure min and max are in the grid
                        else:
                            dx = (xmax - xo) * 1.01
                        if nby > 1:
                            dy = (ymax - yo) / float(nby - 1)
                        else:
                            dy = (ymax - yo) * 1.01
                    else:
                        dx = (xmax - xo) / float(
                            nbx
                        )  #toric canopies allows coordinate outside the pattern
                        dy = (ymax - yo) / float(nby)
                    if nbz > 1:
                        dz = (zmax - zo) / float(nbz - 1)
                    else:
                        dz = (zmax - zo) * 1.01
                    # try to accomodate flat scene
                    if dz == 0:
                        dz = (dx + dy) / 2.
                    if dx == 0:
                        dx = (dy + dz) / 2.
                    if dy == 0:
                        dy = (dx + dz) / 2.
                if self.grid_shape is None:
                    dx, dy, dz = self.grid_resolution
                    if self.domain is None:
                        nbx = int(numpy.ceil((xmax - xo) / float(dx)))
                        nby = int(numpy.ceil((ymax - yo) / float(dy)))
                    else:  #dx,dy,dz are adjusted to fit the domain exactly
                        nbx = int((xmax - xo) / float(dx))
                        nby = int((ymax - yo) / float(dy))
                        dx = (xmax - xo) / float(nbx)
                        dy = (ymax - yo) / float(nby)
                    nbz = int(numpy.ceil((zmax - zo) / float(dz)))
                # balance extra-space between both sides of the grid (except z i zsoil has been set)
                extrax = dx * nbx - (xmax - xo)
                xo -= (extrax / 2.)
                extray = dy * nby - (ymax - yo)
                yo -= (extray / 2.)
                if self.z_soil is None:
                    extraz = dz * nbz - (zmax - zo)
                    zo -= (extraz / 2.)

        # dz for all voxels
        if self.z_resolution is not None:
            dz = self.z_resolution[::-1]  # dz is from top to base for ratp
            nbz = len(dz)
        else:
            dz = [dz] * nbz

        grid_pars = {
            'njx': nbx,
            'njy': nby,
            'njz': nbz,
            'dx': dx,
            'dy': dy,
            'dz': dz,
            'xorig': xo,
            'yorig': yo,
            'zorig': -zo
        }  # zorig is a z offset in grid.py (grid_z = z + zo)

        return grid_pars
Ejemplo n.º 24
0
def shape_mesh(pgl_shape, tesselator=None):
    if tesselator is None:
        tesselator = pgl.Tesselator()
    tesselator.process(pgl_shape)
    tset = tesselator.result
    return numpy.array(tset.pointList), numpy.array(tset.indexList)