void OnEnable()
    {
        _instance = this;

        if (Application.isPlaying)
        {
            StartCoroutine(Loop());
        }
    }
    private bool CheckIfNeedSubdivide(List <BorderPoint> growPoints)
    {
        float segementSubdDist = InfluenceCirclesManager.SegementSubdDist();

        if (growPoints.Any(v => Vector3.Distance(v.pointA, v.pointB) > segementSubdDist))
        {
            SubdSegments(segementSubdDist);
            return(true);
        }

        return(false);
    }
    public void GenerateInitial()
    {
        //growPoints.Add(transform.position);

        var points = GenerateCircle(polygonRadius, InfluenceCirclesManager.NumSides(), transform.position, false);


        borderPoints = new List <BorderPoint>();
        foreach (Vector3 p in points)
        {
            borderPoints.Add(new BorderPoint()
            {
                pointA = p
            });
        }

        borderPoints_subPolygons = new List <List <BorderPoint> >()
        {
            borderPoints
        };

        UpdateModel();
    }
 public void GenerateCircle(Vector3 centerPoint)
 {
     GenerateCircle(polygonRadius, InfluenceCirclesManager.NumSides(), centerPoint);
 }
    public void GrowUniform(float growDist)
    {
        #region Calc grow points

        SubdSegments(InfluenceCirclesManager.SegementSubdDist());


        var allSceneBorderPoints = allInfluenceCircles
                                   .Where(v => v != this)
                                   .SelectMany(v => v.borderPoints).ToList();
        var allSceneBorderPoints_NotThisFraction = allSceneBorderPoints
                                                   .Where(c => c.circle.fraction != fraction).ToList();


        var notBlocked_BP_Points = /*vertices*/ borderPoints
                                   .Where(v =>
                                          allSceneBorderPoints_NotThisFraction
                                          .All(b => Vector3.Distance(b.pointA, v.pointA) > 0.25f)
                                          )
                                   .ToList();


        if (notBlocked_BP_Points.Count == 0)
        {
            return;
        }


        var growPoints = new List <BorderPoint>(/*notBlocked_BP_Points*/ notBlocked_BP_Points);

        List <BorderPoint> growedEdges = new List <BorderPoint>(borderPoints);

        #endregion

        borderPoints_subPolygons = new List <List <BorderPoint> >()
        {
            borderPoints
        };
        //List<BorderPoint> connectionBorderPoints = new List<BorderPoint>();

        //GROW
        foreach (BorderPoint nearPoint in growPoints)
        {
            Vector3 np            = nearPoint.pointA;
            float   towardShift   = growDist;
            Vector3 segmentNormal = nearPoint.normal;


            //raycast against others

            var lineCast_growResult = LineCastForGrow(
                nearPoint, towardShift, 0.2f, segmentNormal, allSceneBorderPoints, false
                );
            towardShift = lineCast_growResult.dist;

            #region Connect similar fraction circles

            BorderPoint ibp = lineCast_growResult.intersectionBP;
            if (ibp != null && ibp.circle.fraction == fraction)
            {
                ConnectTwoCircles(growDist, nearPoint, ibp);
                break;
                //connectionBorderPoints.Add(ibp);
            }

            #endregion

            Vector3 newPos = nearPoint.pointA + segmentNormal * towardShift;


            #region raycast against self

            //int indexOfnearPoint = borderPoints.IndexOf(nearPoint);

            var intersectionResult = LineCastForGrow(
                nearPoint, towardShift + 0.2f, 0, segmentNormal, growedEdges, true);
            if (intersectionResult.intersectionBP != null)
            {
                BorderPoint intBP = intersectionResult.intersectionBP;

/*                if (nearPoint.nextPoint != null) nearPoint.nextPoint.prevPoint = null;
 *              if (nearPoint.prevPoint != null) nearPoint.prevPoint.nextPoint = null;*/
                borderPoints.Remove(nearPoint);

/*                if( intBP.nextPoint != null ) intBP.nextPoint.prevPoint = null;
 *              if( intBP.prevPoint != null ) intBP.prevPoint.nextPoint = null;*/
                borderPoints.Remove(intBP);

/*                Debug.DrawLine(nearPoint.pointA + Vector3.up, nearPoint.pointB +Vector3.up, Color.red, 0.1f);
 *              Debug.DrawLine( intersectionResult.intersectionBP.pointA + Vector3.up,
 *                  intersectionResult.intersectionBP.pointB + Vector3.up, Color.red, 0.1f );*/

                continue;
                //newPos = nearPoint.pointA + segmentNormal * intersectionResult.dist*1.05f;
            }

            #region Is inside polygon

            /*            var newPosLocal = transform.InverseTransformPoint(newPos);
             *          if ( polygon != null
             *               && polygon.ContainsPoint( new Vector2( newPosLocal.x, newPosLocal.z ) ) )
             *          {
             *              borderPoints.Remove( nearPoint );
             *
             * /*                Debug.DrawLine(nearPoint.pointA + Vector3.up*0.1f, newPos + Vector3.up * 0.1f,
             *                  Color.magenta, InfluenceCirclesManager._instance.loopWaitTime );
             *              Debug.DrawRay( nearPoint.pointA, Vector3.up * 10,
             *                  Color.magenta, InfluenceCirclesManager._instance.loopWaitTime );#1#
             *
             *              //Debug.LogError(this);
             *              continue;
             *          }*/

            #endregion


            #region AddGrowedEdges

            Vector3 segmentVector       = (nearPoint.pointA - newPos).normalized;
            Vector3 newGrowedEdgeNormal = Quaternion.Euler(0, -90, 0) * segmentVector;
            growedEdges.Add(new BorderPoint()
            {
                pointA = nearPoint.pointA,
                pointB = newPos,
                normal = newGrowedEdgeNormal
            });
            segmentVector       = (newPos - nearPoint.pointA).normalized;
            newGrowedEdgeNormal = Quaternion.Euler(0, -90, 0) * segmentVector;
            growedEdges.Add(new BorderPoint()
            {
                pointA = newPos,
                pointB = nearPoint.pointA,
                normal = newGrowedEdgeNormal
            });

            #endregion

            #endregion


/*            Debug.DrawRay( nearPoint.pointA + Vector3.up * 0.25f, segmentNormal * towardShift,
 *              Color.green, InfluenceCirclesManager._instance.loopWaitTime );*/

            nearPoint.pointA = newPos;
        }


        //GenerateTriangulation();
        UpdateModel();
    }
