Example #1
0
    private bool Remove(Node node, IFixedAgent fixedAgent)
    {
        var n = node.linkedList;

        if (n == null)
        {
            return(false);
        }
        if (n == fixedAgent)
        {
            node.linkedList = n.Next;
            node.count--;
            return(true);
        }
        int count = 0;

        while (n.Next != null && count < LeafSize + 1)
        {
            //count++;
            if (n.Next == fixedAgent)
            {
                n.Next = fixedAgent.Next;
                node.count--;
                return(true);
            }
            n = n.Next;
        }
        return(false);
    }
Example #2
0
 private void Add(Node node, IFixedAgent fixedAgent)
 {
     fixedAgent.Next = node.linkedList;
     node.linkedList = fixedAgent;
     node.count++;
     _agentRootDic[fixedAgent] = node;
 }
Example #3
0
    public bool Remove(IFixedAgent fixedAgent)
    {
        Node node = null;

        if (_agentRootDic.TryGetValue(fixedAgent, out node))
        {
            return(Remove(node, fixedAgent));
        }
        return(false);
    }
Example #4
0
    public void Insert <T>(IFixedAgent fixedAgent)
    {
        var r = _bounds;
        var p = new Vector2d(fixedAgent.Position.x, fixedAgent.Position.z);

        fixedAgent.Next = null;
        var node = _root;

        while (true)
        {
            if (!node.HasChild)
            {
                if (node.count < LeafSize)
                {
                    Add(node, fixedAgent);
                    break;
                }
                else
                {
                    Distribute(node, r);
                }
            }
            else
            {
                var c = r.center;
                if (p.x > c.x)
                {
                    if (p.y > c.y)
                    {
                        node = node.child11;
                        r    = Utility.MinMaxRect(c.x, c.y, r.xMax, r.yMax);
                    }
                    else
                    {
                        node = node.child10;
                        r    = Utility.MinMaxRect(c.x, r.yMin, r.xMax, c.y);
                    }
                }
                else
                {
                    if (p.y > c.y)
                    {
                        node = node.child01;
                        r    = Utility.MinMaxRect(r.xMin, c.y, c.x, r.yMax);
                    }
                    else
                    {
                        node = node.child00;
                        r    = Utility.MinMaxRect(r.xMin, r.yMin, c.x, c.y);
                    }
                }
            }
        }
    }
Example #5
0
    private long QueryRec <K>(Node node, IFixedAgent fixedAgent, long radius, List <K> fixedAgents, Utility.FixedRect r) where K : IFixedAgent
    {
        Vector2d p = new Vector2d(fixedAgent.Position.x, fixedAgent.Position.z);

        //找到一个子节点
        if (!node.HasChild)
        {
            var a = node.linkedList;
            while (a != null)
            {
                if (a is K && a != fixedAgent && Vector2d.SqrDistance(p, new Vector2d(a.Position.x, a.Position.z)) < radius.Mul(radius))
                {
                    fixedAgents.Add((K)a);
                }
                a = a.Next;
            }
        }
        else
        {
            //搜索子节点
            var c = r.center;
            if (p.x - radius < c.x)
            {
                if (p.y - radius < c.y)
                {
                    radius = QueryRec(node.child00, fixedAgent, radius, fixedAgents,
                                      Utility.MinMaxRect(r.xMin, r.yMin, c.x, c.y));
                }
                if (p.y + radius > c.y)
                {
                    radius = QueryRec(node.child01, fixedAgent, radius, fixedAgents,
                                      Utility.MinMaxRect(r.xMin, c.y, c.x, r.yMax));
                }
            }

            if (p.x + radius > c.x)
            {
                if (p.y - radius < c.y)
                {
                    radius = QueryRec(node.child10, fixedAgent, radius, fixedAgents,
                                      Utility.MinMaxRect(c.x, r.yMin, r.xMax, c.y));
                }
                if (p.y + radius > c.y)
                {
                    radius = QueryRec(node.child11, fixedAgent, radius, fixedAgents,
                                      Utility.MinMaxRect(c.x, c.y, r.xMax, r.yMax));
                }
            }
        }

        return(radius);
    }
Example #6
0
    public void Relocate(IFixedAgent fixedAgent)
    {
        Node node;

        if (_agentRootDic.TryGetValue(fixedAgent, out node))
        {
            if (!node.rect.ContainsPoint(fixedAgent.Position))
            {
                if (Remove(node, fixedAgent))
                {
                    Insert <T>(fixedAgent);
                }
            }
        }
    }
