// D E F I N E S /////////////////////////////////////////////////// // S T R U C T S /////////////////////////////////////////////////// // C L A S S ////////////////////////////////////////////////////// template inline TLine::TLine(const POINT& _pt1, const POINT& _pt2) : pt1(_pt1), pt2(_pt2) { ASSERT(!ISZERO((_pt1-_pt2).norm())); } // constructor template template inline TLine::TLine(const TLine& rhs) : pt1(rhs.pt1.template cast()), pt2(rhs.pt2.template cast()) { } // copy constructor /*----------------------------------------------------------------*/ // set attributes template inline void TLine::Set(const POINT& _pt1, const POINT& _pt2) { ASSERT(!ISZERO((_pt1-_pt2).norm())); pt1 = _pt1; pt2 = _pt2; } /*----------------------------------------------------------------*/ // least squares refinement of the line to the given 3D point set // (return the number of iterations) template template int TLine::Optimize(const POINT* points, size_t size, const RobustNormFunctor& robust, int maxIters) { ASSERT(DIMS == 3); ASSERT(size >= numParams); struct OptimizationFunctor { const POINT* points; size_t size; double scale; const RobustNormFunctor& robust; // construct with the data points OptimizationFunctor(const POINT* _points, size_t _size, const RobustNormFunctor& _robust) : points(_points), size(_size), robust(_robust) { ASSERT(size < std::numeric_limits::max()); } static void Residuals(const double* x, int nPoints, const void* pData, double* fvec, double* fjac, int* /*info*/) { const OptimizationFunctor& data = *reinterpret_cast(pData); ASSERT((size_t)nPoints == data.size && fvec != NULL && fjac == NULL); TLine line; for (int j=0; j())); } } functor(points, size, robust); double arrParams[numParams]; for (int j=0; j int TLine::Optimize(const POINT* points, size_t size, int maxIters) { const auto identity = [](double x) { return x; }; return Optimize(points, size, identity, maxIters); } // Optimize /*----------------------------------------------------------------*/ // get attributes template inline TYPE TLine::GetLength() const { return (pt2 - pt1).norm(); } template inline TYPE TLine::GetLengthSq() const { return (pt2 - pt1).squaredNorm(); } template inline typename TLine::POINT TLine::GetCenter() const { return (pt2 + pt1) / TYPE(2); } template inline typename TLine::VECTOR TLine::GetDir() const { return (pt2 - pt1); } template inline typename TLine::VECTOR TLine::GetNormDir() const { return (pt2 - pt1).normalized(); } template inline typename TLine::RAY TLine::GetRay() const { return RAY(pt1, GetNormDir()); } /*----------------------------------------------------------------*/ template inline bool TLine::IsSame(const TLine& line, TYPE th) const { const TYPE thSq(SQUARE(th)); const VECTOR l(pt2-pt1); const TYPE invLenSq(INVERT(l.squaredNorm())); const VECTOR r1(pt1-line.pt1); const TYPE dSq1((l.cross(r1)).squaredNorm()*invLenSq); if (dSq1 > thSq) return false; const VECTOR r2(pt1-line.pt2); const TYPE dSq2((l.cross(r2)).squaredNorm()*invLenSq); return dSq2 <= thSq; } /*----------------------------------------------------------------*/ // test for intersection with aabb template bool TLine::Intersects(const AABB &aabb) const { return GetRay().Intersects(aabb); } // Intersects(AABB) template bool TLine::Intersects(const AABB &aabb, TYPE& t) const { return GetRay().Intersects(aabb, t); } // Intersects(AABB) /*----------------------------------------------------------------*/ // Computes the distance between the line and a point. template inline TYPE TLine::DistanceSq(const POINT& pt) const { const VECTOR l(pt2-pt1), r(pt1-pt); if (DIMS == 2) return TYPE(SQUARE(l[0]*r[1]-r[0]*l[1])/(l[0]*l[0]+l[1]*l[1])); ASSERT(DIMS == 3); return TYPE((l.cross(r)).squaredNorm()/l.squaredNorm()); } // DistanceSq(POINT) template inline TYPE TLine::Distance(const POINT& pt) const { return SQRT(DistanceSq(pt)); } // Distance(POINT) /*----------------------------------------------------------------*/ // Computes the position on the line segment of the point projection. // Returns 0 if it coincides with the first point, and 1 if it coincides with the second point. template inline TYPE TLine::Classify(const POINT& p) const { const VECTOR vL(pt2 - pt1); ASSERT(!ISZERO(vL.squaredNorm())); const VECTOR vP(p - pt1); return vL.dot(vP) / vL.squaredNorm(); } // Classify(POINT) // Calculate point's projection on this line (closest point to this line). template inline typename TLine::POINT TLine::ProjectPoint(const POINT& p) const { const VECTOR vL(pt2 - pt1); ASSERT(!ISZERO(vL.squaredNorm())); const VECTOR vP(p - pt1); return pt1 + vL * (vL.dot(vP) / vL.squaredNorm()); } // ProjectPoint /*----------------------------------------------------------------*/ template template TPoint3 FitLineOnline::GetLine(TLine& line) const { TPoint3 avg, dir; const TPoint3 quality(this->GetModel(avg, dir)); const TPoint3 pt2(avg+dir); line.Set(TPoint3(avg), TPoint3(pt2)); return TPoint3(quality); } /*----------------------------------------------------------------*/