/*    public void GrowAllGrowPoints(float growDist)
 *  {
 *      for (var i = 0; i < growPoints.Count; i++)
 *      {
 *          Vector3 growPoint = growPoints[i];
 *          Grow(growDist, growPoint);
 *      }
 *  }*/


    public void Grow(float growDist, Vector3 centerOfMass)
    {
        #region Remove parallel border points

/*        for( var i = 0; i < borderPoints.Count; i++ )
 *      {
 *          var bp = borderPoints[i];
 *          BorderPoint firstOrDefault = borderPoints.FirstOrDefault(v =>v!= bp && BorderPointsNormalIntersected(bp, v, 20));
 *          if( firstOrDefault != null )
 *          {
 *              borderPoints.Remove( firstOrDefault );
 *              borderPoints.Remove( bp );
 *
 *              i = -1;
 *          }
 *      }*/

        #endregion

        borderPoints_subPolygons = new List <List <BorderPoint> >()
        {
            borderPoints
        };

        List <BorderPoint> vertices = new List <BorderPoint>(borderPoints);
        if (vertices.Count < 1)
        {
            return;
        }


        #region Calc grow points

        var allSceneBorderPoints = allInfluenceCircles
                                   .Where(v => v != this)
                                   .SelectMany(v => v.borderPoints).ToList();
        var allSceneBorderPoints_NotThisFraction = allSceneBorderPoints
                                                   .Where(c => c.circle.fraction != fraction).ToList();


        var notBlocked_BP_Points = vertices
                                   .Where(v =>
                                          allSceneBorderPoints_NotThisFraction
                                          .All(b => Vector3.Distance(b.pointA, v.pointA) > 0.5f /*PointNotBlocked(b, v)*/)
                                          )
                                   .ToList();

/*        foreach (BorderPoint bp in notBlocked_BP_Points )
 *      {
 *          Debug.DrawRay(bp.pointA , Vector3.up,
 *              Color.red, InfluenceCirclesManager._instance.loopWaitTime );
 *      }*/

        if (notBlocked_BP_Points.Count == 0)
        {
            return;
        }


        //Vector3 centerOfMass = CenterOfMass_BorderPoints( borderPoints);


        BorderPoint closestPoint = notBlocked_BP_Points
                                   .OrderBy(v => Vector3.Distance(v.pointA, centerOfMass)).ToList()[0];
        Vector3 closestPoint_Start = closestPoint.pointA;

        var growPoints = borderPoints.Where(v => Vector3.Distance(v.pointA, closestPoint_Start) < growDist).ToList();

        #endregion

        //subdivide
        if (CheckIfNeedSubdivide(growPoints))
        {
            growPoints = borderPoints.Where(v => Vector3.Distance(v.pointA, closestPoint_Start) < growDist).ToList();
        }


        List <BorderPoint> growedEdges = new List <BorderPoint>(borderPoints);


        //GROW
        foreach (BorderPoint nearPoint in growPoints)
        {
            Vector3 np = nearPoint.pointA;
            float   distToStartPoint = Vector3.Distance(np, closestPoint_Start);
            float   towardShift      = InfluenceCirclesManager.SampleGrowCurve((growDist - distToStartPoint) / growDist) * growDist;


            #region Normal

            Vector3 segmentNormal = nearPoint.normal;

/*            if (Vector3.Angle(segmentNormal, averageNormal) > 100)
 *          {
 *              segmentNormal *= -1;
 *          }
 *          averageNormal = Vector3.Lerp(averageNormal, segmentNormal, 0.3f);*/

            #endregion

            //raycast against others
            /*towardShift*/ var lineCast_growResult = LineCastForGrow(
                nearPoint, towardShift, 0.2f, segmentNormal, allSceneBorderPoints, false
                );
            towardShift = lineCast_growResult.dist;

            #region Connect similar fraction circles

            BorderPoint ibp = lineCast_growResult.intersectionBP;
            if (ibp != null && ibp.circle.fraction == fraction)
            {
                ConnectTwoCircles(growDist, nearPoint, ibp);
                break;
            }

            #endregion

            Vector3 newPos = nearPoint.pointA + segmentNormal * towardShift;


            #region raycast against self

            //int indexOfnearPoint = borderPoints.IndexOf(nearPoint);

            var intersectionBP = LineCastForGrow(
                nearPoint, towardShift + 0.2f, 0, segmentNormal, growedEdges, true).intersectionBP;
            if (intersectionBP != null)
            {
                borderPoints.Remove(nearPoint);

/*                Debug.DrawRay( nearPoint.pointA, Vector3.up*10,
 *                  Color.magenta, InfluenceCirclesManager._instance.loopWaitTime );*/

                continue;
            }

/*            var newPosLocal = transform.InverseTransformPoint(newPos);
 *          if ( polygon != null
 *               && polygon.ContainsPoint( new Vector2( newPosLocal.x, newPosLocal.z ) ) )
 *          {
 *              borderPoints.Remove( nearPoint );
 *
 * /*                Debug.DrawLine(nearPoint.pointA + Vector3.up*0.1f, newPos + Vector3.up * 0.1f,
 *                  Color.magenta, InfluenceCirclesManager._instance.loopWaitTime );
 *              Debug.DrawRay( nearPoint.pointA, Vector3.up * 10,
 *                  Color.magenta, InfluenceCirclesManager._instance.loopWaitTime );#1#
 *
 *              //Debug.LogError(this);
 *              continue;
 *          }*/

            #region AddGrowedEdges

            Vector3 segmentVector       = (nearPoint.pointA - newPos).normalized;
            Vector3 newGrowedEdgeNormal = Quaternion.Euler(0, -90, 0) * segmentVector;
            growedEdges.Add(new BorderPoint()
            {
                pointA = nearPoint.pointA,
                pointB = newPos,
                normal = newGrowedEdgeNormal
            });
            segmentVector       = (newPos - nearPoint.pointA).normalized;
            newGrowedEdgeNormal = Quaternion.Euler(0, -90, 0) * segmentVector;
            growedEdges.Add(new BorderPoint()
            {
                pointA = newPos,
                pointB = nearPoint.pointA,
                normal = newGrowedEdgeNormal
            });

            #endregion

            #endregion


            Debug.DrawRay(nearPoint.pointA + Vector3.up * 0.25f, segmentNormal * towardShift,
                          Color.green, InfluenceCirclesManager._instance.loopWaitTime);

            nearPoint.pointA = newPos;
        }


        //GenerateTriangulation();
        UpdateModel();
    }