def test_bbox():
    faces = ((0, 1, 2), (0, 2, 0), (0, 1, 3))
    vertices = ((0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1))
    sc = {'0': (vertices, faces)}
    spc = SurfacicPointCloud.from_scene_mesh(sc)
    expected = ((0.0, 0.0, 0.0), [1. / 3] * 3)
    numpy.testing.assert_almost_equal(spc.bbox(), expected)
def test_subset():
    faces = ((0, 1, 2), (0, 2, 3), (0, 1, 3))
    vertices = ((0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1))
    sc = {
        1: (vertices, (faces[1], )),
        2: (vertices, [faces[i] for i in (0, 2)])
    }
    spc = SurfacicPointCloud.from_scene_mesh(sc)
    sub = spc.subset(point_id=1)
    assert len(sub.as_data_frame() == 1)
    sub = spc.subset(shape_id=2)
    assert len(sub.as_data_frame() == 2)
def test_spc_instantiation():
    spc = SurfacicPointCloud(0, 0, 0, 1)
    for w in ('x', 'y', 'z', 'area', 'shape_id', 'normals', 'properties',
              'size'):
        assert hasattr(spc, w)
    spc = SurfacicPointCloud(100, 100, 100, 10000, scene_unit='cm')
    assert spc.x == spc.y == spc.z == spc.area == 1  # m2

    faces = (range(3), )
    vertices = ((0, 0, 0), (1, 0, 0), (0, 1, 0))
    sc = {'0': (vertices, faces)}
    spc = SurfacicPointCloud.from_scene_mesh(sc)
    assert spc.area == 0.5
    numpy.testing.assert_array_equal(spc.normals, ((0, 0, 1), ))
def test_inclinations():
    faces = ((0, 1, 2), (0, 2, 3), (0, 1, 3))
    vertices = ((0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1))
    sc = {
        1: (vertices, (faces[1], )),
        2: (vertices, [faces[i] for i in (0, 2)])
    }
    spc = SurfacicPointCloud.from_scene_mesh(sc)
    df = spc.inclinations()
    inc = {
        g: x.to_dict('list')['inclination']
        for g, x in df.groupby('shape_id')
    }
    numpy.testing.assert_array_equal(inc[1], [90.0])
    numpy.testing.assert_array_equal(inc[2], [0.0, 90.0])
Beispiel #5
0
    def __init__(self,
                 scene=None,
                 grid=None,
                 entities=None,
                 rleaf=0.15,
                 rsoil=0.2,
                 nbinclin=9,
                 orientation=0,
                 localisation='Montpellier',
                 scene_unit='m',
                 mu=None,
                 distinc=None,
                 **grid_kwds):
        """
        Initialise a RatpScene.

        Arguments:
        scene: a pyratp.interface.surfacic_point_cloud or a plantgl.Scene or a
        {shape_id: vertices, faces} scene mesh dict encoding the 3D scene
        grid: a pyratp.interface.smart_grid instance encoding the voxel grid.
         If None (default), the grid is adjusted to fit the input scene.
        entities: a {shape_id: entity} dict defining entities in the scene. If
         None (default), all shapes are considered as members of the same entity
        rleaf: leaf reflectance or a {entity: leaf_reflectance} property dict.
        rsoil: soil reflectance
        nbinclin: the number of angular classes for leaf angle distribution
        orientation (float): the angle (deg, positive clockwise) from X+ to
         North (default: 0)
        localisation : a string referencing a city of the localisation database
         (class variable), or a dict{'longitude':longitude, 'latitude':latitude}
        scene_unit: a string indicating unit used for scene coordinates
        mu : a list of clumping indices, indexed by density.If None (default)
         clumping is automatically evaluated using clark-evans method.
        distinc: a list of list giving the frequency of the nbinclin leaf angles
         classes (from horizontal to vertical) per entity in the canopy.
         If None (default), distinc is computed automatically from the scene

        Other named args to this function are used for controlling grid shape
        when grid=None

        """

        # scene_box will be used to construct grid, if grid is None
        scene_box = ((0, 0, 0), (1, 1, 1))

        if scene is None:
            scene = {'plant': unit_square_mesh()}

        if isinstance(scene, SurfacicPointCloud):
            self.scene = scene
            self.scene_mesh = scene.as_scene_mesh()
            if grid is None:
                scene_box = scene.bbox()
        elif is_pgl_scene(scene):
            self.scene_mesh = pgls.as_scene_mesh(scene)
            self.scene = SurfacicPointCloud.from_scene_mesh(
                self.scene_mesh, scene_unit=scene_unit)
            if grid is None:
                scene_box = pgls.bbox(scene, scene_unit)
        else:
            try:
                self.scene_mesh = scene
                self.scene = SurfacicPointCloud.from_scene_mesh(
                    scene, scene_unit=scene_unit)
                if grid is None:
                    vertices, faces = zip(*scene.values())
                    vertices = reduce(lambda pts, new: pts + list(new),
                                      vertices, [])
                    x, y, z = zip(*vertices)
                    scene_box = ((min(x), min(y), min(z)), (max(x), max(y),
                                                            max(z)))
            except Exception as details:
                print details
                raise ValueError(
                    "Unrecognised scene format: should be one of pgl.Scene, "
                    "SurfacicPointCloud or {sh_id:(vertices, faces)} dict")

        if grid is None:
            self.smart_grid = SmartGrid(scene_box=scene_box, **grid_kwds)
        elif isinstance(grid, SmartGrid):
            self.smart_grid = grid
        else:
            raise ValueError('Unrecognised grid format: should be None or a '
                             'SmartGrid instance')

        if entities is None:
            entities = {sh_id: 'default' for sh_id in self.scene_mesh}
        self.entities = entities
        # RATP entity code starts at 1
        ent = list(set(self.entities.values()))
        self.entity_map = dict(zip(ent, range(1, len(ent) + 1)))
        self.entity_code = numpy.array(
            [self.entity_map[entities[sh]] for sh in self.scene.shape_id])

        if not isinstance(rleaf, dict):
            # if not hasattr(rleaf, '__len__'):
            #     rleaf = [rleaf]
            rleaf = {'default': rleaf}
        self.rleaf = {self.entity_map[k]: rleaf[k] for k in self.entity_map}

        if not hasattr(rsoil, '__len__'):
            rsoil = [rsoil]
        self.rsoil = rsoil

        self.orientation = orientation

        if not isinstance(localisation, dict):
            try:
                localisation = RatpScene.localisation_db[localisation]
            except KeyError:
                print 'Warning : localisation', localisation, \
                    'not found in database, using default localisation', \
                    RatpScene.localisation_db.iter().next()
                localisation = RatpScene.localisation_db.itervalues().next()
        self.localisation = localisation

        if mu is None:
            mu = self.clumping()
            print(' '.join(['clumping evaluated:'] + [str(m) for m in mu]))
        self.set_clumping(mu)

        if distinc is None:
            distinc = self.inclination_distribution(nbinclin)
        self.set_inclin(distinc)

        self.ratp_grid, self.grid_indices = self.grid()