Пример #1
0
def kdtree_closest(point, kdtree, depth=0):

    if isinstance(kdtree, KDNode):
        dim = kdtree.axis

        if point[dim] < kdtree.pivot[dim]:
            point_kdtree, opposite_kdtree = kdtree.left_child, kdtree.right_child
        else:
            point_kdtree, opposite_kdtree = kdtree.right_child, kdtree.left_child

        best_candidate = kdtree_closest(point, point_kdtree)
        best_distance = pgl.norm(point - best_candidate)

        if best_distance > abs(point[dim] - kdtree.pivot[dim]):

            if best_distance > pgl.norm(point - kdtree.pivot):
                best_candidate = kdtree.pivot
                best_distance = pgl.norm(point - best_candidate)

            opp_candidate = kdtree_closest(point, opposite_kdtree)
            opp_distance = pgl.norm(point - opp_candidate)
            if best_distance > opp_distance:
                best_candidate = opp_candidate
    else:
        best_candidate = brute_force_closest(point, kdtree)

    return best_candidate
Пример #2
0
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
Пример #3
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
Пример #4
0
def stars(leaves,
          g,
          direction=Vector3(1, 1, 1),
          up=Vector3(0, 0, 1),
          right=Vector3(1, 1, 1),
          beam_radius=.1):
    from openalea.plantik.tools.convex import cvxHull
    from openalea.plantgl.all import BoundingBox, Viewer, norm
    hull = cvxHull(leaves)
    lad = surface(leaves) / volume(hull)
    print lad
    bbx = BoundingBox(hull)
    pos = bbx.upperRightCorner
    interception = 0.
    for rshift in range(bbx.getSize().y / beam_radius):
        for upshift in range(bbx.getSize().z / beam_radius):
            sx = 1
            sy = 1
            print pos - rshift * right - upshift * up
            intersections = Viewer.frameGL.castRays(
                pos - rshift * right - upshift * up, direction,
                Vector3(0.5, 0., 0), Vector3(0, 0.5, 0), sx, sy)
            print intersections
            p = 1
            for intersection in intersections.flatten():
                length = norm(intersection.out - getattr(intersection, 'in'))
                length = 1
                p *= exp(-g * lad(length))
        interception += (1. - p) * beam_radius**beam_radius
    return interception / surface(leaves)
Пример #5
0
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
Пример #6
0
 def _common_init( self, **keys ):
     """
     """
     if keys.has_key("height"):
         self._height = keys[ "height" ]
     else:
         self._height = pgl.norm( keys[ "axis" ] )
     self._radius = keys[ "radius" ]
Пример #7
0
 def _common_init(self, **keys):
     """
     """
     if keys.has_key("height"):
         self._height = keys["height"]
     else:
         self._height = pgl.norm(keys["axis"])
     self._radius = keys["radius"]
Пример #8
0
 def _common_init( self, **keys ):
     """
     """
     if "height" in keys:
         self._height = keys[ "height" ]
     else:
         self._height = pgl.norm( keys[ "axis" ] )
     self._radius = keys[ "radius" ]
Пример #9
0
def closestpoint(kdtree, p, depth):
	axis = depth % 3
	if isinstance(kdtree, Kdnode):
		""" Move down the tree recursively """
		if p[axis] > kdtree.location[axis]:
			candidat = closestpoint(kdtree.right_child, p, depth-1)
		else:
			candidat = closestpoint(kdtree.left_child, p, depth-1)
			
		""" Unwind the recursion of the tree """
		if candidat == None or norm(p-kdtree.location) < norm(p-candidat):
			candidat = kdtree.location
		if norm(p-candidat) < abs(p[axis]-kdtree.location[axis]):
			return candidat
		else:
			if p[axis] > kdtree.location[axis]:
				other_candidat = closestpoint(kdtree.left_child, p, depth-1)
			else:
				other_candidat = closestpoint(kdtree.right_child, p, depth-1)
			if other_candidat == None or norm(p-candidat) < norm(p-other_candidat):
				return candidat
			else:
				return other_candidat
	else:
		""" Leaf node """
		candidat = None
		for c in kdtree:
			if candidat == None or norm(p-c) < norm(p-candidat):
				candidat = c
		return candidat
