Beispiel #1
0
        public void Search(IPlayer player, List <AssetLocation> missing, List <AssetLocation> notmissing, string type = "Block", bool DL = false)
        {
            for (int i = 0; i < missing.Count; i++)
            {
                List <int> distance = new List <int>();
                for (int j = 0; j < notmissing.Count; j++)
                {
                    if (missing[i] == null || notmissing[j] == null)
                    {
                        distance.Add(999999999);
                        continue;
                    }
                    if (DL)
                    {
                        distance.Add(missing[i].ToString().Replace(missing[i].Domain + ":", "").ComputeDLDistance(notmissing[j].ToString().Replace(notmissing[j].Domain + ":", "")));
                    }
                    else
                    {
                        distance.Add(missing[i].ToString().Replace(missing[i].Domain + ":", "").ComputeDistance(notmissing[j].ToString().Replace(notmissing[j].Domain + ":", "")));
                    }
                }
                int index = distance.IndexOfMin();

                if (!MostLikely.ContainsValue(notmissing[index]))
                {
                    MostLikely.Add(missing[i], notmissing[index]);
                    notmissing.RemoveAt(index);
                }

                sapi.SendMessage(player, GlobalConstants.InfoLogChatGroup, "Finding Closest " + type + " Matches... " + Math.Round(i / (float)missing.Count * 100, 2) + "%", EnumChatType.Notification);
            }
            sapi.SendMessage(player, GlobalConstants.InfoLogChatGroup, "Finding Closest " + type + " Matches... 100%", EnumChatType.Notification);
        }
Beispiel #2
0
        private DiverSpan GetDivergence()
        {
            var allDivers = new List <DiverSpan>();

            foreach (var ind in IndexList)
            {
                var indexDiv = ind;
                var divers   = ind.DiverType == IndexDivergencyInfo.DivergenceType.Классические
                                 ? Divergency.FindDivergencePointsClassic(candles.Count,
                                                                          ind.PeriodExtremum, ind.MaxPastExtremum,
                                                                          index => candles[index].close,
                                                                          index => indexDiv.lastIndicies[index], ind.WaitOneBar)
                                 : Divergency.FindDivergencePointsQuasi(candles.Count,
                                                                        (double)ind.IndexMarginUp, (double)ind.IndexMarginDn,
                                                                        index => candles[index].close,
                                                                        index => indexDiv.lastIndicies[index]);
                allDivers.AddRange(divers);
            }
            // нас интересует знак последнего дивера
            var diverSpan = allDivers.Count == 0
                                ? null
                                : allDivers[allDivers.IndexOfMin(d => - d.end)];

            if (diverSpan != null && candles.Count - diverSpan.end > ForgetDiverCandles)
            {
                diverSpan = null; // дивер устарел
            }
            return(diverSpan);
        }
            public void Enumerable_IndexOfMin_WithEmptySequence_ReturnsNegativeOne()
            {
                IEnumerable <int> source = new List <int> {
                };
                int result = source.IndexOfMin();

                Assert.AreEqual(-1, result, "Minimum element of an empty sequence should not be found.");
            }
            public void Enumerable_IndexOfMin_WithBackwardsOrderingFunction_ReturnsMaxValue()
            {
                IEnumerable <int> source = new List <int> {
                    3, 2, 1
                };
                int result = source.IndexOfMin((x, y) => Comparer <int> .Default.Compare(y, x));

                Assert.AreEqual(0, result, "Minimum element of a sequence should be found.");
            }
            public void Enumerable_IndexOfMin_WithBackwardsOrderedSequence_ReturnsLastValue()
            {
                IEnumerable <int> source = new List <int> {
                    3, 2, 1
                };
                int result = source.IndexOfMin();

                Assert.AreEqual(2, result, "Minimum element of a sequence should be found.");
            }
        public void IndexOfMin()
        {
            var numbers = new List <Point>
            {
                new Point(0, 1),        // 0
                new Point(0, -1),       // 1
                new Point(0, 2),        // 2
                new Point(0, 3),        // 3
                new Point(0, -2),       // 4
                new Point(0, 4),        // 5
            };

            Assert.IsTrue(numbers.IndexOfMin(p => p.Y) == 4);
            numbers.Add(new Point(0, -2));
            var minIndex = numbers.IndexOfMin(p => p.Y);

            Assert.IsTrue(minIndex == 4 || minIndex == 6);
            numbers.Clear();
            numbers.IndexOfMin(p => p.Y);
        }
