Exemple #1
0
    //returns null for no intersection
    public CSGsegment getClosestIntersectingSegment(CSGshape shape, bool isMovingForward)
    {
        var candidates = new List <CSGsegment>();

        foreach (var i in shape.segments)
        {
            if (i.doesIntersect(this))
            {
                candidates.Add(i);
            }
        }
        float      currBestDist = float.PositiveInfinity;
        CSGsegment currBest     = null;

        foreach (var i in candidates)
        {
            var point = i.intersectionPoint(this);
            var dist  = (this.getPoint(isMovingForward) - point).magnitude;
            if (dist < currBestDist)
            {
                currBestDist = dist;
                currBest     = i;
            }
        }
        return(currBest);
    }
Exemple #2
0
 public bool doesIntersect(CSGsegment seg)
 {
     foreach (var i in this.segments)
     {
         if (i.doesIntersect(seg))
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #3
0
    private bool isPointInside(Vector2 point)
    {
        var collisionLine = new CSGsegment(point, new Vector2(largePositive, point.y));

        CSGsegment.LetterCounter--;
        int counter = 0;

        foreach (var i in this.segments)
        {
            if (collisionLine.doesIntersect(i))
            {
                counter++;
            }
        }
        return(counter % 2 == 1);       //odd number of intersections? then it is inside the shape
    }
Exemple #4
0
    public Vector2 intersectionPoint(CSGsegment other)//can optimize by removing redundant slope&yinter calculations
    {
        if (this.end.x == this.start.x && other.start.x == other.end.x)
        {
            throw new Exception("Vertical overlapping lines");
            //Debug.Log("Vertical overlapping lines");
            //return this.end;
        }
        if (this.end.x == this.start.x)
        {
            return(new Vector2(this.start.x, other.getSlope() * this.start.x + other.getYInter()));
        }
        else if (other.end.x == other.start.x)
        {
            return(new Vector2(other.start.x, this.getSlope() * other.start.x + this.getYInter()));
        }
        var num   = this.getYInter() - other.getYInter();
        var denom = other.getSlope() - this.getSlope();
        var x     = num / denom;

        return(new Vector2(x, x * this.getSlope() + this.getYInter()));
    }
Exemple #5
0
    //make sure to only wiggle a little bit, according to some small constant
    public bool getDirection(CSGsegment seg, bool isEntering, Vector2 intersectionPoint)
    {
        var startWiggle = intersectionPoint + smallDelta * (seg.start - intersectionPoint).normalized;
        var endWiggle   = intersectionPoint + smallDelta * (seg.end - intersectionPoint).normalized;
        var isStart     = isPointInside(startWiggle);
        var isEnd       = isPointInside(endWiggle);

        if (isStart && isEnd)
        {
            throw new Exception("Delta too large: error encountered");
        }
        else if (!isStart && !isEnd)
        {
            throw new Exception("This really shouldn't happen");
        }
        if (isEntering)
        {
            return(!isStart);
        }
        else
        {
            return(!isEnd);
        }
    }
Exemple #6
0
    /*public static bool operator ==(CSGshape a,CSGshape b)
     * {
     *      CSGsegment first = null;
     *      CSGsegment other = null;
     *      if (a.isClockwise() != b.isClockwise())
     *      {
     *              throw new Exception();//slow, remove eventually
     *      }
     *      foreach (var j in a.segments)
     *      {
     *              foreach (var i in b.segments)
     *              {
     *                      if (j.start == i.start)
     *                      {
     *                              first = j;
     *                              other = i;
     *                              break;
     *                      }
     *              }
     *      }
     *      if (first == null)
     *      {
     *              return false;
     *      }
     *      var curr = first;
     *      var otherCurr = other;
     *      do
     *      {
     *              if (curr.start != otherCurr.start)
     *              {
     *                      return false;
     *              }
     *              otherCurr = otherCurr.endSegment;
     *              curr = curr.endSegment;
     *      } while (curr!=first);
     *      return true;
     * }*/

    //such a trash function to make sure 2 identical shapes are on top of each other

    /*public static List<CollisionHull> prune(List<CollisionHull> existingShapes, List<CollisionHull> listToPrune)
     * {
     *      listToPrune.AddRange(existingShapes);
     *      listToPrune = removeDups(listToPrune);
     *      listToPrune.RemoveAll(a => existingShapes.Contains(a));
     *      return listToPrune;
     * }
     *
     * public static List<CollisionHull> removeDups(List<CollisionHull> list)
     * {
     *      List<CollisionHull> retr = new List<CollisionHull>();
     *      //list.RemoveAll(a => list.FindAll(b=>b.externalHull==a).Count()>1);
     *      foreach (var i in list)
     *      {
     *              if (retr.Count == 0)
     *              {
     *                      retr.Add(i);
     *              }
     *              else
     *              {
     *                      foreach (var j in retr)
     *                      {
     *                              if (i.externalHull == j.externalHull)
     *                              {
     *                                      break;
     *                              }
     *                              else if (j == retr[retr.Count - 1])
     *                              {
     *                                      retr.Add(i);
     *                                      break;
     *                              }
     *                      }
     *              }
     *      }
     *      return retr;
     * }
     * public static bool operator !=(CSGshape a,CSGshape b)
     * {
     *      return !(a == b);
     * }*/
    public CSGshape(List <Vector2> points)
    {
        segments = new List <CSGsegment>();
        CSGsegment lastSegment = null;
        Vector2    prev        = points[points.Count - 1];

        foreach (var i in points)
        {
            var currSegment = new CSGsegment(prev, i);
            //Debug.Log(currSegment.Letter);
            segments.Add(currSegment);
            if (lastSegment != null)
            {
                currSegment.startSegment = lastSegment;
                lastSegment.endSegment   = currSegment;
            }
            lastSegment = currSegment;
            prev        = i;
        }
        var first = segments[0];

        first.startSegment     = lastSegment;
        lastSegment.endSegment = first;
    }
Exemple #7
0
    ///end of not my code

    public bool doesIntersect(CSGsegment other)
    {
        return(doIntersect(this.start, this.end, other.start, other.end));
    }
Exemple #8
0
    //returns a list of the segments of the path and then the segment on the other shape which ended the path, also ends when it reaches the start
    public Tuple <List <CSGsegment>, CSGsegment> ridePathUntilIntersection(CSGshape shapeToIntersect, List <CSGsegment> externalSegments, bool isMovingForward, CSGsegment first, bool isStart = false)
    {
        var retr     = new Tuple <List <CSGsegment>, CSGsegment>();
        var curr     = this;
        var retrList = new List <CSGsegment>();

        retr.first  = retrList;
        retr.second = null;
        while (curr != first || isStart)
        {
            //Debug.Log(curr.Letter);
            isStart = false;
            retrList.Add(curr);
            if (externalSegments.Contains(curr))//slow linear search
            {
                externalSegments.Remove(curr);
            }
            var intersection = curr.getClosestIntersectingSegment(shapeToIntersect, isMovingForward);
            if (intersection == null)
            {
                curr = curr.next(isMovingForward);
            }
            else
            {
                retr.second = intersection;
                return(retr);
            }
        }
        return(retr);
    }
Exemple #9
0
    //collision hull.hull or whatever is null if nothing is left
    public static List <CollisionHull> not(CSGshape shape, CSGshape other, bool isNot, out bool usedFlag, List <CSGshape> holes = null)
    {
        //start with a point on me thats not in the other shape
        //List<CSGshape> retr = new List<CSGshape>();
        List <CollisionHull> hulls            = new List <CollisionHull>();
        List <CSGsegment>    externalSegments = shape.getExternalSegments(other);

        usedFlag = !isNot;
        if (other.segments.TrueForAll(i => !shape.doesIntersect(i)) && !isNot)
        {
            var foo = new CollisionHull();
            foo.externalHull = shape;
            foo.holes        = holes;

            /*var bar = new CollisionHull();
             * bar.externalHull = other;*/
            hulls.Add(foo);
            //hulls.Add(bar);
            usedFlag = false;
            return(hulls);
        }
        else if (externalSegments.Count == 0)        //other completely surrounds this
        {
            if (isNot)
            {
                return(hulls);
            }
            else
            {
                hulls.Add(new CollisionHull());
                hulls[0].externalHull = other;
                return(hulls);
            }
        }
        else if (externalSegments.Count == shape.segments.Count && other.segments.TrueForAll(a => shape.isPointInside(a.start)))        //this completely surrounds other
        {
            if (isNot)
            {
                var foo = new List <CSGshape>();
                foo.Add(other);
                if (holes != null)
                {
                    foo.AddRange(holes);
                }
                foo = andAll(foo);
                var hull = new CollisionHull();
                hull.externalHull = shape;
                hull.holes.Add(other);
                hulls.Add(hull);
            }
            else
            {
                hulls.Add(new CollisionHull());
                hulls[0].externalHull = shape;
            }
            return(hulls);
            //throw new NotImplementedException();

            /*float closestDist = float.PositiveInfinity;
             * CSGsegment closestItem = null;
             * CSGsegment closestInnerItem = null;
             * if (!other.isClockwise())
             * {
             * other.antiRotate();
             * }
             * foreach (var i in shape.segments)
             * {
             * foreach (var j in other.segments)
             * {
             * var dist = (i.end - j.start).magnitude;
             * if (dist < closestDist)
             * {
             * closestItem = i;
             * closestInnerItem = j;
             * closestDist = dist;
             * }
             * }
             * }
             * var enter = new CSGsegment(closestItem.end, closestInnerItem.start);
             * var exit = new CSGsegment(closestInnerItem.start, closestItem.end);
             * var oldnext = closestItem.endSegment;
             * var oldinnernext = closestInnerItem.startSegment;
             * oldnext.startSegment = exit;
             * closestItem.endSegment = enter;
             * enter.endSegment = closestInnerItem;
             * exit.endSegment = oldnext;
             * oldinnernext.endSegment = exit;
             * enter.startSegment = closestItem;
             * closestInnerItem.startSegment = enter;
             * exit.startSegment = oldinnernext;
             *
             * CSGsegment curr = enter;
             * List<Vector2> newPoints = new List<Vector2>();
             * do
             * {
             * newPoints.Add(curr.getPoint(true));
             * curr = curr.next(true);
             * } while (curr!=enter);
             * retr.Add(new CSGshape(newPoints));
             * return retr;*/
        }
        else
        {
            while (externalSegments.Count > 0)
            {
                List <Vector2> newPoints       = new List <Vector2>();
                bool           isMovingForward = true;
                var            first           = externalSegments[0];//better to remove at start or end? look this up
                var            curr            = first;
                var            isStart         = true;
                externalSegments.RemoveAt(0);
                int counter = 0;
                while (true)
                {
                    if (counter > 100)                    //remove this?
                    {
                        throw new Exception("Linerider exceeded 100 steps");
                        //break;
                    }
                    counter++;
                    var partialPath = curr.ridePathUntilIntersection(other, externalSegments, isMovingForward, first, isStart);
                    foreach (var i in partialPath.first)
                    {
                        newPoints.Add(i.getPoint(isMovingForward));
                    }
                    if (partialPath.second == null)
                    {
                        break;
                    }
                    var intersectionPoint = partialPath.first[partialPath.first.Count - 1].intersectionPoint(partialPath.second);
                    isMovingForward = shape.getDirection(partialPath.second, isNot, intersectionPoint);                    //toggle this to add instead of subtract
                    isStart         = false;
                    //now we must enter this shape, so test the two points
                    var exitPoint     = partialPath.second.getPoint(!isMovingForward);                //!isMovingForward so we get end instead of start
                    var entrancePoint = intersectionPoint + smallDelta * (exitPoint - intersectionPoint).normalized;
                    if (isMovingForward)
                    {
                        curr = new CSGsegment(entrancePoint, exitPoint);
                    }
                    else
                    {
                        curr = new CSGsegment(exitPoint, entrancePoint);
                    }
                    curr.startSegment = partialPath.second.startSegment;
                    curr.endSegment   = partialPath.second.endSegment;
                    ////////////////////////now inside this
                    partialPath = curr.ridePathUntilIntersection(shape, externalSegments, isMovingForward, null);                    //null because it can't end inside
                    foreach (var i in partialPath.first)
                    {
                        newPoints.Add(i.getPoint(isMovingForward));
                    }
                    intersectionPoint = partialPath.first[partialPath.first.Count - 1].intersectionPoint(partialPath.second);
                    isMovingForward   = other.getDirection(partialPath.second, false, intersectionPoint);
                    //now we gotta leave this shape
                    exitPoint     = partialPath.second.getPoint(!isMovingForward);                //!isMovingForward so we get end instead of start
                    entrancePoint = intersectionPoint + smallDelta * (exitPoint - intersectionPoint).normalized;
                    if (isMovingForward)
                    {
                        curr = new CSGsegment(entrancePoint, exitPoint);
                    }
                    else
                    {
                        curr = new CSGsegment(exitPoint, entrancePoint);
                    }
                    curr.startSegment = partialPath.second.startSegment;
                    curr.endSegment   = partialPath.second.endSegment;
                }
                var foo      = new CollisionHull();
                var newShape = new CSGshape(newPoints);
                foo.externalHull = newShape;
                hulls.Add(foo);
            }
            return(hulls);
        }
    }