Пример #1
0
    def _check_collision(width, height, mechs, mech):
        tree = aabb.AABBTree()
        # Add edge bounding boxes for backboard.
        gripper_gap = 0.035  # so gripper doesn't collide with busybox base
        tree.add(
            aabb.AABB([(-width / 2.0, width / 2.0),
                       (height / 2.0, height / 2.0 + 1)]))  # top
        tree.add(
            aabb.AABB([(-width / 2.0, width / 2.0),
                       (-height / 2.0 - 1, -height / 2.0 + gripper_gap)
                       ]))  # bottom
        tree.add(
            aabb.AABB([(-width / 2.0 - 1, -width / 2.0),
                       (-height / 2.0, height / 2.0)]))  # left
        tree.add(
            aabb.AABB([(width / 2.0, width / 2.0 + 1),
                       (-height / 2.0, height / 2.0)]))  # right

        # Get the bounding box for each existing mechanism.
        for ix, m in enumerate(mechs):
            if not m == mech:
                tree.add(m.get_bounding_box(), str(ix))

        # Get the bounding box of the current mechanism and check overlap.
        if tree.does_overlap(mech.get_bounding_box()):
            return True
        else:
            return False
Пример #2
0
    def removeSensor(self, index):
        #We remove the sensor from the list
        self.sensorList.pop(index)
        self.sensorNumber -= 1

        #Now, we need to recreate the tree
        self.tree = aabbtree.AABBTree()
        for sensor in self.sensorList:
            self.tree.add(sensor["bbox"])
Пример #3
0
def main():
    # Cross shapes
    cross_horiz_left = aabbtree.AABB([(-6, 1), (-1, 2)])
    cross_vert_left = aabbtree.AABB([(-1, 1), (-15, 5)])
    cross_horiz_right = aabbtree.AABB([(3, 10), (-2, 1)])
    cross_vert_right = aabbtree.AABB([(3, 5), (-15, 5)])

    # Box sets
    box_1 = aabbtree.AABB([(-21, -18), (-21, -18)])
    box_2 = aabbtree.AABB([(-17, -14), (-21, -18)])
    box_3 = aabbtree.AABB([(-16, -13), (-16, -13)])
    box_4 = aabbtree.AABB([(-12, -9), (-16, -13)])

    # Random boxes
    rand_1 = aabbtree.AABB([(-15, -13), (-2, 2)])

    # Build tree
    tree = aabbtree.AABBTree()
    aabbs = [
        box_3, cross_vert_right, box_1, cross_horiz_left, box_4, rand_1,
        cross_vert_left, box_2, cross_horiz_right
    ]
    for i, aabb in enumerate(aabbs):
        tree.add(aabb, i + 1)

    # Set up figure
    plt.clf()
    plt.close('all')
    fig = plt.figure()
    ax = plt.axes()
    ax.set_axis_off()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    fig.add_axes(ax)

    # Plot tree contents
    plot_contents(tree)

    # Plot tree
    plot_tree(tree)

    # Format axes
    plt.axis('square')
    plt.xlim([-85, 11])
    plt.ylim([-22, 7])

    # Save figure
    docs_path = os.path.join(os.path.dirname(__file__), 'docs')
    fig_filename = os.path.join(docs_path, 'source', '_static', 'diagram.png')
    plt.savefig(fig_filename,
                dpi=300,
                bbox_inches='tight',
                pad_inches=0,
                transparent=True)
Пример #4
0
    def __init__(self) -> None:
        #Structure
        self.sensor = [("groupIndex", np.int32), ("WtOMatrix", np.float32, 12),
                       ("twoSided", np.bool8), ("color", np.float32, 3),
                       ("exponent", np.float32)]

        #Attributes
        self.tree = aabbtree.AABBTree()
        self.sensorList = []
        self.builder = bvhBuilder.BVHBuilder()
        self.sensorNumber = 0