Beispiel #7
0
        /// <summary>
        /// Проверка, пересекаются ли Id полученных транзакций с тем Id, что лежит в файле
        /// true - дырок нет
        /// </summary>
        private bool CheckIntersectionTransfer(List <Transfer> transfers, uint?lastReqId)
        {
            if (!lastReqId.HasValue)
            {
                return(true);
            }
            if (transfers.Count == 0)
            {
                return(true);
            }
            var transId = transfers[transfers.IndexOfMin(t => t.CreateTime.GetServerTime())].Id;

            return(transId <= lastReqId.Value);
        }
Beispiel #8
0
        static void EliminateTinySections(List <Section> list, int minLineLengthPx)
        {
            // Eliminate tiny sections
            Section cur;
            int     i;

            while ((cur = list[i = list.IndexOfMin(s => s.LengthPx)]).LengthPx < minLineLengthPx)
            {
                var prev = list.TryGet(i - 1, null);
                var next = list.TryGet(i + 1, null);
                if (PickMerge(ref prev, cur, ref next))
                {
                    if (prev != null)
                    {
                        list[i - 1] = prev;
                    }
                    if (next != null)
                    {
                        list[i + 1] = next;
                    }
                    list.RemoveAt(i);
                }
                else
                {
                    break;
                }
            }

            // Merge adjacent sections that now have the same mod-8 angle
            for (i = 1; i < list.Count; i++)
            {
                Section s0 = list[i - 1], s1 = list[i];
                if (s0.AngleMod8 == s1.AngleMod8)
                {
                    s0.EndSS     = s1.EndSS;
                    s0.iEnd      = s1.iEnd;
                    s0.LengthPx += s1.LengthPx;
                    list.RemoveAt(i);
                    i--;
                }
            }
        }
        private static IEnumerable <List <T> > ToBuckets <T>(this IEnumerable <T> list, int bucketCount, Func <T, long> getWeight)
        {
            List <T> sortedList = list.OrderByDescending(v => getWeight(v)).ToList();

            List <long>      runningTotals = Enumerable.Repeat(0L, bucketCount).ToList();
            List <List <T> > buckets       = Enumerable.Range(0, bucketCount)
                                             .Select(v => new List <T>(sortedList.Count / bucketCount))
                                             .ToList();

            foreach (T item in sortedList)
            {
                // MinBy runningTotal
                int i = runningTotals.IndexOfMin();
                // Add to bucket
                runningTotals[i] += getWeight(item);
                buckets[i].Add(item);
            }

            return(buckets);
        }
 private DiverSpan GetDivergence()
 {
     var allDivers = new List<DiverSpan>();
     foreach (var ind in IndexList)
     {
         var indexDiv = ind;
         var divers = ind.DiverType == IndexDivergencyInfo.DivergenceType.Классические
                          ? Divergency.FindDivergencePointsClassic(candles.Count,
                                                                   ind.PeriodExtremum, ind.MaxPastExtremum,
                                                                   index => candles[index].close,
                                                                   index => indexDiv.lastIndicies[index], ind.WaitOneBar)
                          : Divergency.FindDivergencePointsQuasi(candles.Count,
                                                                 (double) ind.IndexMarginUp, (double) ind.IndexMarginDn,
                                                                 index => candles[index].close,
                                                                 index => indexDiv.lastIndicies[index]);
         allDivers.AddRange(divers);
     }
     // нас интересует знак последнего дивера
     var diverSpan = allDivers.Count == 0
                         ? null
                         : allDivers[allDivers.IndexOfMin(d => -d.end)];
     if (diverSpan != null && candles.Count - diverSpan.end > ForgetDiverCandles)
         diverSpan = null; // дивер устарел
     return diverSpan;
 }
 /// <summary>
 /// Проверка, пересекаются ли Id полученных транзакций с тем Id, что лежит в файле
 /// true - дырок нет
 /// </summary>
 private bool CheckIntersectionTransfer(List<Transfer> transfers, uint? lastReqId)
 {
     if (!lastReqId.HasValue) return true;
     if (transfers.Count == 0)
         return true;
     var transId = transfers[transfers.IndexOfMin(t => t.CreateTime.GetServerTime())].Id;
     return transId <= lastReqId.Value;
 }
