24 #define EPSILON_CCI ( 100*std::numeric_limits<T>::epsilon() )
26 template<
class T=real_t>
29 gsPoint2d(
const T xCoord,
const T yCoord)
35 inline T x()
const {
return pt.x();}
36 inline T y()
const {
return pt.y();}
47 short_t orientationxx(
const gsPoint2d<T> &p,
const gsPoint2d<T> &q,
const gsPoint2d<T> &r)
51 T val = (q.y() - p.y()) * (r.x() - q.x()) - (q.x() - p.x()) * (r.y() - q.y());
54 if (val == 0)
return 0;
56 return (val > 0) ? 1 : 2;
62 bool onSegment(
const gsPoint2d<T> &p,
const gsPoint2d<T> &q,
const gsPoint2d<T> &r)
64 if (q.x() <= math::max(p.x(), r.x()) && q.x() >= math::min(p.x(), r.x()) &&
65 q.y() <= math::max(p.y(), r.y()) && q.y() >= math::min(p.y(), r.y()))
74 bool doIntersect(
const gsPoint2d<T> &p1,
const gsPoint2d<T> &q1,
75 const gsPoint2d<T> &p2,
const gsPoint2d<T> &q2)
78 short_t o1 = orientationxx(p1, q1, p2);
79 short_t o2 = orientationxx(p1, q1, q2);
80 short_t o3 = orientationxx(p2, q2, p1);
81 short_t o4 = orientationxx(p2, q2, q1);
84 if (o1 != o2 && o3 != o4)
89 if (o1 == 0 && onSegment(p1, p2, q1))
return true;
92 if (o2 == 0 && onSegment(p1, q2, q1))
return true;
95 if (o3 == 0 && onSegment(p2, p1, q2))
return true;
98 if (o4 == 0 && onSegment(p2, q1, q2))
return true;
114 template<
class T=real_t>
115 struct gsCurveIntersectionResult
118 explicit gsCurveIntersectionResult(
const T paramOnCurve1,
119 const T paramOnCurve2,
120 const gsVector<T> & pt)
122 m_paramOnCurve1(paramOnCurve1),
123 m_paramOnCurve2(paramOnCurve2),
128 bool operator==(
const gsCurveIntersectionResult& other)
const
130 return m_paramOnCurve1 == other.paramOnCurve1 &&
131 m_paramOnCurve2 == other.paramOnCurve2 &&
132 m_point == other.point;
135 bool operator!=(
const gsCurveIntersectionResult& other)
const
137 return !(*
this == other);
140 T getParamOnCurve1()
const {
return m_paramOnCurve1; }
141 T getParamOnCurve2()
const {
return m_paramOnCurve2; }
142 gsVector<T> getPoint()
const {
return m_point; }
151 template<
class T=real_t>
155 gsInterval(
const T min,
const T max)
161 bool almostEqual(
const T a,
const T b,
const T tolerance = EPSILON_CCI)
const
166 bool operator==(
const gsInterval<T> &other)
const
168 return almostEqual(m_min, other.getMin()) && almostEqual(m_max, other.getMax());
171 T getMin()
const {
return m_min; }
172 T getMax()
const {
return m_max; }
174 void setMin(T mmin) { m_min = mmin; }
175 void setMax(T mmax) { m_min = mmax; }
178 T m_min{0}, m_max{0};
182 template<
class T=real_t>
184 class gsCurveBoundingBox
187 explicit gsCurveBoundingBox(
const gsBSpline<T> &curve)
189 range(curve.domainStart(),curve.domainEnd())
191 low.resize( curve.geoDim() );
192 high.resize(curve.geoDim() );
193 for (
short_t i = 0; i != curve.geoDim(); ++i)
195 low[i] = std::numeric_limits<T>::max();
196 high[i] = std::numeric_limits<T>::lowest();
200 for (
index_t ipt = 0; ipt != curve.coefsSize(); ++ipt)
202 typename gsMatrix<T>::ConstRowXpr p = curve.coef(ipt);
203 for (
short_t i = 0; i != curve.geoDim(); ++i)
205 high[i] = math::max(high[i], p(i));
206 low[i] = math::min(low[i], p(i));
212 bool intersect(
const gsCurveBoundingBox<T> &other,
213 T eps = EPSILON_CCI)
const
215 GISMO_ASSERT( this->getLow().size() == other.getLow().size(),
"Size mismatch between this and other size" );
216 for (
index_t i = 0; i != other.getLow().size(); ++i)
218 if (math::max(low[i], other.low[i]) > math::min(high[i], other.high[i]) + eps)
224 gsVector<T> getLow()
const {
return low; }
225 gsVector<T> getHigh()
const {
return high; }
226 gsInterval<T> getRange()
const {
return range; }
229 gsVector<T> low, high;
233 template<
class T=real_t>
234 struct gsBoundingBoxPair
236 gsBoundingBoxPair(
const gsCurveBoundingBox<T> &i1,
const gsCurveBoundingBox<T> &i2)
242 gsCurveBoundingBox<T> b1;
243 gsCurveBoundingBox<T> b2;
253 template<
class T=real_t>
256 const T MAX_CURVATURE)
258 gsCurveBoundingBox<T> h1(curve1);
259 gsCurveBoundingBox<T> h2(curve2);
261 std::vector<gsBoundingBoxPair<T>> result;
264 if (!h1.intersect(h2))
272 if (crv1Curvature <= MAX_CURVATURE && crv2Curvature <= MAX_CURVATURE)
274 if ( curve1.
geoDim() == 2 )
277 gsPoint2d<T> pt1(curve1.
coef(0).x(), curve1.
coef(0).y());
279 gsPoint2d<T> pt3(curve2.
coef(0).x(), curve2.
coef(0).y());
281 if (doIntersect(pt1, pt2, pt3, pt4))
283 result.push_back(gsBoundingBoxPair<T>(h1, h2));
289 result.push_back(gsBoundingBoxPair<T>(h1, h2));
295 if (crv1Curvature > MAX_CURVATURE && crv2Curvature > MAX_CURVATURE)
302 curve1.
splitAt(curve1MidParm, c11, c12);
303 curve2.
splitAt(curve2MidParm, c21, c22);
305 std::vector<gsBoundingBoxPair<T>> result1 = getPotentialIntersectionRanges<T>(c11, c21, MAX_CURVATURE);
306 std::vector<gsBoundingBoxPair<T>> result2 = getPotentialIntersectionRanges<T>(c11, c22, MAX_CURVATURE);
307 std::vector<gsBoundingBoxPair<T>> result3 = getPotentialIntersectionRanges<T>(c12, c21, MAX_CURVATURE);
308 std::vector<gsBoundingBoxPair<T>> result4 = getPotentialIntersectionRanges<T>(c12, c22, MAX_CURVATURE);
311 result.insert(result.end(), result1.begin(), result1.end());
312 result.insert(result.end(), result2.begin(), result2.end());
313 result.insert(result.end(), result3.begin(), result3.end());
314 result.insert(result.end(), result4.begin(), result4.end());
318 else if (crv1Curvature <= MAX_CURVATURE && MAX_CURVATURE < crv2Curvature)
323 curve2.
splitAt(curve2MidParm, c21, c22);
325 std::vector<gsBoundingBoxPair<T>> result1 = getPotentialIntersectionRanges<T>(curve1, c21, MAX_CURVATURE);
326 std::vector<gsBoundingBoxPair<T>> result2 = getPotentialIntersectionRanges<T>(curve1, c22, MAX_CURVATURE);
328 result.insert(result.end(), result1.begin(), result1.end());
329 result.insert(result.end(), result2.begin(), result2.end());
332 else if (crv2Curvature <= MAX_CURVATURE && MAX_CURVATURE < crv1Curvature)
337 curve1.
splitAt(curve1MidParm, c11, c12);
339 std::vector<gsBoundingBoxPair<T>> result1 = getPotentialIntersectionRanges<T>(c11, curve2, MAX_CURVATURE);
340 std::vector<gsBoundingBoxPair<T>> result2 = getPotentialIntersectionRanges<T>(c12, curve2, MAX_CURVATURE);
342 result.insert(result.end(), result1.begin(), result1.end());
343 result.insert(result.end(), result2.begin(), result2.end());
351 template<
class T=real_t>
352 class gsCurveCurveDistanceSystem
363 void Values(
const gsVector<T,2> &uv,
364 gsMatrix<T> &funcVal,
365 gsMatrix<T> &invJac)
const
367 std::vector<gsMatrix<T>> crv1Der = m_crv1.evalAllDers(uv.row(0), 1);
368 std::vector<gsMatrix<T>> crv2Der = m_crv2.evalAllDers(uv.row(1), 1);
370 funcVal = crv1Der[0] - crv2Der[0];
372 gsMatrix<T>
jac(m_crv1.geoDim(), 2);
373 jac.col(0) = crv1Der[1];
374 jac.col(1) = -crv2Der[1];
375 invJac =
jac.completeOrthogonalDecomposition().pseudoInverse();
379 T compute(gsVector<T,2> &uv, T tolerance = 1e-5,
size_t maxIter = 20)
const
383 Values(uv, funVal, invJac);
384 T currentResidual = funVal.norm();
386 gsVector<T,2> deltaUv = invJac * funVal;
388 for (
size_t iter = 1; iter != maxIter; ++iter)
393 newUv.at(0) = math::min(math::max(uv.at(0), m_crv1.domainStart()), m_crv1.domainEnd());
394 newUv.at(1) = math::min(math::max(uv.at(1), m_crv2.domainStart()), m_crv2.domainEnd());
399 T delta = (uv - newUv).norm();
402 if (delta > EPSILON_CCI)
404 Values(uv, funVal, invJac);
405 currentResidual = funVal.norm();
409 Values(uv, funVal, invJac);
410 currentResidual = funVal.norm();
411 if (currentResidual < tolerance)
414 deltaUv = invJac * funVal;
415 if (deltaUv.norm() < 1e-3*tolerance)
420 return currentResidual;
424 const gsBSpline<T> m_crv1{}, m_crv2{};
gsMatrix< T >::RowXpr coef(index_t i)
Returns the i-th coefficient of the geometry as a row expression.
Definition: gsGeometry.h:346
T pseudoCurvature() const
Definition: gsBSpline.hpp:189
#define short_t
Definition: gsConfig.h:35
#define index_t
Definition: gsConfig.h:32
T domainEnd() const
Returns the end value of the domain of the basis.
Definition: gsBSpline.h:167
index_t coefsSize() const
Return the number of coefficients (control points)
Definition: gsGeometry.h:371
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
A B-spline function of one argument, with arbitrary target dimension.
Definition: gsBSpline.h:50
bool operator!=(gsVertex< T > const &lhs, gsVertex< T > const &rhs)
Definition: gsVertex.h:240
bool gsClose(const T &a, const T &b, const T &tol)
tests if the difference between two numbers is below tolerance
Definition: gsMath.h:439
This is the main header file that collects wrappers of Eigen for linear algebra.
T domainStart() const
Returns the starting value of the domain of the basis.
Definition: gsBSpline.h:164
std::vector< gsBoundingBoxPair< T > > getPotentialIntersectionRanges(const gsBSpline< T > &curve1, const gsBSpline< T > &curve2, const T MAX_CURVATURE)
Definition: gsCurveCurveIntersection.h:254
short_t geoDim() const
Dimension n of the absent physical space.
Definition: gsGeometry.h:292
void splitAt(T u0, gsBSpline< T > &left, gsBSpline< T > &right, T tolerance=1e-15) const
Definition: gsBSpline.hpp:255
EIGEN_STRONG_INLINE jac_expr< E > jac(const symbol_expr< E > &u)
The Jacobian matrix of a FE variable.
Definition: gsExpressions.h:4528