Пример #10
0
def brute_force_closest(point, pointlist):
    """ Find the closest points of 'point' in 'pointlist' using a brute force approach """
    import sys
    pid, d = -1, sys.maxint
    for i, p in enumerate(pointlist):
        nd = pgl.norm(point-p) 
        if nd < d:
            d = nd
            pid = i
    return pointlist[pid]
Пример #11
0
def brute_force_closest(point, pointlist):
	""" Find the closest points of 'point' in 'pointlist' using a brute force approach """
	import sys
	pid, d = -1, sys.maxint
	for p in pointlist:
		nd = norm(point-p) 
		if nd < d:
			d = nd
			pid = p
	return pid
Пример #12
0
def test_ifs():
    for i in xrange(5):
        ifs = pgl.IFS(
            randint(1, 3),
            [pgl.Transform4(randtransform()) for i in xrange(1, 4)],
            pgl.Sphere(radius=uniform(0.1, 1),
                       slices=randint(4, 255),
                       stacks=randint(4, 255)))
        res = eval_code(ifs, True)
        for j in xrange(len(ifs.transfoList)):
            for k in xrange(4):
                if pgl.norm(
                        ifs.transfoList[j].getMatrix().getColumn(k) -
                        res.transfoList[j].getMatrix().getColumn(k)) > 1e-3:
                    print ifs.transfoList[j].getMatrix()
                    print res.transfoList[j].getMatrix()
                    print k, pgl.norm(
                        ifs.transfoList[j].getMatrix().getColumn(k) -
                        res.transfoList[j].getMatrix().getColumn(k))
                    warnings.warn(
                        "Transformation retrieval from matrix4 failed.")
Пример #13
0
 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)
             #p1 = pts1[i]
             d = min(pgl.norm(pt - p1), d)
             return d
     else:
         return maxint
Пример #14
0
 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
Пример #15
0
 def _common_init( self, **keys ):
     """
     """
     if keys.has_key("height"):
         self._height = keys[ "height" ]
     else:
         self._height = pgl.norm( keys[ "axis" ] )
     self._radius = keys[ "radius" ]
     
     self.shaft = pgl.Scaled(pgl.Vector3(1, 1, AARROW_SHAFT_PROPORTION), ACYLINDER_PRIMITIVE )
     self.head = pgl.Translated(pgl.Vector3(0, 0, AARROW_SHAFT_PROPORTION), pgl.Scaled(pgl.Vector3(
         AARROW_HEAD_PROPORTION,AARROW_HEAD_PROPORTION,1-AARROW_SHAFT_PROPORTION), ACONE_PRIMITIVE) )
Пример #16
0
 def _common_init( self, **keys ):
     """
     """
     if "height" in keys:
         self._height = keys[ "height" ]
     else:
         self._height = pgl.norm( keys[ "axis" ] )
     self._radius = keys[ "radius" ]
     
     self.shaft = pgl.Scaled(pgl.Vector3(1, 1, AARROW_SHAFT_PROPORTION), ACYLINDER_PRIMITIVE )
     self.head = pgl.Translated(pgl.Vector3(0, 0, AARROW_SHAFT_PROPORTION), pgl.Scaled(pgl.Vector3(
         AARROW_HEAD_PROPORTION,AARROW_HEAD_PROPORTION,1-AARROW_SHAFT_PROPORTION), ACONE_PRIMITIVE) )
Пример #17
0
def scale_and_center(points, mtg):
    import openalea.plantgl.all  as pgl

    if type(mtg) != pgl.Point3Array:
        mtgpoints = pgl.Point3Array(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 mtg.property('position').items()])
    mtg.property('position').update(npos1)
Пример #18
0
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)
Пример #19
0
 def last_year_ancestors(i):
     ancestors = [i]
     l = 0
     p = nodepos(i)
     while l < avg_length_gu:
         i = g.parent(i)
         if i:
             ancestors.append(i)
             try:
               np = toppos[i]
               l += norm(p-np)
               p = np
             except:
               pass
         else:
            break
     return ancestors
Пример #20
0
 def last_year_ancestors(i):
     ancestors = [i]
     l = 0
     p = nodepos(i)
     while l < avg_length_gu:
         i = g.parent(i)
         if i:
             ancestors.append(i)
             try:
                 np = toppos[i]
                 l += norm(p - np)
                 p = np
             except:
                 pass
         else:
             break
     return ancestors
