| 2804 | } |
| 2805 | |
| 2806 | bool LNLib::NurbsCurve::FitWithConic(const std::vector<XYZ>& throughPoints, int startPointIndex, int endPointIndex, const XYZ& startTangent, const XYZ& endTangent, double maxError, std::vector<XYZW>& middleControlPoints) |
| 2807 | { |
| 2808 | VALIDATE_ARGUMENT(throughPoints.size() > 0, "throughPoints", "ThroughPoints size must be greater than zero."); |
| 2809 | VALIDATE_ARGUMENT_RANGE(startPointIndex, 0, throughPoints.size() - 1); |
| 2810 | VALIDATE_ARGUMENT_RANGE(endPointIndex, startPointIndex + 1, throughPoints.size() - 1); |
| 2811 | VALIDATE_ARGUMENT(!startTangent.IsZero(), "startTangent", "StartTangent must not be zero vector."); |
| 2812 | VALIDATE_ARGUMENT(!endTangent.IsZero(), "endTangent", "EndTangent must not be zero vector."); |
| 2813 | |
| 2814 | XYZ startPoint = throughPoints[startPointIndex]; |
| 2815 | XYZ endPoint = throughPoints[endPointIndex]; |
| 2816 | if (endPointIndex - startPointIndex == 1) |
| 2817 | { |
| 2818 | return BezierCurve::ComputerMiddleControlPointsOnQuadraticCurve(startPoint, startTangent, endPoint, endTangent, middleControlPoints); |
| 2819 | } |
| 2820 | |
| 2821 | double alf1, alf2 = 0.0; |
| 2822 | XYZ R(0, 0, 0); |
| 2823 | CurveCurveIntersectionType type = Intersection::ComputeRays(startPoint, startTangent, endPoint, endTangent, alf1, alf2, R); |
| 2824 | if (type == CurveCurveIntersectionType::Coincident) |
| 2825 | { |
| 2826 | middleControlPoints.emplace_back(XYZW((startPoint + endPoint) / 2, 1)); |
| 2827 | return true; |
| 2828 | } |
| 2829 | else if (type == CurveCurveIntersectionType::Skew || type == CurveCurveIntersectionType::Parallel) |
| 2830 | { |
| 2831 | return false; |
| 2832 | } |
| 2833 | if (MathUtils::IsLessThanOrEqual(alf1, 0.0) || |
| 2834 | MathUtils::IsGreaterThanOrEqual(alf2, 0.0)) |
| 2835 | { |
| 2836 | return false; |
| 2837 | } |
| 2838 | double s = 0.0; |
| 2839 | XYZ V = endPoint - startPoint; |
| 2840 | XYZ dummy; |
| 2841 | for (int i = startPointIndex + 1; i <= endPointIndex - 1; i++) |
| 2842 | { |
| 2843 | XYZ V1 = throughPoints[i] - R; |
| 2844 | type = Intersection::ComputeRays(startPoint, V, R, V1, alf1, alf2, dummy); |
| 2845 | if (type != CurveCurveIntersectionType::Intersecting || |
| 2846 | MathUtils::IsLessThanOrEqual(alf1, 0.0) || |
| 2847 | MathUtils::IsGreaterThanOrEqual(alf1, 1.0) || |
| 2848 | MathUtils::IsLessThanOrEqual(alf2, 0.0)) |
| 2849 | { |
| 2850 | return false; |
| 2851 | } |
| 2852 | double wi = 0.0; |
| 2853 | if (CreateOneConicArc(startPoint, V, R, V1, throughPoints[i], dummy, wi)) |
| 2854 | { |
| 2855 | s = s + wi / (1 + wi); |
| 2856 | } |
| 2857 | } |
| 2858 | |
| 2859 | s = s / (endPointIndex - startPointIndex - 1); |
| 2860 | double w = s / (1.0 - s); |
| 2861 | |
| 2862 | std::vector<XYZW> controlPoints = { XYZW(startPoint,1), XYZW(R,w), XYZW(endPoint,1) }; |
| 2863 | std::vector<double> knotVectors = { 0,0,0,1.0,1.0,1.0 }; |
nothing calls this directly
no test coverage detected