Beispiel #12
0
        /// <summary>
        /// сделать ход, не заморачиваясь подсчетом
        /// вариантов, если ход "очевиден"
        /// </summary>
        public static Point?MakeTurnNoChoice(Board board)
        {
            var spieler = board.CurrentSpieler;

            if (spieler.GiveCabbage || spieler.Freezed)
            {
                return(null);
            }
            var tokens = board.GetSpielerTokens(board.currentSpielerIndex);

            if (tokens.Any(t => board.cells[t.Position].CellType == CellType.Cabbage))
            {
                return(null);
            }

            // token - targetCell - rate
            var turnVariants = new List <Cortege3 <int, int, int> >();

            // посчитать бонусную капусту
            var carrotsBonus   = GetSpielerCarrotsBonus(spieler, tokens, board);
            var spielerCarrots = carrotsBonus + spieler.CarrotsSpare;

            // есть ли свободная капуста для прыжка вперед?
            const int minCarrotsReserved = 10;

            if (spieler.CabbageSpare > 0)
            {
                for (var i = 0; i < tokens.Length; i++)
                {
                    var token = tokens[i];

                    // есть ли свободная капуста впереди?
                    for (var j = token.Position + 1; j < board.cells.Length - 1; j++)
                    {
                        if (board.cells[j].CellType != CellType.Cabbage)
                        {
                            continue;
                        }
                        // занята?
                        if (board.tokens.Any(t => t.Position == j))
                        {
                            break;
                        }
                        var carrotsRequired = Board.GetCarrotsPerCells(j - token.Position);
                        if (carrotsRequired > spielerCarrots - minCarrotsReserved)
                        {
                            break;
                        }
                        // есть свободная капуста!
                        var turnRate = (spielerCarrots - carrotsRequired) +
                                       board.tokens.Count(t => t.Position > i) * 10;
                        turnVariants.Add(new Cortege3 <int, int, int>(i, j, turnRate));
                    }
                }
            }

            // отсеять недопустимые ходы
            if (turnVariants.Count == 0)
            {
                return(null);
            }
            string error;
            int    deltaCarrots;

            turnVariants = turnVariants.Where(v => board.CheckTurn(board.currentSpielerIndex, v.a, v.b, false,
                                                                   out error, out deltaCarrots)).ToList();
            if (turnVariants.Count == 0)
            {
                return(null);
            }

            // выбор лучшего из вариантов
            var bestIndex   = turnVariants.IndexOfMin(v => - v.c);
            var bestVariant = turnVariants[bestIndex];

            // скорректировать индекс токена
            var tokenIndex = board.tokens.FindIndex(t => t == tokens[bestVariant.a]);

            return(new Point(tokenIndex, bestVariant.b));
        }
		static void EliminateTinySections(List<Section> list, int minLineLengthPx)
		{
			// Eliminate tiny sections
			Section cur;
			int i;
			while ((cur = list[i = list.IndexOfMin(s => s.LengthPx)]).LengthPx < minLineLengthPx)
			{
				var prev = list.TryGet(i - 1, null);
				var next = list.TryGet(i + 1, null);
				if (PickMerge(ref prev, cur, ref next))
				{
					if (prev != null)
						list[i - 1] = prev;
					if (next != null)
						list[i + 1] = next;
					list.RemoveAt(i);
				}
				else
					break;
			}

			// Merge adjacent sections that now have the same mod-8 angle
			for (i = 1; i < list.Count; i++)
			{
				Section s0 = list[i - 1], s1 = list[i];
				if (s0.AngleMod8 == s1.AngleMod8)
				{
					s0.EndSS = s1.EndSS;
					s0.iEnd = s1.iEnd;
					s0.LengthPx += s1.LengthPx;
					list.RemoveAt(i);
					i--;
				}
			}
		}