Example #7
0
    public long InsertAgentNeighbour(IFixedAgent fixedAgent, long rangeSq)
    {
        if (this == fixedAgent)
        {
            return(rangeSq);
        }
        var dist = (fixedAgent.Position.x - Position.x).Mul(fixedAgent.Position.x - Position.x)
                   + (fixedAgent.Position.z - Position.z).Mul(fixedAgent.Position.z - Position.z);

        if (dist < rangeSq)
        {
            if (AgentNeighbors.Count < 10)
            {
                AgentNeighbors.Add(fixedAgent);
                AgentNeighborSqrDists.Add(dist);
            }
            var i = AgentNeighbors.Count - 1;
            if (dist < AgentNeighborSqrDists[i])
            {
                while (i != 0 && dist < AgentNeighborSqrDists[i - 1])
                {
                    AgentNeighbors[i]        = AgentNeighbors[i - 1];
                    AgentNeighborSqrDists[i] = AgentNeighborSqrDists[i - 1];
                    i--;
                }
                AgentNeighbors[i]        = fixedAgent;
                AgentNeighborSqrDists[i] = dist;
            }

            if (AgentNeighbors.Count == 10)
            {
                rangeSq = AgentNeighborSqrDists[AgentNeighbors.Count - 1];
            }
        }
        return(rangeSq);
    }
Example #8
0
 public void Query <K>(IFixedAgent fixedAgent, long radius, List <K> fixedAgents) where K : IFixedAgent
 {
     QueryRec(_root, fixedAgent, radius, fixedAgents, _bounds);
 }
Example #9
0
 public void Query(IFixedAgent fixedAgent, long radius, List <IFixedAgent> fixedAgents)
 {
     QueryRec(_root, fixedAgent, radius, fixedAgents, _bounds);
 }
Example #10
0
 public PathIntersection(IFixedAgent obstacle)
 {
     Obstacle  = obstacle;
     Intersect = false;
     Distance  = float.MaxValue;
 }
Example #11
0
    /// <summary>
    /// Finds a vehicle's next intersection with a spherical obstacle
    /// </summary>
    /// <param name="vehicle">
    /// The vehicle to evaluate.
    /// </param>
    /// <param name="futureVehiclePosition">
    /// The position where we expect the vehicle to be soon
    /// </param>
    /// <param name="obstacle">
    /// A spherical obstacle to check against <see cref="DetectableObject"/>
    /// </param>
    /// <returns>
    /// A PathIntersection with the intersection details <see cref="PathIntersection"/>
    /// </returns>
    /// <remarks>We could probably spin out this function to an independent tool class</remarks>
    public static PathIntersection FindNextIntersectionWithSphere(IFixedAgent vehicle, Vector3 futureVehiclePosition,
                                                                  IFixedAgent obstacle)
    {
        // this mainly follows http://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/

        var intersection = new PathIntersection(obstacle);

        var combinedRadius = vehicle.Radius.ToFloat() + obstacle.Radius.ToFloat();
        var movement       = futureVehiclePosition - vehicle.Position.ToVector3();
        var direction      = movement.normalized;

        var vehicleToObstacle = obstacle.Position - vehicle.Position;

        // this is the length of vehicleToObstacle projected onto direction
        var projectionLength = Vector3.Dot(direction, vehicleToObstacle.ToVector3());

        // if the projected obstacle center lies further away than our movement + both radius, we're not going to collide
        if (projectionLength > movement.magnitude + combinedRadius)
        {
            //print("no collision - 1");
            return(intersection);
        }

        // the foot of the perpendicular
        var projectedObstacleCenter = vehicle.Position.ToVector3() + projectionLength * direction;

        // distance of the obstacle to the pathe the vehicle is going to take
        var obstacleDistanceToPath = (obstacle.Position.ToVector3() - projectedObstacleCenter).magnitude;

        //print("obstacleDistanceToPath: " + obstacleDistanceToPath);

        // if the obstacle is further away from the movement, than both radius, there's no collision
        if (obstacleDistanceToPath > combinedRadius)
        {
            //print("no collision - 2");
            return(intersection);
        }

        // use pythagorean theorem to calculate distance out of the sphere (if you do it 2D, the line through the circle would be a chord and we need half of its length)
        var halfChord = Mathf.Sqrt(combinedRadius * combinedRadius + obstacleDistanceToPath * obstacleDistanceToPath);

        // if the projected obstacle center lies opposite to the movement direction (aka "behind")
        if (projectionLength < 0)
        {
            // behind and further away than both radius -> no collision (we already passed)
            if (vehicleToObstacle.magnitude > combinedRadius)
            {
                return(intersection);
            }

            var intersectionPoint = projectedObstacleCenter - direction * halfChord;
            intersection.Intersect = true;
            intersection.Distance  = (intersectionPoint - vehicle.Position.ToVector3()).magnitude;
            return(intersection);
        }

        // calculate both intersection points
        var intersectionPoint1 = projectedObstacleCenter - direction * halfChord;
        var intersectionPoint2 = projectedObstacleCenter + direction * halfChord;

        // pick the closest one
        var intersectionPoint1Distance = (intersectionPoint1 - vehicle.Position.ToVector3()).magnitude;
        var intersectionPoint2Distance = (intersectionPoint2 - vehicle.Position.ToVector3()).magnitude;

        intersection.Intersect = true;
        intersection.Distance  = Mathf.Min(intersectionPoint1Distance, intersectionPoint2Distance);

        return(intersection);
    }