Exemple #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)
Exemple #2
0
def visibilityBound(obj, target):
    """Upper bound the distance from an Object to another it can see."""
    # Upper bound on visible distance is a sum of several terms:
    # 1. obj.visibleDistance
    _, maxVisibleDistance = supportInterval(obj.visibleDistance)
    if maxVisibleDistance is None:
        return None
    # 2. distance from obj's center to its camera
    _, maxCameraX = supportInterval(obj.cameraOffset.x)
    _, maxCameraY = supportInterval(obj.cameraOffset.y)
    if maxCameraX is None or maxCameraY is None:
        return None
    maxVisibleDistance += math.hypot(maxCameraX, maxCameraY)
    # 3. radius of target
    _, maxRadius = supportInterval(target.radius)
    if maxRadius is None:
        return None
    maxVisibleDistance += maxRadius
    return maxVisibleDistance
Exemple #3
0
def maxDistanceBetween(scenario, obj, target):
    # TODO also infer from requirements
    ego = scenario.egoObject
    if not ((obj is ego and target.requireVisible) or
            (target is ego and obj.requireVisible)):
        return None
    # Upper bound on visible distance is a sum of several terms:
    # 1. obj.visibleDistance
    _, maxVisibleDistance = supportInterval(obj.visibleDistance)
    if maxVisibleDistance is None:
        return None
    # 2. distance from obj's center to its camera
    _, maxCameraX = supportInterval(obj.cameraOffset.x)
    _, maxCameraY = supportInterval(obj.cameraOffset.y)
    if maxCameraX is None or maxCameraY is None:
        return None
    maxVisibleDistance += math.hypot(maxCameraX, maxCameraY)
    # 3. radius of target
    _, maxRadius = supportInterval(target.radius)
    if maxRadius is None:
        return None
    maxVisibleDistance += maxRadius
    return maxVisibleDistance
Exemple #4
0
def matchPolygonalField(heading, position):
    if (isMethodCall(heading, VectorField.__getitem__)
            and isinstance(heading.object, PolygonalVectorField)
            and heading.arguments == (position.toVector(), )):
        return heading.object, 0, 0
    elif isinstance(heading,
                    OperatorDistribution) and heading.operator in ('__add__',
                                                                   '__radd__'):
        field, lower, upper = matchPolygonalField(heading.object, position)
        if field is not None:
            assert len(heading.operands) == 1
            offset = heading.operands[0]
            ol, oh = supportInterval(offset)
            if ol is not None and oh is not None:
                return field, lower + ol, upper + oh
    return None, 0, 0
Exemple #5
0
def matchPolygonalField(heading, position):
    """Match headings defined by a PolygonalVectorField at the given position.

    Matches headings exactly equal to a PolygonalVectorField, or offset by a
    bounded disturbance. Returns a triplet consisting of the matched field if
    any, together with lower/upper bounds on the disturbance.
    """
    if (isMethodCall(heading, VectorField.__getitem__)
        and isinstance(heading.object, PolygonalVectorField)
        and heading.arguments == (position.toVector(),)):
        return heading.object, 0, 0
    elif isinstance(heading, OperatorDistribution) and heading.operator in ('__add__', '__radd__'):
        field, lower, upper = matchPolygonalField(heading.object, position)
        if field is not None:
            assert len(heading.operands) == 1
            offset = heading.operands[0]
            ol, oh = supportInterval(offset)
            if ol is not None and oh is not None:
                return field, lower + ol, upper + oh
    return None, 0, 0