Beispiel #14
0
        /// <summary>
        /// Split this region into two (or more) sub-regions along a straight line
        /// </summary>
        /// <param name="splitPt">A point on the splitting line</param>
        /// <param name="splitDir">The direction of the line</param>
        /// <param name="splitWidth">Optional.  The width of the split.</param>
        /// <returns>The resultant list of regions.  If the line does not bisect
        /// this region and the region could not be split, this collection will contain
        /// only the original region.</returns>
        public IList <PlanarRegion> SplitByLineXY(Vector splitPt, Vector splitDir, double splitWidth = 0)
        {
            var result    = new List <PlanarRegion>();
            var lineInts  = new List <double>();
            var outerInts = Intersect.CurveLineXY(Perimeter, splitPt, splitDir, null, 0, 1, false, lineInts);

            if (outerInts.Count > 1)
            {
                // Sort intersections by position along curve:
                var sortedInts = new SortedList <double, double>(outerInts.Count);
                for (int i = 0; i < outerInts.Count; i++)
                {
                    sortedInts.Add(outerInts[i], lineInts[i]);
                }

                outerInts = sortedInts.Keys.ToList();
                lineInts  = sortedInts.Values.ToList();
                int offset = lineInts.IndexOfMin();
                outerInts.Shift(offset);
                lineInts.Shift(offset);

                // Create segments data structure
                var segments = new List <PerimeterSegment>(outerInts.Count - 1);
                for (int i = 0; i < outerInts.Count; i++)
                {
                    double t0      = outerInts[i];
                    double t1      = outerInts.GetWrapped(i + 1);
                    double tC0     = lineInts[i];
                    double tC1     = lineInts.GetWrapped(i + 1);
                    var    segment = new PerimeterSegment(Perimeter, t0, t1, tC0, tC1);
                    segments.Add(segment);
                }

                //TODO: void intersections

                bool backwards = true;
                while (segments.Count > 0)
                {
                    var offsets = new List <double>();
                    PerimeterSegment segment = segments.First();

                    PolyCurve newPerimeter = segment.Extract().ToPolyCurve();
                    for (int i = 0; i < newPerimeter.SegmentCount; i++)
                    {
                        offsets.Add(0);
                    }
                    PerimeterSegment nextSegment = FindNextPerimeterSegment(segments, segment.CutterDomain.End, backwards);
                    while (nextSegment != null && nextSegment != segment)
                    {
                        Curve nextCurve = nextSegment.Extract();
                        newPerimeter.AddLine(nextCurve.StartPoint);
                        offsets.Add(splitWidth / 2);
                        newPerimeter.Add(nextCurve);
                        for (int i = 0; i < nextCurve.SegmentCount; i++)
                        {
                            offsets.Add(0);
                        }
                        segments.Remove(nextSegment);
                        nextSegment = FindNextPerimeterSegment(segments, nextSegment.CutterDomain.End, backwards);
                    }
                    segments.RemoveAt(0);
                    if (!newPerimeter.Closed)
                    {
                        /*if (splitWidth > 0)
                         * {
                         *  // Temporary bodge to get rid of 'blades' at ends of split
                         *  Vector endToEnd = (newPerimeter.StartPoint - newPerimeter.EndPoint).Unitize();
                         *  var line = new Line(
                         *      newPerimeter.EndPoint - endToEnd * splitWidth / 4,
                         *      newPerimeter.StartPoint + endToEnd * splitWidth / 4);
                         *  newPerimeter.AddLine(line.StartPoint);
                         *  offsets.Add(0);
                         *  newPerimeter.Add(line);
                         *  offsets.Add(splitWidth / 2);
                         *  newPerimeter.Close();
                         *  offsets.Add(0);
                         * }
                         * else
                         * {*/
                        newPerimeter.Close();
                        offsets.Add(splitWidth / 2);
                        //}
                    }
                    backwards = !backwards;

                    if (splitWidth > 0)
                    {
                        var newNewPerimeter = newPerimeter.OffsetInwards(offsets);
                        // Check offset has not inverted perimeter:
                        // TODO: Do this automatically when offsetting?
                        if (newNewPerimeter != null && newNewPerimeter.IsClockwiseXY() == newPerimeter.IsClockwiseXY())
                        {
                            newPerimeter = newNewPerimeter.ToPolyCurve();
                        }
                        else
                        {
                            newPerimeter = null;
                        }
                    }

                    if (newPerimeter != null)
                    {
                        result.Add(new PlanarRegion(newPerimeter, Attributes?.Duplicate()));
                    }
                }

                // OLD VERSION:

                /*for (int i = 0; i < outerInts.Count; i++)
                 * {
                 *  double t0 = outerInts[i];
                 *  double t1 = outerInts.GetWrapped(i + 1);
                 *  Curve newPerimeter = Perimeter.Extract(new Interval(t0, t1))?.ToPolyCurve();
                 *  //TODO: Cut through and include voids
                 *  if (!newPerimeter.Closed)
                 *  {
                 *      ((PolyCurve)newPerimeter).Close();
                 *      if (splitWidth > 0)
                 *      {
                 *          var offsets = new double[newPerimeter.SegmentCount];
                 *          offsets[offsets.Length - 1] = splitWidth / 2;
                 *          var newNewPerimeter = newPerimeter.OffsetInwards(offsets);
                 *          // Check offset has not inverted perimeter:
                 *          // TODO: Do this automatically when offsetting?
                 *          if (newNewPerimeter != null && newNewPerimeter.IsClockwiseXY() == newPerimeter.IsClockwiseXY())
                 *          {
                 *              newPerimeter = newNewPerimeter;
                 *          }
                 *          else newPerimeter = null;
                 *      }
                 *  }
                 *  if (newPerimeter != null) result.Add(new PlanarRegion(newPerimeter, Attributes?.Duplicate()));
                 * }*/
            }
            else
            {
                result.Add(this); //Return the original
            }
            return(result);
        }