Пример #5
0
def _leaf_cloud_positions_cuboid_avoid_overlap(
    n_leaves, l_horizontal, l_vertical, leaf_radius, n_attempts, rng
):
    """
    Compute leaf positions for a cuboid-shaped leaf cloud (square footprint).
    This function also performs conservative collision checks to avoid leaf
    overlapping. This process might take a very long time, if the parameters
    specify a very dense leaf cloud. Consider using
    :func:`_leaf_cloud_positions_cuboid`.
    """
    n_attempts = int(n_attempts)  # For safety, ensure conversion to int

    # try placing the leaves such that they do not overlap by creating
    # axis-aligned bounding boxes and checking them for intersection
    positions = np.empty((n_leaves, 3))
    tree = aabbtree.AABBTree()

    for i in range(n_leaves):
        for j in range(n_attempts):
            rand = rng.random(3)
            pos_candidate = [
                rand[0] * l_horizontal - 0.5 * l_horizontal,
                rand[1] * l_horizontal - 0.5 * l_horizontal,
                rand[2] * l_vertical,
            ]
            aabb = aabbtree.AABB(
                [
                    (pos_candidate[0] - leaf_radius, pos_candidate[0] + leaf_radius),
                    (pos_candidate[1] - leaf_radius, pos_candidate[1] + leaf_radius),
                    (pos_candidate[2] - leaf_radius, pos_candidate[2] + leaf_radius),
                ]
            )
            if i == 0:
                positions[i, :] = pos_candidate
                tree.add(aabb)
                break
            else:
                if not tree.does_overlap(aabb):
                    positions[i, :] = pos_candidate
                    tree.add(aabb)
                    break
        else:
            raise RuntimeError(
                "unable to place all leaves: the specified canopy might be too dense"
            )

    return positions
Пример #6
0
    def __init__(self, sce=Scene()):
        # Type check
        assert type(
            sce
        ) == openalea.plantgl.scenegraph._pglsg.Scene, "Tree must be constructed with a PlantGL scene."

        # Structures
        # left BBox XY min and Max, both BBOx Z min and max, and right BBox XY min and Max
        self.firstInfos = [("n0xy", np.float32, 4), ("nz", np.float32, 4),
                           ("n1xy", np.float32, 4)]
        # left child and right child index
        self.branch = self.firstInfos + [("c0idx", np.int32),
                                         ("c1idx", np.int32)]
        # primitive index, and primitive count
        self.leaf = self.firstInfos + [("idx", np.int32), ("pcount", np.int32)]

        # Attributes
        self.tree = aabbtree.AABBTree()
        self.scene = sce
        self.serializedNodes = 0
