Пример #1
0
        public static void SplitByLength(ApproximatedLine line, out ApproximatedLine splitA, out ApproximatedLine splitB)
        {
            var bestFit = line.BestFitLine;
            var s       = bestFit.Start;
            var e       = bestFit.End;

            splitA = new ApproximatedLine(line.Settings);
            splitB = new ApproximatedLine(line.Settings);

            foreach (var ln in line.lines)
            {
                NearestPointOnLine(s, e, ln.Start, out var startDen);
                NearestPointOnLine(s, e, ln.End, out var endDen);

                if (startDen <= 0.5f && endDen <= 0.5f)
                {
                    splitA.lines.Add(ln);
                }
                else if (startDen > 0.5f && endDen > 0.5f)
                {
                    splitB.lines.Add(ln);
                }
                else
                {
                    var aDen = Mathf.Min(startDen, endDen);
                    var bDen = Mathf.Max(startDen, endDen);
                    var aPt  = startDen < endDen ? ln.Start : ln.End;
                    var bPt  = startDen < endDen ? ln.End : ln.Start;
                    var p    = (0.5f - aDen) / (bDen - aDen);
                    var mPt  = Vector3.Lerp(aPt, bPt, p);

                    splitA.lines.Add(new Line(aPt, mPt));
                    splitB.lines.Add(new Line(mPt, bPt));
                }
            }

            if (splitA.lines.Count == 0 || splitB.lines.Count == 0)
            {
                foreach (var ln in line.lines)
                {
                    NearestPointOnLine(s, e, ln.Start, out _);
                    NearestPointOnLine(s, e, ln.End, out _);
                }
            }

            splitA.color = line.color;
            splitB.color = line.color;

            splitA.Recalculate();
            splitB.Recalculate();
        }
Пример #2
0
        public bool TryMergeIgnoreAngle(ApproximatedLine approxLine)
        {
            foreach (var line in lines)
            {
                foreach (var sLine in approxLine.lines)
                {
                    if (LineUtils.LineLineDistance(line, sLine) < Settings.lineDistanceThreshold)
                    {
                        lines.AddRange(approxLine.lines);
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #3
0
        public static void RemovePastThresholdLines(ApproximatedLine line)
        {
            var settings = line.Settings;
            var thr      = settings.worstFitThreshold;

            var jointLines = new List <ApproximatedLine>();

            foreach (var ln in line.lines)
            {
                var found = false;
                foreach (var jointLine in jointLines)
                {
                    if (jointLine.TryAddLine(ln, settings.jointLineThreshold))
                    {
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    jointLines.Add(new ApproximatedLine(ln, settings));
                }
            }

            var changed = true;
            var safety  = 0;

            while (changed)
            {
                if (safety++ > 5000)
                {
                    Debug.LogError("Broken infinite loop");
                    return;
                }

                changed = false;
                for (var i = 0; i < jointLines.Count - 1; ++i)
                {
                    for (var j = i + 1; j < jointLines.Count; ++j)
                    {
                        if (jointLines[i].TryMerge(jointLines[j], settings.jointLineThreshold))
                        {
                            jointLines.Remove(jointLines[j]);
                            changed = true;
                            break;
                        }
                    }

                    if (changed)
                    {
                        break;
                    }
                }
            }

            foreach (var jointLine in jointLines)
            {
                jointLine.Recalculate();
            }

            var bestLength = float.MinValue;
            var bestLine   = jointLines[0];

            foreach (var jointLine in jointLines)
            {
                var length = jointLine.BestFitLine.Length;
                if (length > bestLength)
                {
                    bestLength = length;
                    bestLine   = jointLine;
                }
            }

            for (var i = 0; i < line.lines.Count; ++i)
            {
                if (LineLineDistance(line.lines[i].Start, line.lines[i].End, bestLine.BestFitLine.Start, bestLine.BestFitLine.Start) > thr)
                {
                    line.lines.RemoveAt(i--);
                }
            }

            line.Recalculate();
        }
Пример #4
0
        public bool TrySplit(out ApproximatedLine a, out ApproximatedLine b)
        {
            a = b = null;
            if (lines.Count < 2)
            {
                return(false);
            }

            var combinations = Enumerable
                               .Range(0, 1 << lines.Count)
                               .Select(index => lines
                                       .Where((line, i) => (index & (1 << i)) != 0)
                                       .ToList());

            var setA = new ApproximatedLine(Settings);
            var setB = new ApproximatedLine(Settings);
            var resA = new ApproximatedLine(Settings)
            {
                color = color
            };
            var resB = new ApproximatedLine(Settings)
            {
                color = color
            };
            var bestVal = float.MaxValue;

            foreach (var combination in combinations)
            {
                if (combination.Count == 0 || combination.Count == lines.Count)
                {
                    continue;
                }

                setA.lines.Clear();
                setB.lines.Clear();

                foreach (var line in lines)
                {
                    if (combination.Contains(line))
                    {
                        setA.lines.Add(line);
                    }
                    else
                    {
                        setB.lines.Add(line);
                    }
                }

                setA.Recalculate();
                setB.Recalculate();

                var val = Mathf.Max(setA.OptimizationValue, setB.OptimizationValue);

                if (val < bestVal)
                {
                    bestVal = val;
                    resA.lines.Clear();
                    resA.lines.AddRange(setA.lines);
                    resB.lines.Clear();
                    resB.lines.AddRange(setB.lines);
                }
            }

            if (bestVal > OptimizationValue)
            {
                return(false);
            }

            resA.Recalculate();
            resB.Recalculate();

            a = resA;
            b = resB;

            return(true);
        }
Пример #5
0
 public bool TryMerge(ApproximatedLine approxLine)
 {
     return(TryMerge(approxLine, Settings.lineDistanceThreshold));
 }