Пример #21
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]
Пример #22
0
def lidarscan(scene, a=90, z=1):
    pgl.Viewer.display(scene)
    sc = pgl.Viewer.getCurrentScene()
    bbx = pgl.BoundingBox(sc)
    c = bbx.getCenter()
    p, h, u = pgl.Viewer.camera.getPosition()
    pts = pgl.PointSet([], [])
    for a in arange(0, 360, a):
        np = (c + pgl.Matrix3.axisRotation(
            (0, 0, 1), a) * pgl.Vector3(1, 0, 0) * pgl.norm(p - c))

        pgl.Viewer.camera.lookAt(np / z, c)
        pi, ci = pgl.Viewer.frameGL.grabZBufferPoints()
        pts.pointList += pi
        pts.colorList += ci

    return pts
Пример #23
0
def to_js(scene):
    bbx = BoundingBox(scene)
    center = bbx.getCenter()
    objsize = norm(bbx.getSize())
    code = template_code_begin.format(objcenter=(center.x, center.y, center.z),
                                      objsize=objsize,
                                      lightposition=tuple(center +
                                                          (0, 0, 5 * objsize)))
    if isinstance(scene, Geometry):
        code += sh2js(Shape(scene, Material.DEFAULT_MATERIAL))
    elif isinstance(scene, Shape):
        code += sh2js(scene)
    else:
        for sh in scene:
            code += sh2js(sh)
    code += template_code_end
    return code
Пример #24
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
Пример #25
0
def c_determine_colorindex(fruiting_structures, mtg, scene):
    from openalea.plantgl.all import norm
    import numpy
    from random import randint
    allinflos = sum([inflos for inflos, gus in fruiting_structures], [])
    inflopos = inflo_positions(fruiting_structures, mtg, scene)
    idmap = mtg.property('_axial_id')
    pos = [inflopos[i] for i in inflopos]
    distances = numpy.array([[norm(p1 - p2) for p1 in pos] for p2 in pos])
    #print distances
    maxdist = numpy.amax(distances)
    mindist = numpy.amin(distances)
    distances -= mindist
    distances /= (maxdist - mindist)
    nbcolors = len(pos)
    index = list(range(nbcolors))
    print(distances)

    def cost(index, distances):
        return sum([
            sum([distances[i, j] * abs(vi - vj) for j, vj in enumerate(index)])
            for i, vi in enumerate(index)
        ])

    def swap(index, i=None, j=None):
        assert i != j or i == None
        nindex = list(index)
        i1, i2 = randint(0, nbcolors -
                         1) if i is None else i, randint(0, nbcolors -
                                                         1) if j is None else j
        if i1 == i2: return swap(index, i, j)
        nindex[i1], nindex[i2] = index[i2], index[i1]
        return nindex

    def bestswap(index, distances):
        bcost = cost(index, distances)
        bindex = index
        for i in range(len(index) - 2):
            for j in range(i + 1, len(index) - 1):
                nindex = swap(index, i, j)
                ccost = cost(nindex, distances)
                if ccost < bcost:
                    bcost = ccost
                    bindex = nindex
        return bindex

    def bestswapi(index, distances, i):
        bcost = cost(index, distances)
        bindex = index
        for j in range(0, len(index) - 1):
            if j != i:
                nindex = swap(index, i, j)
                ccost = cost(nindex, distances)
                if ccost < bcost:
                    bcost = ccost
                    bindex = nindex
        return bindex

    def shuffle(index):
        from numpy.random import shuffle as nshuffle
        nindex = list(index)
        nshuffle(nindex)
        return nindex

    bcost = cost(index, distances)
    print(bcost)
    bindex = index
    bestiter = None
    for i in range(10):
        success = True
        index = shuffle(index)
        icost = cost(index, distances)
        while success:
            nindex = bestswapi(index, distances, randint(0, nbcolors - 1))
            cicost = cost(nindex, distances)
            if cicost < icost:
                index = nindex
                icost = cicost
                print(icost)
            else:
                success = False
        if icost < bcost:
            bcost = icost
            bindex = index
            print('bestiter', i)
            bestiter = i

    print(bcost)
    result = {}
    i = 0
    for inflos, gus in fruiting_structures:
        for inflo in inflos:
            result[inflo] = index[i]
            i += 1
        nindex.append(result[inflos[0]])
    print(bestiter)
    #print result
    return result
