Example usage for org.apache.commons.math3.geometry.euclidean.twod Vector2D getNorm

List of usage examples for org.apache.commons.math3.geometry.euclidean.twod Vector2D getNorm

Introduction

In this page you can find the example usage for org.apache.commons.math3.geometry.euclidean.twod Vector2D getNorm.

Prototype

public double getNorm() 

Source Link

Usage

From source file:edu.unc.cs.gamma.rvo.Agent.java

/**
 * Computes the new velocity of this agent.
 *///from   w  ww.j  a  v  a  2s. c  om
void computeNewVelocity() {
    lines.clear();

    final double invTimeHorizonObstacle = 1.0 / timeHorizonObstacles;

    // Create obstacle ORCA lines.
    for (final Pair<Double, Obstacle> obstacleNeighbor : obstacleNeighbors) {
        Obstacle obstacle1 = obstacleNeighbor.getSecond();
        Obstacle obstacle2 = obstacle1.next;

        final Vector2D relativePosition1 = obstacle1.point.subtract(position);
        final Vector2D relativePosition2 = obstacle2.point.subtract(position);

        // Check if velocity obstacle of obstacle is already taken care of
        // by previously constructed obstacle ORCA lines.
        boolean alreadyCovered = false;

        for (final Line orcaLine : lines) {
            if (RVOMath.det(relativePosition1.scalarMultiply(invTimeHorizonObstacle).subtract(orcaLine.point),
                    orcaLine.direction) - invTimeHorizonObstacle * radius >= -RVOMath.EPSILON
                    && RVOMath
                            .det(relativePosition2.scalarMultiply(invTimeHorizonObstacle)
                                    .subtract(orcaLine.point), orcaLine.direction)
                            - invTimeHorizonObstacle * radius >= -RVOMath.EPSILON) {
                alreadyCovered = true;

                break;
            }
        }

        if (alreadyCovered) {
            continue;
        }

        // Not yet covered. Check for collisions.
        final double distanceSq1 = relativePosition1.getNormSq();
        final double distanceSq2 = relativePosition2.getNormSq();
        final double radiusSq = radius * radius;

        final Vector2D obstacleVector = obstacle2.point.subtract(obstacle1.point);
        final double s = -relativePosition1.dotProduct(obstacleVector) / obstacleVector.getNormSq();
        final double distanceSqLine = relativePosition1.add(s, obstacleVector).getNormSq();

        if (s < 0.0 && distanceSq1 <= radiusSq) {
            // Collision with left vertex. Ignore if non-convex.
            if (obstacle1.convex) {
                final Vector2D direction = new Vector2D(-relativePosition1.getY(), relativePosition1.getX())
                        .normalize();
                lines.add(new Line(Vector2D.ZERO, direction));
            }

            continue;
        }

        if (s > 1.0 && distanceSq2 <= radiusSq) {
            // Collision with right vertex. Ignore if non-convex or if it
            // will be taken care of by neighboring obstacle.
            if (obstacle2.convex && RVOMath.det(relativePosition2, obstacle2.direction) >= 0.0) {
                final Vector2D direction = new Vector2D(-relativePosition2.getY(), relativePosition2.getX())
                        .normalize();
                lines.add(new Line(Vector2D.ZERO, direction));
            }

            continue;
        }

        if (s >= 0.0 && s < 1.0 && distanceSqLine <= radiusSq) {
            // Collision with obstacle segment.
            final Vector2D direction = obstacle1.direction.negate();
            lines.add(new Line(Vector2D.ZERO, direction));

            continue;
        }

        // No collision. Compute legs. When obliquely viewed, both legs can
        // come from a single vertex. Legs extend cut-off line when
        // non-convex vertex.
        Vector2D leftLegDirection;
        Vector2D rightLegDirection;

        if (s < 0.0 && distanceSqLine <= radiusSq) {
            // Obstacle viewed obliquely so that left vertex defines
            // velocity obstacle.
            if (!obstacle1.convex) {
                // Ignore obstacle.
                continue;
            }

            obstacle2 = obstacle1;

            final double leg1 = FastMath.sqrt(distanceSq1 - radiusSq);
            leftLegDirection = new Vector2D(relativePosition1.getX() * leg1 - relativePosition1.getY() * radius,
                    relativePosition1.getX() * radius + relativePosition1.getY() * leg1)
                            .scalarMultiply(1.0 / distanceSq1);
            rightLegDirection = new Vector2D(
                    relativePosition1.getX() * leg1 + relativePosition1.getY() * radius,
                    -relativePosition1.getX() * radius + relativePosition1.getY() * leg1)
                            .scalarMultiply(1.0 / distanceSq1);
        } else if (s > 1.0 && distanceSqLine <= radiusSq) {
            // Obstacle viewed obliquely so that right vertex defines
            // velocity obstacle.
            if (!obstacle2.convex) {
                // Ignore obstacle.
                continue;
            }

            obstacle1 = obstacle2;

            final double leg2 = FastMath.sqrt(distanceSq2 - radiusSq);
            leftLegDirection = new Vector2D(relativePosition2.getX() * leg2 - relativePosition2.getY() * radius,
                    relativePosition2.getX() * radius + relativePosition2.getY() * leg2)
                            .scalarMultiply(1.0 / distanceSq2);
            rightLegDirection = new Vector2D(
                    relativePosition2.getX() * leg2 + relativePosition2.getY() * radius,
                    -relativePosition2.getX() * radius + relativePosition2.getY() * leg2)
                            .scalarMultiply(1.0 / distanceSq2);
        } else {
            // Usual situation.
            if (obstacle1.convex) {
                final double leg1 = FastMath.sqrt(distanceSq1 - radiusSq);
                leftLegDirection = new Vector2D(
                        relativePosition1.getX() * leg1 - relativePosition1.getY() * radius,
                        relativePosition1.getX() * radius + relativePosition1.getY() * leg1)
                                .scalarMultiply(1.0 / distanceSq1);
            } else {
                // Left vertex non-convex; left leg extends cut-off line.
                leftLegDirection = obstacle1.direction.negate();
            }

            if (obstacle2.convex) {
                final double leg2 = FastMath.sqrt(distanceSq2 - radiusSq);
                rightLegDirection = new Vector2D(
                        relativePosition2.getX() * leg2 + relativePosition2.getY() * radius,
                        -relativePosition2.getX() * radius + relativePosition2.getY() * leg2)
                                .scalarMultiply(1.0 / distanceSq2);
            } else {
                // Right vertex non-convex; right leg extends cut-off line.
                rightLegDirection = obstacle1.direction;
            }
        }

        // Legs can never point into neighboring edge when convex vertex,
        // take cut-off line of neighboring edge instead. If velocity
        // projected on "foreign" leg, no constraint is added.
        boolean leftLegForeign = false;
        boolean rightLegForeign = false;

        if (obstacle1.convex && RVOMath.det(leftLegDirection, obstacle1.previous.direction.negate()) >= 0.0) {
            // Left leg points into obstacle.
            leftLegDirection = obstacle1.previous.direction.negate();
            leftLegForeign = true;
        }

        if (obstacle2.convex && RVOMath.det(rightLegDirection, obstacle2.direction) <= 0.0) {
            // Right leg points into obstacle.
            rightLegDirection = obstacle2.direction;
            rightLegForeign = true;
        }

        // Compute cut-off centers.
        final Vector2D leftCutOff = obstacle1.point.subtract(position).scalarMultiply(invTimeHorizonObstacle);
        final Vector2D rightCutOff = obstacle2.point.subtract(position).scalarMultiply(invTimeHorizonObstacle);
        final Vector2D cutOffVector = rightCutOff.subtract(leftCutOff);

        // Project current velocity on velocity obstacle.

        // Check if current velocity is projected on cutoff circles.
        final double t = obstacle1 == obstacle2 ? 0.5
                : velocity.subtract(leftCutOff).dotProduct(cutOffVector) / cutOffVector.getNormSq();
        final double tLeft = velocity.subtract(leftCutOff).dotProduct(leftLegDirection);
        final double tRight = velocity.subtract(rightCutOff).dotProduct(rightLegDirection);

        if (t < 0.0 && tLeft < 0.0 || obstacle1 == obstacle2 && tLeft < 0.0 && tRight < 0.0) {
            // Project on left cut-off circle.
            final Vector2D unitW = velocity.subtract(leftCutOff).normalize();

            final Vector2D direction = new Vector2D(unitW.getY(), -unitW.getX());
            final Vector2D point = leftCutOff.add(radius * invTimeHorizonObstacle, unitW);
            lines.add(new Line(point, direction));

            continue;
        }

        if (t > 1.0 && tRight < 0.0) {
            // Project on right cut-off circle.
            final Vector2D unitW = velocity.subtract(rightCutOff).normalize();

            final Vector2D direction = new Vector2D(unitW.getY(), -unitW.getX());
            final Vector2D point = rightCutOff.add(radius * invTimeHorizonObstacle, unitW);
            lines.add(new Line(point, direction));

            continue;
        }

        // Project on left leg, right leg, or cut-off line, whichever is
        // closest to velocity.
        final double distanceSqCutOff = t < 0.0 || t > 1.0 || obstacle1 == obstacle2 ? Double.POSITIVE_INFINITY
                : velocity.distanceSq(leftCutOff.add(cutOffVector.scalarMultiply(t)));
        final double distanceSqLeft = tLeft < 0.0 ? Double.POSITIVE_INFINITY
                : velocity.distanceSq(leftCutOff.add(leftLegDirection.scalarMultiply(tLeft)));
        final double distanceSqRight = tRight < 0.0 ? Double.POSITIVE_INFINITY
                : velocity.distanceSq(rightCutOff.add(rightLegDirection.scalarMultiply(tRight)));

        if (distanceSqCutOff <= distanceSqLeft && distanceSqCutOff <= distanceSqRight) {
            // Project on cut-off line.
            final Vector2D direction = obstacle1.direction.negate();
            final Vector2D point = leftCutOff.add(radius * invTimeHorizonObstacle,
                    new Vector2D(-direction.getY(), direction.getX()));
            lines.add(new Line(point, direction));

            continue;
        }

        if (distanceSqLeft <= distanceSqRight) {
            // Project on left leg.
            if (leftLegForeign) {
                continue;
            }

            final Vector2D point = leftCutOff.add(radius * invTimeHorizonObstacle,
                    new Vector2D(-leftLegDirection.getY(), leftLegDirection.getX()));
            lines.add(new Line(point, leftLegDirection));

            continue;
        }

        // Project on right leg.
        if (rightLegForeign) {
            continue;
        }

        final Vector2D direction = rightLegDirection.negate();
        final Vector2D point = rightCutOff.add(radius * invTimeHorizonObstacle,
                new Vector2D(-direction.getY(), direction.getX()));
        lines.add(new Line(point, direction));
    }

    final int numObstacleLines = lines.size();

    final double invTimeHorizon = 1.0 / timeHorizonAgents;

    // Create agent ORCA lines.
    for (final Pair<Double, Agent> agentNeighbor : agentNeighbors) {
        final Agent other = agentNeighbor.getSecond();

        final Vector2D relativePosition = other.position.subtract(position);
        final Vector2D relativeVelocity = velocity.subtract(other.velocity);
        final double distanceSq = relativePosition.getNormSq();
        final double combinedRadius = radius + other.radius;
        final double combinedRadiusSq = combinedRadius * combinedRadius;

        final Vector2D direction;
        final Vector2D u;

        if (distanceSq > combinedRadiusSq) {
            // No collision.
            final Vector2D w = relativeVelocity.subtract(invTimeHorizon, relativePosition);

            // Vector from cutoff center to relative velocity.
            final double wLengthSq = w.getNormSq();
            final double dotProduct1 = w.dotProduct(relativePosition);

            if (dotProduct1 < 0.0 && dotProduct1 * dotProduct1 > combinedRadiusSq * wLengthSq) {
                // Project on cut-off circle.
                final double wLength = FastMath.sqrt(wLengthSq);
                final Vector2D unitW = w.scalarMultiply(1.0 / wLength);

                direction = new Vector2D(unitW.getY(), -unitW.getX());
                u = unitW.scalarMultiply(combinedRadius * invTimeHorizon - wLength);
            } else {
                // Project on legs.
                final double leg = FastMath.sqrt(distanceSq - combinedRadiusSq);

                if (RVOMath.det(relativePosition, w) > 0.0) {
                    // Project on left leg.
                    direction = new Vector2D(
                            relativePosition.getX() * leg - relativePosition.getY() * combinedRadius,
                            relativePosition.getX() * combinedRadius + relativePosition.getY() * leg)
                                    .scalarMultiply(1.0 / distanceSq);
                } else {
                    // Project on right leg.
                    direction = new Vector2D(
                            relativePosition.getX() * leg + relativePosition.getY() * combinedRadius,
                            -relativePosition.getX() * combinedRadius + relativePosition.getY() * leg)
                                    .scalarMultiply(-1.0 / distanceSq);
                }

                final double dotProduct2 = relativeVelocity.dotProduct(direction);
                u = direction.scalarMultiply(dotProduct2).subtract(relativeVelocity);
            }
        } else {
            // Collision. Project on cut-off circle of time timeStep.
            final double invTimeStep = 1.0 / Simulator.instance.timeStep;

            // Vector from cutoff center to relative velocity.
            final Vector2D w = relativeVelocity.subtract(invTimeStep, relativePosition);

            final double wLength = w.getNorm();
            final Vector2D unitW = w.scalarMultiply(1.0 / wLength);

            direction = new Vector2D(unitW.getY(), -unitW.getX());
            u = unitW.scalarMultiply(combinedRadius * invTimeStep - wLength);
        }

        final Vector2D point = velocity.add(0.5, u);
        lines.add(new Line(point, direction));
    }

    final int lineFail = linearProgram2(lines, preferredVelocity, false);

    if (lineFail < lines.size()) {
        linearProgram3(numObstacleLines, lineFail);
    }
}