#ifndef __JSEGMENT2D__ #define __JSEGMENT2D__ #include #include #include #include "JIO/JSerialisable.hh" #include "JLang/JException.hh" #include "JMath/JMathToolkit.hh" #include "JGeometry2D/JPosition2D.hh" /** * \author mdejong */ namespace JGEOMETRY2D {} namespace JPP { using namespace JGEOMETRY2D; } namespace JGEOMETRY2D { using JIO::JReader; using JIO::JWriter; using JLANG::JDivisionByZero; /** * Type definition of line segment in two dimensions. */ typedef std::pair JSegment2D_t; /** * Line segment in two dimensions. */ class JSegment2D : public JSegment2D_t { public: /** * Default constructor. */ JSegment2D() : JSegment2D_t() {} /** * Constructor. * * \param A start position * \param B end position */ JSegment2D(const JVector2D& A, const JVector2D& B) : JSegment2D_t(A,B) {} /** * Get length squared. * * \return square of length */ double getLengthSquared() const { return JVector2D(this->second - this->first).getLengthSquared(); } /** * Get length. * * \return length */ double getLength() const { return sqrt(getLengthSquared()); } /** * Test whether two line segments intersect. * * \param segment line segment * \return true if two line segment intersect; else false */ bool intersects(const JSegment2D& segment) const { return (getCCW(this->first, segment.first, this->second) != getCCW(this->first, segment.second, this->second) && getCCW(segment.first, this->first, segment.second) != getCCW(segment.first, this->second, segment.second)); } /** * Get intersection of two line segments. * * \param segment line segment * \return intersection point */ JVector2D getIntersection(const JSegment2D& segment) const { JVector2D da(this->second - this->first); JVector2D db(segment.second - segment.first); const double gp = JMATH::getPerpDot(da, db); if (gp != 0.0) { da.mul(JMATH::getPerpDot(segment.second, segment.first)); db.mul(JMATH::getPerpDot(this->second, this->first)); db.sub(da); db.div(gp); return db; } else { throw JDivisionByZero("JSegment2D::getIntersection()"); } } /** * Get squared of distance to point. * * \param point point * \return square of distance */ double getDistanceSquared(const JVector2D& point) const { JVector2D D(this->second - this->first); const double gp = D.getLengthSquared(); if (gp != 0.0) { const JVector2D U(point - this->first); double u = D.getDot(U); if (u < 0.0) u = 0.0; else if (u > gp) u = 1.0; else u /= gp; D.mul(u); D.sub(U); return D.getLengthSquared(); } else { return first.getDistanceSquared(point); } } /** * Get distance to point. * * \param point point * \return distance */ double getDistance(const JVector2D& point) const { return sqrt(getDistanceSquared(point)); } /** * Get dot product. * * \param segment segment * \return dot product */ double getDot(const JSegment2D& segment) const { return JVector2D(this->second - this->first).getDot(segment.second - segment.first); } /** * Read segment from input. * * \param in reader * \param segment segment * \return reader */ friend inline JReader& operator>>(JReader& in, JSegment2D& segment) { in >> segment.first; in >> segment.second; return in; } /** * Write segment to output. * * \param out writer * \param segment segment * \return writer */ friend inline JWriter& operator<<(JWriter& out, const JSegment2D& segment) { out << segment.first; out << segment.second; return out; } }; } #endif