Пример #7
0
    def position(self,
                 domain,
                 pos_dists={},
                 rng_seed=0,
                 hold=[],
                 max_attempts=10000,
                 rtol='fit',
                 verbose=False):
        """Position seeds in a domain

        This method positions the seeds within a domain. The "domain" should be
        a geometry instance from the :mod:`microstructpy.geometry` module.

        The "pos_dist" input is for phases with custom position distributions,
        the default being a uniform random distribution.
        For example:

        .. code-block:: python

            import scipy.stats
            mu = [0.5, -0.2]
            sigma = [[2.0, 0.3], [0.3, 0.5]]
            pos_dists = {2: scipy.stats.multivariate_normal(mu, sigma),
                         3: ['random',
                             scipy.stats.norm(0, 1)]
                         }

        Here, phases 0 and 1 have the default distribution, phase 2 has a
        bivariate normal position distribution, and phase 3 is uniform in the
        x and normally distributed in the y. Multivariate distributions are
        described in the multivariate section of the :mod:`scipy.stats`
        documentation.

        The position of certain seeds can be held fixed during the positioning
        process using the "hold" input. This should be a list of booleans,
        where False indicates a seed should not be held fixed and True
        indicates that it should be held fixed. The default behavior is to not
        hold any seeds fixed.

        The "rtol" parameter governs the relative overlap tolerable between
        seeds. Setting rtol to 0 means that there is no overlap, while a value
        of 1 means that one seed's center is on the edge of another seed.
        The default value is 'fit', which determines a tolerance between 0 and
        1 based on the ratio of standard deviation to mean in grain volumes.

        Args:
            domain (from :mod:`microstructpy.geometry`): The domain of the
                microstructure.
            pos_dists (dict): *(optional)* Position distributions for each
                phase, formatted like the example above.
                Defaults to uniform random throughout the domain.
            rng_seed (int): *(optional)* Random number generator (RNG) seed
                for positioning the seeds. Should be a non-negative integer.
            hold (list or numpy.ndarray): *(optional)* List of booleans for
                holding the positions of seeds.
                Defaults to False for all seeds.
            max_attempts (int): *(optional)* Number of random trials before
                removing a seed from the list.
                Defaults to 10,000.
            rtol (str or float): *(optional)* The relative overlap tolerance
                between seeds. This parameter should be between 0 and 1.
                Using the 'fit' option, a function will determine the value
                for rtol based on the mean and standard deviation in seed
                volumes.
            verbose (bool): *(optional)* This option will print a running
                counter of how many seeds have been positioned.
                Defaults to False.

        """  # NOQA: E501
        if len(hold) == 0:
            hold = [False for seed in self]

        # set the spatial distributions
        u_dist = [
            scipy.stats.uniform(lb, ub - lb) for lb, ub in domain.sample_limits
        ]

        distribs = []
        n_phases = max([s.phase for s in self]) + 1
        for i in range(n_phases):
            distribs.append(pos_dists.get(i, u_dist))

        # Add hold seeds
        n_seeds = len(self)
        tree = aabbtree.AABBTree()
        for i in range(n_seeds):
            if hold[i]:
                # add to tree
                aabb = aabbtree.AABB(self[i].geometry.limits)
                tree.add(aabb, i)

        positioned = np.array(hold)
        vols = np.array([s.volume for s in self])
        i_sort = np.flip(np.argsort(vols))
        posd_sort = positioned[i_sort]
        i_position = i_sort[~posd_sort]

        # allowable overlap, relative to radius
        cv = scipy.stats.variation(vols)
        if domain.n_dim == 2 and rtol == 'fit':
            numer = 0.362954 * cv * cv - 0.419069 * cv + .184959
            denom = cv * cv - 1.05989 * cv + 0.365096
            rtol = numer / denom
        elif rtol == 'fit':
            numer = 0.471115 * cv * cv - 0.602324 * cv + 0.297562
            denom = cv * cv - 1.08469 * cv + 0.428216
            rtol = numer / denom

        # position the remaining seeds
        i_reject = []
        np.random.seed(rng_seed)
        n_samples = 100

        for k, i in enumerate(i_position):
            if verbose:
                print(k + 1, 'of', len(i_position))

            seed = self[i]
            pos_dist = distribs[seed.phase]

            searching = True
            n_attempts = 0
            i_sample = 0
            pts = sample_pos_within(pos_dist, n_samples, domain)
            while searching and n_attempts < max_attempts:
                pt = pts[i_sample]

                seed.position = pt
                n_attempts += 1
                i_sample += 1

                if i_sample == n_samples:
                    pts = sample_pos_within(pos_dist, n_samples, domain)
                    i_sample = 0

                bkdwn = np.array(seed.breakdown)
                cens = bkdwn[:, :-1]
                rads = bkdwn[:, -1].reshape(-1, 1)

                aabb = aabbtree.AABB(seed.geometry.limits)
                olap_inds = tree.overlap_values(aabb, method='BFS')
                olap_seeds = self[olap_inds]
                clears = True
                for olap_seed in olap_seeds:
                    o_bkdwn = np.array(olap_seed.breakdown)
                    o_cens = o_bkdwn[:, :-1]
                    o_rads = o_bkdwn[:, -1].reshape(1, -1)

                    if len(rads) > 1:
                        dists = distance.cdist(cens, o_cens)
                    else:
                        rel_pos = o_cens - cens
                        rp2 = rel_pos * rel_pos
                        dists = np.sqrt(np.sum(rp2, axis=1))
                    tol = rtol * np.minimum(rads, o_rads)
                    total_dists = dists + tol - rads - o_rads
                    if np.any(total_dists < 0):
                        clears = False
                        break

                searching = not clears

            if searching:
                i_reject.append(i)
            else:
                positioned[i] = True
                self[i] = seed

                # add to tree
                aabb = aabbtree.AABB(seed.geometry.limits)
                tree.add(aabb, i)

        keep_mask = np.array(n_seeds * [True])
        keep_mask[i_reject] = False

        if ~np.all(keep_mask):
            reject_seeds = self[~keep_mask]
            f = 'seed_position_reject.log'
            reject_seeds.write(f)

            w_str = 'Seeds were removed from the seed list during positioning.'
            w_str += ' Their data has beeen written to ' + f + ' and their'
            w_str += ' indices were ' + str(i_reject) + '.'
            warnings.warn(w_str, RuntimeWarning)

        self.seeds = self[keep_mask].seeds
