Esempio n. 1
0
def pruneContainment(scenario, verbosity):
    """Prune based on the requirement that individual Objects fit within their container.

    Specifically, if O is positioned uniformly in region B and has container C, then we
    can instead pick a position uniformly in their intersection. If we can also lower
    bound the radius of O, then we can first erode C by that distance.
    """
    for obj in scenario.objects:
        base = matchInRegion(obj.position)
        if base is None:  # match objects positioned uniformly in a Region
            continue
        basePoly = regions.toPolygon(base)
        if basePoly is None:  # to prune, the Region must be polygonal
            continue
        container = scenario.containerOfObject(obj)
        containerPoly = regions.toPolygon(container)
        if containerPoly is None:  # the object's container must also be polygonal
            return None
        minRadius, _ = supportInterval(obj.inradius)
        if minRadius is not None:  # if we can lower bound the radius, erode the container
            containerPoly = containerPoly.buffer(-minRadius)
        elif base is container:
            continue
        newBasePoly = basePoly & containerPoly  # restrict the base Region to the container
        if verbosity >= 1:
            percent = 100 * (1.0 - (newBasePoly.area / basePoly.area))
            print(
                f'    Region containment constraint pruned {percent:.1f}% of space.'
            )
        newBase = regions.PolygonalRegion(polygon=newBasePoly,
                                          orientation=base.orientation)
        newPos = regions.Region.uniformPointIn(newBase)
        obj.position.conditionTo(newPos)
Esempio n. 2
0
def pruneRelativeHeading(scenario, verbosity):
    """Prune based on requirements bounding the relative heading of an Object.

    Specifically, if an object O is:
        * positioned uniformly within a polygonal region B;
        * aligned to a polygonal vector field F (up to a bounded offset);
    and another object O' is:
        * aligned to a polygonal vector field F' (up to a bounded offset);
        * at most some finite maximum distance from O;
        * required to have relative heading within a bounded offset of that of O;
    then we can instead position O uniformly in the subset of B intersecting the cells
    of F which satisfy the relative heading requirements w.r.t. some cell of F' which
    is within the distance bound.
    """
    # Check which objects are (approximately) aligned to polygonal vector fields
    fields = {}
    for obj in scenario.objects:
        field, offsetL, offsetR = matchPolygonalField(obj.heading,
                                                      obj.position)
        if field is not None:
            fields[obj] = (field, offsetL, offsetR)
    # Check for relative heading relations among such objects
    for obj, (field, offsetL, offsetR) in fields.items():
        position = currentPropValue(obj, 'position')
        base = matchInRegion(position)
        if base is None:  # obj must be positioned uniformly in a Region
            continue
        basePoly = regions.toPolygon(base)
        if basePoly is None:  # the Region must be polygonal
            continue
        newBasePoly = basePoly
        for rel in obj._relations:
            if isinstance(rel,
                          RelativeHeadingRelation) and rel.target in fields:
                tField, tOffsetL, tOffsetR = fields[rel.target]
                maxDist = maxDistanceBetween(scenario, obj, rel.target)
                if maxDist == float(
                        'inf'
                ):  # the distance between the objects must be bounded
                    continue
                feasible = feasibleRHPolygon(field, offsetL, offsetR, tField,
                                             tOffsetL, tOffsetR, rel.lower,
                                             rel.upper, maxDist)
                if feasible is None:  # the RH bounds may be too weak to restrict the space
                    continue
                try:
                    pruned = newBasePoly & feasible
                except shapely.geos.TopologicalError:  # TODO how can we prevent these??
                    pruned = newBasePoly & feasible.buffer(0.1, cap_style=2)
                if verbosity >= 1:
                    percent = 100 * (1.0 - (pruned.area / newBasePoly.area))
                    print(
                        f'    Relative heading constraint pruned {percent:.1f}% of space.'
                    )
                newBasePoly = pruned
        if newBasePoly is not basePoly:
            newBase = regions.PolygonalRegion(polygon=newBasePoly,
                                              orientation=base.orientation)
            newPos = regions.Region.uniformPointIn(newBase)
            obj.position.conditionTo(newPos)
Esempio n. 3
0
def pruneRelativeHeading(scenario, verbosity):
    # Check which objects are (approximately) aligned to polygonal vector fields
    fields = {}
    for obj in scenario.objects:
        field, offsetL, offsetR = matchPolygonalField(obj.heading,
                                                      obj.position)
        if field is not None:
            fields[obj] = (field, offsetL, offsetR)
    # Check for relative heading relations
    for obj, (field, offsetL, offsetR) in fields.items():
        position = currentPropValue(obj, 'position')
        base = matchInRegion(position)
        if base is None:
            continue
        basePoly = regions.toPolygon(base)
        if basePoly is None:
            continue
        newBasePoly = basePoly
        for rel in obj._relations:
            if isinstance(rel,
                          RelativeHeadingRelation) and rel.target in fields:
                tField, tOffsetL, tOffsetR = fields[rel.target]
                maxDist = maxDistanceBetween(scenario, obj, rel.target)
                if maxDist is None:
                    continue
                feasible = feasibleRHPolygon(field, offsetL, offsetR, tField,
                                             tOffsetL, tOffsetR, rel.lower,
                                             rel.upper, maxDist)
                if feasible is None:
                    continue
                try:
                    pruned = newBasePoly & feasible
                except shapely.geos.TopologicalError:  # TODO how can we prevent these??
                    pruned = newBasePoly & feasible.buffer(0.1, cap_style=2)
                if verbosity >= 1:
                    percent = 100 * (1.0 - (pruned.area / newBasePoly.area))
                    print(
                        f'    Relative heading constraint pruned {percent:.1f}% of space.'
                    )
                newBasePoly = pruned
        if newBasePoly is not basePoly:
            newBase = regions.PolygonalRegion(polygon=newBasePoly,
                                              orientation=base.orientation)
            newPos = regions.Region.uniformPointIn(newBase)
            obj.position.conditionTo(newPos)