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
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]
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
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]
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)
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 = {}
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
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
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
""" Gather different strategies for modeling dispersal of fungus propagules.