Пример #8
0
  def find_overlaps_in_sources_sinks_agents( 
                  collected_sources_sinks_agent_states_geometries):
    # create aabbtree for fast distance lookup between agents
    tree = aabbtree.AABBTree()
    for source_sink_idx, states_geometries in enumerate(
            collected_sources_sinks_agent_states_geometries):
      agent_states = states_geometries[0]
      agent_geometries = states_geometries[1]
      for agent_idx, agent_state in enumerate(agent_states):
        agent_translated_polygon = agent_geometries[agent_idx].Translate(
                                                      Point2d(agent_state[1],
                                                            agent_state[2]))
        tmp = agent_translated_polygon.bounding_box
        bb = aabbtree.AABB([(tmp[0].x(), tmp[1].x()), (tmp[0].y(), tmp[1].y())])
        tree.add(bb, (source_sink_idx, agent_idx))

    # check for all agents in a source sink config collision with
    # agents in other sources sinks and track the collisions
    collisions = defaultdict(list)
    for source_sink_idx, states_geometries in enumerate(
            collected_sources_sinks_agent_states_geometries):
        agent_states = states_geometries[0]
        agent_geometries = states_geometries[1]
        for agent_idx, agent_state in enumerate(agent_states):
          agent_translated_polygon = agent_geometries[agent_idx].Translate(
                                                        Point2d(agent_state[1],
                                                              agent_state[2]))
          tmp = agent_translated_polygon.bounding_box
          bb = aabbtree.AABB([(tmp[0].x(), tmp[1].x()), ( tmp[0].y() , tmp[1].y())])
          overlaps = tree.overlap_values(bb)
          for overlap in overlaps:
            if source_sink_idx == overlap[0]:
              if agent_idx == overlap[1]:
                continue
              else:
                raise ValueError("Something went wrong. \
                    We have colliding agent within one source sink configuration")
          
            key1 = "{}-{}".format(source_sink_idx, overlap[0])
            key2 = "{}-{}".format(overlap[0], source_sink_idx, )
            key = None
            if key1 in collisions:
              key = key1
            elif key2 in collisions:
              key = key2
            else:
              key = key1

            pairwise_collisions = collisions[key]
            found = False
            for collision in pairwise_collisions:
              # exclude the case where this collision was already detected in a previous
              # run through the loop
              agent_desc1 = collision[0]
              if overlap[0] == agent_desc1[0] and overlap[1] == agent_desc1[1]:
                found = True
            if not found:
              agent_geometry_other = collected_sources_sinks_agent_states_geometries[overlap[0]][1][overlap[1]]
              agent_state_other = collected_sources_sinks_agent_states_geometries[overlap[0]][0][overlap[1]]
              agent_translated_polygon_other = agent_geometry_other.Translate(
                                              Point2d(agent_state_other[1],
                                                    agent_state_other[2]))
              if Collide(agent_translated_polygon, agent_translated_polygon_other):
                pairwise_collisions.append(((source_sink_idx, agent_idx), overlap))
            
                collisions[key] = pairwise_collisions
    
    return collisions