| #pragma once |
| |
| #ifndef T_CURVES_INCLUDED |
| #define T_CURVES_INCLUDED |
| |
| #include "tgeometry.h" |
| |
| #undef DVAPI |
| #undef DVVAR |
| #ifdef TGEOMETRY_EXPORTS |
| #define DVAPI DV_EXPORT_API |
| #define DVVAR DV_EXPORT_VAR |
| #else |
| #define DVAPI DV_IMPORT_API |
| #define DVVAR DV_IMPORT_VAR |
| #endif |
| |
| |
| |
| |
| |
| class DVAPI TSegment { |
| protected: |
| TPointD m_c0, m_c1; |
| |
| public: |
| TSegment() : m_c0(), m_c1(){}; |
| |
| |
| TSegment(const TPointD &p0, const TPointD &p1) : m_c0(p0), m_c1(p1 - p0) {} |
| |
| TSegment(double x0, double y0, double x1, double y1) |
| : m_c0(x0, y0), m_c1(x1 - x0, y1 - y0) {} |
| |
| TSegment(const TSegment &src) : m_c0(src.m_c0), m_c1(src.m_c1) {} |
| |
| |
| TPointD getPoint(double t) const { return m_c0 + t * m_c1; }; |
| |
| |
| TPointD getSpeed(double = 0) const { return m_c1; }; |
| |
| |
| TPointD getP0() const { return m_c0; } |
| |
| TPointD getP1() const { return m_c0 + m_c1; } |
| |
| |
| void setP0(const TPointD &p) { |
| m_c1 += m_c0 - p; |
| m_c0 = p; |
| } |
| |
| void setP1(const TPointD &p) { m_c1 = p - m_c0; } |
| |
| bool operator==(const TSegment &c) const { |
| return m_c0 == c.m_c0 && m_c1 == c.m_c1; |
| }; |
| |
| bool operator!=(const TSegment &c) const { return !operator==(c); }; |
| |
| |
| TRectD getBBox() const { return TRectD(getP0(), getP1()); } |
| |
| |
| double getLength() const { return norm(m_c1); } |
| |
| |
| bool isPoint(double err2 = TConsts::epsilon) const { |
| return norm2(m_c1) < err2; |
| } |
| }; |
| |
| |
| |
| DVAPI std::ostream &operator<<(std::ostream &out, const TSegment &segment); |
| |
| |
| |
| |
| inline TSegment operator*(const TAffine &aff, const TSegment &seg) { |
| return TSegment(aff * seg.getP0(), aff * seg.getP1()); |
| } |
| |
| |
| |
| |
| |
| class DVAPI TQuadratic { |
| protected: |
| TPointD m_p0, m_p1, m_p2; |
| |
| public: |
| TQuadratic() : m_p0(), m_p1(), m_p2() {} |
| |
| |
| TQuadratic(const TPointD &p0, const TPointD &p1, const TPointD &p2) |
| : m_p0(p0), m_p1(p1), m_p2(p2) {} |
| |
| TQuadratic(const TQuadratic &src) |
| : m_p0(src.m_p0), m_p1(src.m_p1), m_p2(src.m_p2) {} |
| |
| TQuadratic &operator=(const TQuadratic &src) { |
| m_p0 = src.m_p0; |
| m_p1 = src.m_p1; |
| m_p2 = src.m_p2; |
| return *this; |
| } |
| |
| |
| TPointD getPoint(double t) const; |
| double getX(double t) const; |
| double getY(double t) const; |
| |
| |
| TPointD getSpeed(double t) const { |
| return 2 * ((t - 1) * m_p0 + (1.0 - 2.0 * t) * m_p1 + t * m_p2); |
| } |
| |
| |
| double getSpeedY(double t) const { |
| return 2 * ((t - 1) * m_p0.y + (1.0 - 2.0 * t) * m_p1.y + t * m_p2.y); |
| } |
| |
| |
| TPointD getAcceleration(double = 0) const { |
| return 2.0 * (m_p0 + m_p2 - 2.0 * m_p1); |
| } |
| |
| |
| |
| |
| |
| |
| double getCurvature(double t) const; |
| |
| |
| TPointD getP0() const { return m_p0; } |
| |
| TPointD getP1() const { return m_p1; } |
| |
| TPointD getP2() const { return m_p2; } |
| |
| |
| void setP0(const TPointD &p) { m_p0 = p; } |
| |
| void setP1(const TPointD &p) { m_p1 = p; } |
| |
| void setP2(const TPointD &p) { m_p2 = p; } |
| |
| bool operator==(const TQuadratic &c) const { |
| return m_p0 == c.m_p0 && m_p1 == c.m_p1 && m_p2 == c.m_p2; |
| } |
| |
| bool operator!=(const TQuadratic &c) const { return !operator==(c); } |
| |
| |
| double getT(const TPointD &p) const; |
| |
| int getX(double y, double &x0, double &x1) const; |
| |
| int getY(double x, double &y0, double &y1) const; |
| |
| |
| |
| |
| void split(double t, TQuadratic &first, TQuadratic &second) const; |
| |
| |
| TRectD getBBox() const; |
| |
| |
| |
| |
| |
| |
| |
| double getLength(double t0, double t1) const; |
| |
| double getLength(double t1 = 1) const { return getLength(0, t1); } |
| |
| double getApproximateLength(double t0, double t1, double error) const; |
| |
| void reverse() { |
| TPointD app; |
| app = m_p0; |
| m_p0 = m_p2; |
| m_p2 = app; |
| } |
| }; |
| |
| |
| |
| |
| inline TQuadratic operator*(const TAffine &aff, const TQuadratic &curve) { |
| TQuadratic quad; |
| quad.setP0(aff * curve.getP0()); |
| quad.setP1(aff * curve.getP1()); |
| quad.setP2(aff * curve.getP2()); |
| return quad; |
| } |
| |
| |
| |
| DVAPI std::ostream &operator<<(std::ostream &out, const TQuadratic &curve); |
| |
| |
| |
| inline std::ostream &operator<<(std::ostream &out, const TQuadratic *curve) { |
| assert(curve); |
| return out << *curve; |
| } |
| |
| |
| |
| |
| |
| class DVAPI TCubic { |
| protected: |
| TPointD m_p0, m_p1, m_p2, m_p3; |
| |
| public: |
| TCubic() : m_p0(), m_p1(), m_p2(), m_p3() {} |
| |
| |
| TCubic(const TPointD &p0, const TPointD &p1, const TPointD &p2, |
| const TPointD &p3) |
| : m_p0(p0), m_p1(p1), m_p2(p2), m_p3(p3) {} |
| |
| TCubic(const TCubic &src) |
| : m_p0(src.m_p0), m_p1(src.m_p1), m_p2(src.m_p2), m_p3(src.m_p3) {} |
| |
| TCubic &operator=(const TCubic &src) { |
| m_p0 = src.m_p0; |
| m_p1 = src.m_p1; |
| m_p2 = src.m_p2; |
| m_p3 = src.m_p3; |
| return *this; |
| } |
| |
| |
| TPointD getP0() const { return m_p0; } |
| |
| TPointD getP1() const { return m_p1; } |
| |
| TPointD getP2() const { return m_p2; } |
| |
| TPointD getP3() const { return m_p3; } |
| |
| |
| void setP0(const TPointD &p0) { m_p0 = p0; } |
| |
| void setP1(const TPointD &p1) { m_p1 = p1; } |
| |
| void setP2(const TPointD &p2) { m_p2 = p2; } |
| |
| void setP3(const TPointD &p3) { m_p3 = p3; } |
| |
| bool operator==(const TCubic &c) const { |
| return m_p0 == c.m_p0 && m_p1 == c.m_p1 && m_p2 == c.m_p2 && m_p3 == c.m_p3; |
| } |
| |
| bool operator!=(const TCubic &c) const { return !operator==(c); } |
| |
| |
| TRectD getBBox() const { |
| return TRectD(std::min({m_p0.x, m_p1.x, m_p2.x, m_p3.x}), |
| std::min({m_p0.y, m_p1.y, m_p2.y, m_p3.y}), |
| std::max({m_p0.x, m_p1.x, m_p2.x, m_p3.x}), |
| std::max({m_p0.y, m_p1.y, m_p2.y, m_p3.y})); |
| }; |
| |
| |
| TPointD getPoint(double t) const; |
| |
| |
| TPointD getSpeed(double t) const; |
| |
| |
| TPointD getAcceleration(double t) const { |
| return 6.0 * |
| ((m_p2 - 2 * m_p1 + m_p0) * (1 - t) + (m_p3 - 2 * m_p2 + m_p1) * t); |
| }; |
| |
| |
| |
| |
| |
| |
| |
| double getLength(double t0, double t1) const; |
| |
| inline double getLength(double t1 = 1.0) const { return getLength(0.0, t1); } |
| |
| |
| |
| |
| void split(double t, TCubic &first, TCubic &second) const; |
| }; |
| |
| |
| |
| |
| inline TCubic operator*(const TAffine &aff, const TCubic &curve) { |
| TCubic out; |
| out.setP0(aff * curve.getP0()); |
| out.setP1(aff * curve.getP1()); |
| out.setP2(aff * curve.getP2()); |
| out.setP3(aff * curve.getP3()); |
| return out; |
| } |
| |
| |
| |
| DVAPI std::ostream &operator<<(std::ostream &out, const TCubic &curve); |
| |
| |
| |
| inline std::ostream &operator<<(std::ostream &out, const TCubic *curve) { |
| assert(curve); |
| return out << *curve; |
| } |
| |
| |
| |
| |
| |
| |
| class DVAPI TThickSegment final : public TSegment { |
| protected: |
| double m_thickP0; |
| double m_thickP1; |
| |
| public: |
| |
| TThickSegment() : TSegment(), m_thickP0(0), m_thickP1(0) {} |
| |
| TThickSegment(const TThickSegment &thickSegment) |
| : TSegment(thickSegment) |
| , m_thickP0(thickSegment.m_thickP0) |
| , m_thickP1(thickSegment.m_thickP1) {} |
| |
| TThickSegment(const TSegment &seg) |
| : TSegment(seg), m_thickP0(0), m_thickP1(0) {} |
| |
| TThickSegment(const TPointD &p0, double thickP0, const TPointD &p1, |
| double thickP1) |
| : TSegment(p0, p1), m_thickP0(thickP0), m_thickP1(thickP1) {} |
| |
| TThickSegment(const TThickPoint &thickP0, const TThickPoint &thickP1) |
| : TSegment(thickP0, thickP1) |
| , m_thickP0(thickP0.thick) |
| , m_thickP1(thickP1.thick) {} |
| |
| TThickSegment &operator=(const TThickSegment &other) { |
| m_c0.x = other.m_c0.x; |
| m_c1.x = other.m_c1.x; |
| m_c0.y = other.m_c0.y; |
| m_c1.y = other.m_c1.y; |
| m_thickP0 = other.m_thickP0; |
| m_thickP1 = other.m_thickP1; |
| return *this; |
| } |
| |
| |
| void setThickP0(const TThickPoint &p0) { |
| m_c0.x = p0.x; |
| m_c0.y = p0.y; |
| m_thickP0 = p0.thick; |
| } |
| |
| void setThickP1(const TThickPoint &p1) { |
| m_c1.x = p1.x - m_c0.x; |
| m_c1.y = p1.y - m_c0.y; |
| m_thickP1 = p1.thick; |
| } |
| |
| |
| TThickPoint getThickP0() const { return TThickPoint(m_c0, m_thickP0); } |
| |
| TThickPoint getThickP1() const { return TThickPoint(m_c0 + m_c1, m_thickP1); } |
| |
| |
| TThickPoint getThickPoint(double t) const { |
| return TThickPoint(m_c0 + t * m_c1, (1 - t) * m_thickP0 + t * m_thickP1); |
| } |
| }; |
| |
| |
| |
| inline TThickSegment operator*(const TAffine &aff, const TThickSegment &ts) { |
| TThickSegment out(ts); |
| out.setP0(aff * ts.getP0()); |
| out.setP1(aff * ts.getP1()); |
| return out; |
| } |
| |
| |
| |
| DVAPI std::ostream &operator<<(std::ostream &out, const TThickSegment &segment); |
| |
| |
| |
| inline std::ostream &operator<<(std::ostream &out, |
| const TThickSegment *segment) { |
| assert(segment); |
| return out << *segment; |
| } |
| |
| |
| |
| |
| |
| |
| |
| class DVAPI TThickQuadratic final : public TQuadratic { |
| protected: |
| double m_thickP0; |
| double m_thickP1; |
| double m_thickP2; |
| |
| public: |
| TThickQuadratic(); |
| |
| |
| TThickQuadratic(const TPointD &p0, double thickP0, const TPointD &p1, |
| double thickP1, const TPointD &p2, double thickP2); |
| |
| TThickQuadratic(const TThickPoint &p0, const TThickPoint &p1, |
| const TThickPoint &p2); |
| |
| TThickQuadratic(const TThickQuadratic &thickQuadratic); |
| |
| TThickQuadratic(const TQuadratic &quadratic); |
| |
| |
| void setThickP0(const TThickPoint &p); |
| |
| void setThickP1(const TThickPoint &p); |
| |
| void setThickP2(const TThickPoint &p); |
| |
| |
| TThickPoint getThickPoint(double t) const; |
| |
| |
| TThickPoint getThickP0() const { return TThickPoint(m_p0, m_thickP0); } |
| |
| TThickPoint getThickP1() const { return TThickPoint(m_p1, m_thickP1); } |
| |
| TThickPoint getThickP2() const { return TThickPoint(m_p2, m_thickP2); } |
| |
| void split(double t, TThickQuadratic &first, TThickQuadratic &second) const; |
| |
| TRectD getBBox() const; |
| }; |
| |
| |
| |
| inline TThickQuadratic operator*(const TAffine &aff, |
| const TThickQuadratic &tq) { |
| TThickQuadratic out(tq); |
| out.setP0(aff * tq.getP0()); |
| out.setP1(aff * tq.getP1()); |
| out.setP2(aff * tq.getP2()); |
| |
| return out; |
| } |
| |
| |
| |
| inline TThickQuadratic transformQuad(const TAffine &aff, |
| const TThickQuadratic &tq, |
| bool doChangeThickness = false) { |
| if (!doChangeThickness) return aff * tq; |
| |
| TThickQuadratic out(tq); |
| double det = aff.det(); |
| det = (det < 0) ? sqrt(-det) : sqrt(det); |
| |
| out.setThickP0(TThickPoint(aff * tq.getP0(), tq.getThickP0().thick * det)); |
| out.setThickP1(TThickPoint(aff * tq.getP1(), tq.getThickP1().thick * det)); |
| out.setThickP2(TThickPoint(aff * tq.getP2(), tq.getThickP2().thick * det)); |
| return out; |
| } |
| |
| |
| |
| DVAPI std::ostream &operator<<(std::ostream &out, const TThickQuadratic &tq); |
| |
| |
| |
| inline std::ostream &operator<<(std::ostream &out, const TThickQuadratic *tq) { |
| assert(tq); |
| return out << *tq; |
| } |
| |
| |
| |
| |
| |
| |
| |
| class DVAPI TThickCubic final : public TCubic { |
| protected: |
| double m_thickP0; |
| double m_thickP1; |
| double m_thickP2; |
| double m_thickP3; |
| |
| public: |
| TThickCubic(); |
| |
| |
| TThickCubic(const TPointD &p0, double thickP0, const TPointD &p1, |
| double thickP1, const TPointD &p2, double thickP2, |
| const TPointD &p3, double thickP3); |
| |
| TThickCubic(const TThickPoint &p0, const TThickPoint &p1, |
| const TThickPoint &p2, const TThickPoint &p3); |
| |
| |
| TThickCubic(const T3DPointD &p0, const T3DPointD &p1, const T3DPointD &p2, |
| const T3DPointD &p3); |
| |
| |
| |
| TThickCubic(const TThickCubic &thickCubic); |
| |
| TThickCubic(const TCubic &cubic); |
| |
| |
| void setThickP0(const TThickPoint &p); |
| |
| void setThickP1(const TThickPoint &p); |
| |
| void setThickP2(const TThickPoint &p); |
| |
| void setThickP3(const TThickPoint &p); |
| |
| |
| TThickPoint getThickPoint(double t) const; |
| |
| |
| TThickPoint getThickP0() const { return TThickPoint(m_p0, m_thickP0); } |
| |
| TThickPoint getThickP1() const { return TThickPoint(m_p1, m_thickP1); } |
| |
| TThickPoint getThickP2() const { return TThickPoint(m_p2, m_thickP2); } |
| |
| TThickPoint getThickP3() const { return TThickPoint(m_p3, m_thickP3); } |
| |
| void split(double t, TThickCubic &first, TThickCubic &second) const; |
| }; |
| |
| |
| |
| inline TThickCubic operator*(const TAffine &aff, const TThickCubic &tc) { |
| TThickCubic out(tc); |
| out.setP0(aff * tc.getP0()); |
| out.setP1(aff * tc.getP1()); |
| out.setP2(aff * tc.getP2()); |
| out.setP3(aff * tc.getP3()); |
| return out; |
| } |
| |
| |
| |
| DVAPI std::ostream &operator<<(std::ostream &out, const TThickCubic &tc); |
| |
| |
| |
| inline std::ostream &operator<<(std::ostream &out, const TThickCubic *tc) { |
| assert(tc); |
| return out << *tc; |
| } |
| |
| |
| |
| #endif |
| |
| |
| |