Пример #26
0
 def nodelength(i):
     try:
         return norm(toppos[i] - nodepos(g.parent(i)))
     except:
         return 0
Пример #27
0
 def _surf(ind,pts):
     A,B,C = [pts[i] for i in ind]
     return pgl.norm(pgl.cross(B-A, C-A)) / 2.0
Пример #28
0
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(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 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 xrange(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 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 xrange(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'
Пример #29
0
 def lovel_distance(g1, g2):
     p1 = base(g1)
     p2 = top(g2)
     return pgl.norm(p2 - p1)
Пример #30
0
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')
Пример #31
0
 def nodelength(i):
     try:
        return norm(toppos[i]-nodepos(g.parent(i)))
     except:
        return 0
Пример #32
0
    def disperse(self, g, dispersal_units, time_control = None):
        """ Compute distribution of dispersal units by rain splash.
        
        1. Upward dispersal:
        For each source of dispersal units, create a semi-sphere of dispersal 
        normal to the surface of source leaf. In the semi-sphere, target 
        leaves are sorted according to the distance from the source.                
        Then distribute dispersal units from the closer target to the more far.
        The number of dispersal units by target leaf is computed as in Robert et al. 2008
        
        2. Downward dispersal:
        Get leaves in a cylinder whose dimensions are related to the dimesions
        of the semi-sphere in step 1. Then distribute dispersal units from top to bottom.
        
        Parameters
        ----------
        g: MTG
            MTG representing the canopy (and the soil)
        dispersal_units : dict
            Dispersal units emitted by the lesions on leaves
            
        Returns
        -------
        deposits : dict
            Dispersal units deposited on new position on leaves
        """
        try:
            dt = time_control.dt
        except:
            dt = 1
        
        deposits = {}
        if dt>0:
            from alinea.astk.plantgl_utils import get_area_and_normal
            from alinea.alep.architecture import get_leaves
            from openalea.plantgl import all as pgl
            from collections import OrderedDict
            from math import exp, pi, cos, sin, tan
            from random import shuffle
            import numpy as np
            from copy import copy
            
            dmax = self.distance_max
            tesselator = pgl.Tesselator()
            bbc = pgl.BBoxComputer(tesselator)
            leaves = get_leaves(g, label=self.label)
            centroids = g.property('centroid')
            geometries = g.property('geometry')
            _, norm = get_area_and_normal(geometries)
            areas = g.property('area')          
            
            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
            
            for source, dus in dispersal_units.iteritems():
                nb_tri = len(norm[source])
                borders = np.linspace(0,1,num=nb_tri)
                
                dus_by_tri = {k:filter(lambda x: borders[k]<x.position[0]<=borders[k+1], dus) 
                                for k in range(nb_tri-1)
                                if len(filter(lambda x: borders[k]<x.position[0]<=borders[k+1], dus))>0.}
                
                for k,v in dus_by_tri.iteritems():
                    source_normal = norm[source][k]
                    
                    ## UPWARD ##
                    # All leaves except the source are potential targets
                    targets = list(leaf for leaf in leaves if leaf in geometries.iterkeys())
                    targets.remove(source)
                    
                    # Compute centroids
                    centroid(source)
                    for vid in targets:
                        centroid(vid)
                    
                    # Sort the vids based on the direction 
                    # TODO : modify source angle
                    Origin = centroids[source]
                    vects = {vid:(centroids[vid]-Origin) for vid in targets 
                            if (centroids[vid]-Origin)*source_normal >= 0}
                    
                    # Sort the vids based on the distance
                    distances = {vid:pgl.norm(vects[vid]) for vid in vects if pgl.norm(vects[vid])<dmax}
                    distances = OrderedDict(sorted(distances.iteritems(), key=lambda x: x[1]))
                    
                    # Distribute the dispersal units
                    if len(distances.values())>0:
                        shuffle(v)
                        n = len(v)
                        sphere_area = 2*pi*distances.values()[-1]**2
                        for leaf_id in distances:
                            area_factor = areas[leaf_id]/sphere_area
                            distance_factor = exp(-self.k * distances[leaf_id])
                            qc = min(n, (n * area_factor * distance_factor))
                            
                            deposits[leaf_id] = v[:int(qc)]
                            del v[:int(qc)]
                            # if len(dus) < 1 or len(deposits[leafid]) < 1:
                            if len(v) < 1:
                                for d in v:
                                    d.disable()
                                # break
                    
                    ## DOWNWARD ##
                    vects2 = {vid:(centroids[vid]-Origin) for vid in targets if not vid in vects}
                    projection = {}

                    alpha = pgl.angle(source_normal, (1,0,0))
                    if alpha>=pi/2. or (alpha<pi/2. and source_normal[2]>=0):
                        alpha+=pi/2.
                    beta = pgl.angle(source_normal, (0,0,1))
                    a = dmax
                    b = dmax*cos(beta)
                    
                    for leaf in vects2:
                        if (centroids[leaf]-Origin)*(source_normal[0], source_normal[1], 0) >= 0:
                            # Big side of the projection semi circle
                            copy_centroid = copy(centroids[leaf])
                            copy_origin = copy(Origin)
                            copy_centroid[2] = 0.
                            copy_origin[2] = 0.
                            if pgl.norm(copy_centroid-copy_origin) < dmax:
                                projection[leaf] = vects2[leaf]
                        else:
                            # Small side of the projection semi ellipse
                            x = vects2[leaf][0]
                            y = vects2[leaf][1]
                            x2 = x*cos(alpha)+y*sin(alpha)
                            y2 = -x*sin(alpha)+y*cos(alpha)
                            if (x2**2)/(a**2) + (y2**2)/(b**2) < 1 :
                                projection[leaf] = vects2[leaf]
                    projection = OrderedDict(sorted(projection.items(), key=lambda x:x[1][2], reverse=True))
                    
                    if len(projection)>0:
                        shuffle(v)
                        n = len(v)
                        n_big = int(n*(beta+pi/2.)/pi)
                        n_small = n - n_big
                        for leaf in projection:
                            copy_centroid = copy(centroids[leaf])
                            copy_origin = copy(Origin)
                            copy_centroid[2] = 0.
                            copy_origin[2] = 0.
                            if (centroids[leaf]-Origin)*(source_normal[0],source_normal[1],0) >= 0:
                                area_factor = areas[leaf]/(pi*dmax**2/2.)
                                dist = pgl.norm(copy_centroid-copy_origin)
                                distance_factor = exp(-self.k * dist)
                                qc = min(n_big, (n_big * area_factor * distance_factor))
                                g.node(leaf).color = (0, 180, 0)
                            else:
                                area_factor = areas[leaf]/(pi*a*b/2.)
                                dist = pgl.norm(copy_centroid-copy_origin)/abs(cos(pgl.angle(source_normal, (1,0,0))+pi/2.))
                                distance_factor = exp(-self.k * dist)
                                qc = min(n_small, (n_small * area_factor * distance_factor))
                                g.node(leaf).color = (0, 0, 180)
                                # import pdb
                                # pdb.set_trace()
                            deposits[leaf] = v[:int(qc)]
                            del v[:int(qc)]
                            
                    for leaf in distances:
                        g.node(leaf).color = (180, 0, 0)
                    
                    # Temp
                    # from alinea.adel.mtg_interpreter import plot3d
                    # from openalea.plantgl.all import Viewer
                    # g.node(source).color=(230, 62, 218)
                    # scene = plot3d(g)
                    # Viewer.display(scene)
                    # import pdb
                    # pdb.set_trace()
        return deposits
Пример #33
0
 def _surf(ind, pts):
     A, B, C = [pts[i] for i in ind]
     return pgl.norm(pgl.cross(B - A, C - A)) / 2.0
Пример #34
0
 def _surf(ind, pts):
     from openalea.plantgl.all import norm, cross, Vector3
     A, B, C = [Vector3(pts[i]) for i in ind]
     return norm(cross(B - A, C - A)) / 2.0
Пример #35
0
    def disperse(self, g, dispersal_units, time_control = None):
        """ Compute dispersal of spores of powdery mildew by wind in a cone.
        
        For each source of dispersal units, create a cone of dispersal 
        in which target leaves are sorted:
        1. according to the wind direction
        2. according to the angle a0
        3. according to the distance from the source
        
        Then distribute dispersal units from the closer target to the more far.
        The number of dispersal units by target leaf is computed as in
        Calonnec et al. 2008.
        
        Parameters
        ----------
        g: MTG
            MTG representing the canopy (and the soil)
        dispersal_units : dict
            Dispersal units emitted by the lesions on leaves
            
        Returns
        -------
        deposits : dict
            Dispersal units deposited on new position on leaves
        """
        try:
            dt = time_control.dt
        except:
            dt = 1
        
        deposits = {}
        if dt > 0:
            from alinea.alep.architecture import get_leaves
            from openalea.plantgl import all as pgl
            from random import shuffle
            from math import degrees, exp, tan, pi, radians
            from collections import OrderedDict
            geometries = g.property('geometry')
            centroids = g.property('centroid')
            areas = g.property('area')
            wind_directions = g.property('wind_direction')
            tesselator = pgl.Tesselator()
            bbc = pgl.BBoxComputer(tesselator)
        
            leaves = get_leaves(g, label=self.label)

            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
            
            def area(vid):
                # areas[vid] = pgl.surface(geometries[vid][0])*1000
                areas[vid] = pgl.surface(geometries[vid][0])

            for source, dus in dispersal_units.iteritems():
                # TODO: Special computation for interception by source leaf
                
                # All other leaves are potential targets
                targets = list(leaf for leaf in leaves if leaf in geometries.iterkeys())
                targets.remove(source)
                
                # Compute centroids
                centroid(source)
                for vid in targets:
                    centroid(vid)
                    # surface(vid)

                # Sort the vids based on the direction 
                Origin = centroids[source]
                vects = {vid:(centroids[vid]-Origin) for vid in targets 
                        if (centroids[vid]-Origin)*wind_directions[source] >= 0}
                
                # Sort the vids based on the angle                
                angles = {vid:degrees(pgl.angle(vect, wind_directions[source])) 
                          for vid, vect in vects.iteritems()
                          if degrees(pgl.angle(vect, wind_directions[source]))<= self.a0}
                
                # Sort the vids based on the distance
                distances = {vid:pgl.norm(vects[vid]) for vid in angles}
                distances = OrderedDict(sorted(distances.iteritems(), key=lambda x: x[1]))
                               
                # Beer law inside cone to take into account leaf coverage
                shuffle(dus)
                n = len(dus)

                if len(distances.values())>0:
                    for leaf in distances:
                        # qc = min(n, (n * (areas[leaf]/self.reduction) * 
                             # exp(-self.cid * distances[leaf]) * 
                             # (self.a0 - angles[leaf])/self.a0))
                        surf_base_cone = pi*(tan(radians(self.a0))*distances[leaf])**2
                        area_factor = min(1, areas[leaf]/surf_base_cone)
                        # import pdb
                        # pdb.set_trace()
                        qc = min(n, (n * area_factor * 
                             exp(-self.cid * distances[leaf]) * 
                             (self.a0 - angles[leaf])/self.a0))
                        
                        # if qc < 1:
                            # for d in dus:
                                # d.disable()
                            # break
                                            
                        deposits[leaf] = dus[:int(qc)]
                        del dus[:int(qc)]
                        # if len(dus) < 1 or len(deposits[leaf]) < 1:
                        if len(dus) < 1:
                            for d in dus:
                                d.disable()
                            break
                        
        return deposits
Пример #36
0
""" Gather different strategies for modeling dispersal of fungus propagules.
Пример #37
0
""" Gather different strategies for modeling dispersal of fungus propagules.
Пример #38
0
 def _surf(mesh, iface):
     A, B, C = [mesh.pointList[i] for i in mesh.indexAt(iface)]
     return pgl.norm(pgl.cross(B - A, C - A)) / 2.0
Пример #39
0
def isincylinder(point, base, dir, radius, height):
    return 0 <= dot(point - base,
                    pgl.Vector3(dir).normed()) <= height and pgl.norm(
                        cross(point - base,
                              pgl.Vector3(dir).normed())) < radius