Beispiel #15
0
        public static double CalcY(List<List<Point>> source, List<List<Point>> destination)
        {
            var diffs = new List<double>();
            Func<List<Point>, List<Point>, double> f = (p1, p2) =>
                (Functions.AverageColor(p1.Select(s => s.GetColor()).ToList()) - Functions.AverageColor(p2.Select(s => s.GetColor()).ToList())).SqrLength()
                 + (Functions.AverageVector(p1.Select(s => s.GetVector3()).ToList()) - Functions.AverageVector(p2.Select(s => s.GetVector3()).ToList())).sqrMagnitude;
            for (int i = 0; i < source.Count; i++) {
                var spoints = source[i];
                var index = destination.IndexOfMin(b => f(b, spoints));
                var dpoints = destination[index];
                var diff = Functions.AverageVector(dpoints.Select(s => s.GetVector3()).ToList()) - Functions.AverageVector(spoints.Select(s => s.GetVector3()).ToList());
                diffs.Add(diff.y);
            }

            return diffs.Median();
        }
Beispiel #16
0
        public static List <int> GetLocalConvex(List <PointOnGrid> points, double scale)
        {
            #region Navot Israeli code

            /*
             * %computes the envelope of a set of points in the x,y plane
             * %uses a variation of convex hull ahere at each step the next leg is taken
             * %as the "local" continuation of the convex hull. Namely, the continuation
             * %of convhull with the points in the local neighborhood of the current node
             * %
             * % input:
             * % x,y are points coordinates
             * % scale is the radius of the local neighborhood
             * % output:
             * % env_ii is an array of indices into x,y. Namely, x(env_ii), y(env_ii) is the
             * % envelope polygon
             *
             * function env_ii=local_convhull_envelope(x,y,scale)
             *
             *
             * [~, start_p]=min(x);
             *
             * p=start_p;
             * in_dir=[0; 1];
             *
             * env_x=x(p);
             * env_y=y(p);
             * env_ii=p;
             *
             *
             * while (1)
             *  d=sqrt(((x-x(p))/scale).^2+((y-y(p))/scale).^2);
             *  ii=find(d<=1);
             *
             *
             *  min_alpha=1000;
             *  best_q=-1;
             *  best_out_dir=[];
             *  in_dir_n=[in_dir(2); -in_dir(1)];
             *
             *  for qii=1:length(ii)
             *      q=ii(qii);
             *      if q~=p
             *          out_dir=[x(q)-x(p); y(q)-y(p)];
             *          out_dir=out_dir/norm(out_dir);
             *
             *          alpha=atan2(dot(out_dir,in_dir_n),dot(out_dir,in_dir));
             *          if (alpha<min_alpha)
             *              intersects=0;
             *              for k=1:length(env_x)-2
             *                  A=[(env_x(k+1)-env_x(k)) (x(p)-x(q)); (env_y(k+1)-env_y(k)) (y(p)-y(q))];
             *                  if (det(A)>1e-16)
             *                      V=[x(p)-env_x(k); y(p)-env_y(k)];
             *                      s=A\V;
             *
             *                      if ((s(1)>0) && (s(1)<1) && (s(2)>0) && (s(2)<1))
             *                          intersects=1;
             *                          break;
             *                      end
             *                  end
             *              end
             *              if intersects==0
             *                  min_alpha=alpha;
             *                  best_q=q;
             *                  best_out_dir=out_dir;
             *              end
             *          end
             *      end
             *  end
             *
             *  env_x(end+1)=x(best_q);
             *  env_y(end+1)=y(best_q);
             *  env_ii(end+1)=best_q;
             *  p=best_q;
             *  in_dir=best_out_dir;
             *
             *
             *
             *  if p==start_p;
             *      break;
             *  end
             * end
             *
             *
             *
             *
             *
             */
            #endregion Navot Israeli code

            int      startP = points.IndexOfMin();                   //[~, start_p]=min(x);
            int      pInd   = startP;                                //p=start_p;
            double[] inDir  = new double[] { 0, 1 };                 //in_dir=[0; 1];

            List <double> env_x = new List <double>()
            {
                points[pInd].X
            };                                                                                  //env_x=x(p);
            List <double> env_y = new List <double>()
            {
                points[pInd].Y
            };                                                                                  //env_y=y(p);
            List <int> env_ii = new List <int>()
            {
                pInd
            };               //env_ii=p;

            int    iter = 0; //debug
            int    best_q;
            double min_alpha;
            double alpha;

            List <int>    closeIndexes = new List <int>();
            List <double> dist;

            double[] best_out_dir = new double[2];
            double[] in_dir_n     = new double[2] {
                inDir[1], -inDir[0]
            };
            double[] outDir = new double[2];
            double[] V      = new double[2];
            double[] s      = new double[2];
            double[,] A = new double[2, 2];
            while (true)
            {
                iter++;
                if (iter > 1000 && iter > points.Count * 0.3)
                {
                    //env_ii.Clear();
                    break;
                }
                dist = points.Select(p => Math.Sqrt(Math.Pow((p.X - points[pInd].X) / scale, 2) +
                                                    Math.Pow((p.Y - points[pInd].Y) / scale, 2))).ToList();                      //d=sqrt(((x-x(p))/scale).^2+((y-y(p))/scale).^2);


                dist.FindIndexes(f => f <= 1, ref closeIndexes);//ii = find(d <= 1);


                min_alpha = 1000;                                   //min_alpha=1000;
                best_q    = -1;                                     //best_q=-1;

                //best_out_dir = new double[2];                           //best_out_dir=[];
                best_out_dir[0] = 0;
                best_out_dir[1] = 0;
                in_dir_n[0]     = inDir[1];
                in_dir_n[1]     = -inDir[0];    //in_dir_n=[in_dir(2); -in_dir(1)];
                outDir[0]       = 0;
                outDir[1]       = 0;
                for (int qi = 0; qi < closeIndexes.Count; qi++)
                {
                    int q = closeIndexes[qi]; //q=ii(qii);
                    if (q != pInd)
                    {
                        //out_dir=[x(q)-x(p); y(q)-y(p)];
                        outDir[0] = points[q].X - points[pInd].X;
                        outDir[1] = points[q].Y - points[pInd].Y;

                        outDir.DivideByNorm();                                         //out_dir=out_dir/norm(out_dir);
                        alpha = Math.Atan2(dot(outDir, in_dir_n), dot(outDir, inDir)); //alpha=atan2(dot(out_dir,in_dir_n),dot(out_dir,in_dir));

                        if (alpha < min_alpha)                                         //if (alpha<min_alpha)
                        {
                            int intersects = 0;                                        //    intersects=0;
                            for (int kk = 0; kk <= env_x.Count - 3; kk++)              //    for k=1:length(env_x)-2
                            {
                                //double[,] A = new double[,] { { env_x[kk + 1] - env_x[kk], points[pInd].X - points[q].X }, { env_y[kk + 1] - env_y[kk], points[pInd].Y - points[q].Y } }; //        A=[(env_x(k+1)-env_x(k)) (x(p)-x(q)); (env_y(k+1)-env_y(k)) (y(p)-y(q))];
                                A[0, 0] = env_x[kk + 1] - env_x[kk]; // A=[(env_x(k+1)-env_x(k)) (x(p)-x(q)); (env_y(k+1)-env_y(k)) (y(p)-y(q))];
                                A[0, 1] = points[pInd].X - points[q].X;
                                A[1, 0] = env_y[kk + 1] - env_y[kk];
                                A[1, 1] = points[pInd].Y - points[q].Y;

                                if (det(A) > 1e-16)                                           //if (det(A)>1e-16)
                                {
                                    V[0] = points[pInd].X - env_x[kk];                        //V =[x(p) - env_x(k); y(p) - env_y(k)];
                                    V[1] = points[pInd].Y - env_y[kk];                        //V =[x(p) - env_x(k); y(p) - env_y(k)];
                                    Pinv(A, V, ref s);                                        //s=A\V;

                                    if ((s[0] > 0) && (s[0] < 1) && (s[1] > 0) && (s[1] < 1)) //if ((s(1)>0) && (s(1)<1) && (s(2)>0) && (s(2)<1))
                                    {
                                        intersects = 1;                                       // intersects=1;
                                        break;                                                // break;
                                    }
                                }
                            }

                            if (intersects == 0)
                            {
                                min_alpha       = alpha;     // min_alpha = alpha;
                                best_q          = q;         // best_q=q;
                                best_out_dir[0] = outDir[0]; //        best_out_dir=out_dir;
                                best_out_dir[1] = outDir[1];
                            }
                        }
                    }
                }
                env_x.Add(points[best_q].X); //env_x(end + 1) = x(best_q);
                env_y.Add(points[best_q].Y); //env_y(end + 1) = y(best_q);
                env_ii.Add(best_q);          //env_ii(end + 1) = best_q;
                pInd     = best_q;           //p = best_q;
                inDir[0] = best_out_dir[0];  //in_dir = best_out_dir;
                inDir[1] = best_out_dir[1];

                if (pInd == startP) //if p == start_p;
                {
                    break;
                }
            }//end
            return(env_ii);
        }