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(); }
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(); }
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); }