@i cgal_util.fwi @$@<2D Straight declaration@>==@{ CGAL_BEGIN_NAMESPACE class Straight_2_base_ { public: enum states {EMPTY, POINT, SEGMENT, RAY, LINE}; enum bound_states {NO_UNBOUNDED=0, MIN_UNBOUNDED=1, MAX_UNBOUNDED=2, BOTH_UNBOUNDED = 3, LINE_EMPTY = 4}; protected: Straight_2_base_() ; int main_dir_; // support_ is x or y directed (0/1). int dir_sign_; // sign of main direction coord. unsigned int bound_state_; // 0, 1, 2, 3, 4. public: inline unsigned int bound_state() const {return bound_state_;} }; template class Straight_2_: public Straight_2_base_ { public: Straight_2_() ; Straight_2_(Point_2 const &point) ; Straight_2_(Line_2 const &line) ; Straight_2_(Ray_2 const &ray) ; Straight_2_(Ray_2 const &ray,bool cooriented) ; Straight_2_(Segment_2 const &seg) ; ~Straight_2_() {} void cut_right_off(Line_2 const & cutter) ; int collinear_order(Point_2 const & p1, Point_2 const &p2) const ; void current(Line_2 &line) const; void current(Ray_2 &ray) const; void current(Segment_2 &seg) const; void current(Point_2 &point) const; states current_state() const; bool operator==(const Straight_2_&) const; bool operator!=(const Straight_2_&other) const { return !(*this == other);} protected: Line_2 support_; // The supporting line. Point_2 min_; Point_2 max_; }; CGAL_END_NAMESPACE @<2D Straight implementation@> @} @$@<2D Straight implementation@>==@{ #include CGAL_BEGIN_NAMESPACE inline Straight_2_base_:: Straight_2_base_() { bound_state_ = LINE_EMPTY; } template Straight_2_base_::states Straight_2_:: current_state() const { switch (bound_state_) { case BOTH_UNBOUNDED: return LINE; case MIN_UNBOUNDED: case MAX_UNBOUNDED: return RAY; case NO_UNBOUNDED: return (collinear_order(min_, max_) == 0) ? POINT : SEGMENT; case LINE_EMPTY: default: return EMPTY; } } template Straight_2_:: Straight_2_() { bound_state_ = LINE_EMPTY; } template Straight_2_:: Straight_2_(Line_2 const &line) { support_ = line; Vector_2 const &dir = support_.direction().to_vector(); main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; dir_sign_ = CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); bound_state_ = BOTH_UNBOUNDED; } template Straight_2_:: Straight_2_(Point_2 const &point) { support_ = Line_2(point, Direction_2(R::RT(1),R::RT(0))); main_dir_ = 0; dir_sign_ = 1; bound_state_ = NO_UNBOUNDED; min_ = point; max_ = point; } template Straight_2_:: Straight_2_(Ray_2 const &ray) { support_ = ray.supporting_line(); Vector_2 const &dir = ray.direction().to_vector(); // main_dir_ = (CGAL_NTS abs(dir.hx()) > CGAL_NTS abs(dir.hy()) ) ? 0 : 1; main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; dir_sign_ = CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); bound_state_ = MAX_UNBOUNDED; min_ = ray.start(); } template Straight_2_:: Straight_2_(Ray_2 const &ray_,bool cooriented) { Ray_2 const &ray = cooriented ? ray_ : ray_.opposite(); support_ = ray.supporting_line(); /* the supporting line is cooriented with the input ray iff cooriented is true */ Vector_2 const &dir = ray.direction().to_vector(); // main_dir_ = (CGAL_NTS abs(dir.hx()) > CGAL_NTS abs(dir.hy()) ) ? 0 : 1; main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; dir_sign_ = CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); if (cooriented) { bound_state_ = MAX_UNBOUNDED; min_ = ray.start(); } else { bound_state_ = MIN_UNBOUNDED; max_ = ray.start(); } } template Straight_2_:: Straight_2_(Segment_2 const &seg) { support_ = seg.supporting_line(); Vector_2 const &dir = support_.direction().to_vector(); main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; dir_sign_ = CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); bound_state_ = NO_UNBOUNDED; min_ = seg.start(); max_ = seg.end(); } template void Straight_2_:: current(Line_2 &line) const { CGAL_kernel_assertion(bound_state_ == BOTH_UNBOUNDED); line = support_; } template void Straight_2_:: current(Ray_2 &ray) const { CGAL_kernel_assertion(bound_state_ == MIN_UNBOUNDED || bound_state_ == MAX_UNBOUNDED); if (bound_state_ == MIN_UNBOUNDED) { ray = Ray_2(max_, -support_.direction()); } else { ray = Ray_2(min_, support_.direction()); } } template void Straight_2_:: current(Segment_2 &seg) const { CGAL_kernel_assertion(bound_state_ == NO_UNBOUNDED && collinear_order(min_, max_) != 0); seg = Segment_2(min_, max_); } template void Straight_2_:: current(Point_2 &pt) const { CGAL_kernel_assertion(bound_state_ == NO_UNBOUNDED && collinear_order(min_, max_) == 0); pt = min_; } template bool Straight_2_::operator==(const Straight_2_& s) const { typedef Straight_2_ Straight_2; // enum bound_states {NO_UNBOUNDED=0, MIN_UNBOUNDED=1, MAX_UNBOUNDED=2, // BOTH_UNBOUNDED = 3, LINE_EMPTY = 4}; if (bound_state_!=s.bound_state()) return false; if (bound_state_==Straight_2::LINE_EMPTY) return true; // empty if (support_!=s.support_) return false; // on different lines, even if both are points. switch (bound_state_) { case Straight_2::NO_UNBOUNDED: return min_==s.min_ && max_==s.max_; case Straight_2::MAX_UNBOUNDED: return min_==s.min_; case Straight_2::MIN_UNBOUNDED: return max_==s.max_; case Straight_2::BOTH_UNBOUNDED: return true; } return false; } /* template R::FT cross(Vector_2 const &vec1, Vector_2 const &vec2) { (vec1.hx() * vec2.hy() - vec1.hy() * vec2.hx()) / (vec1.hw()*vec2.hw()); } */ #if 0 // #ifdef CGAL_CARTESIAN_H template FT cross(Vector_2< Cartesian > const &vec1, Vector_2< Cartesian > const &vec2) { return vec1.x() * vec2.y() - vec1.y() * vec2.x(); } template int sign_of_cross(Direction_2 const &dir1, Direction_2 const &dir2) { return CGAL_NTS sign(cross(dir1.to_vector(), dir2.to_vector())); } #endif CGAL_END_NAMESPACE #include CGAL_BEGIN_NAMESPACE template int sign_of_cross(Direction_2 const &dir1, Direction_2 const &dir2) { int result; switch(orientation(dir1.to_vector(), dir2.to_vector())) { case COUNTERCLOCKWISE: result = 1; break; case CLOCKWISE: result = -1; break; case COLLINEAR: result = 0; break; } return result; } template void Straight_2_:: cut_right_off(Line_2 const & cutter) // cut off any part of this straight that is to the right of the cutter. { if (bound_state_ == LINE_EMPTY) return; Point_2 ispoint; bool new_point; Line_2_Line_2_pair pair(&support_, &cutter); switch (pair.intersection_type()) { case Line_2_Line_2_pair::NO: if (cutter.has_on_negative_side(support_.point())) bound_state_ = LINE_EMPTY; break; case Line_2_Line_2_pair::LINE: break; case Line_2_Line_2_pair::POINT: pair.intersection(ispoint); new_point = false; switch (sign_of_cross(support_.direction(), cutter.direction())) { case -1: // new minimum. if (bound_state_ & MIN_UNBOUNDED) { new_point = true; bound_state_ ^= MIN_UNBOUNDED; // exclusive or removes flag. } else { if (collinear_order(ispoint, min_) == -1) new_point = true; } if (new_point) { if (!(bound_state_ & MAX_UNBOUNDED) && collinear_order(ispoint, max_) == -1) bound_state_ = LINE_EMPTY; else min_ = ispoint; } break; case 0: // should not happen CGAL_kernel_warning_msg(false, "Internal CGAL error."); break; case 1: // new maximum if (bound_state_ & MAX_UNBOUNDED) { new_point = true; bound_state_ ^= MAX_UNBOUNDED; // exclusive or removes flag. } else { if (collinear_order(ispoint, max_) == 1) new_point = true; } if (new_point) { if (!(bound_state_ & MIN_UNBOUNDED) && collinear_order(ispoint, min_) == 1) bound_state_ = LINE_EMPTY; else max_ = ispoint; } break; } break; } } template int Straight_2_:: collinear_order(Point_2 const &pt1, Point_2 const & pt2) const // Compare two points on the support_ line. // If the second point lies in the direction of the direction vector from // the first point, the result is 1. // Other results are -1 (other side) and 0 (coincidence). { int diffsign; diffsign = CGAL_NTS sign(pt2.cartesian(main_dir_)-pt1.cartesian(main_dir_)); if (diffsign == 0) return 0; return (diffsign == dir_sign_) ? 1 : -1; } CGAL_END_NAMESPACE @} @$@<2D Straight stream declaration@>==@{ CGAL_BEGIN_NAMESPACE #ifndef CGAL_NO_OSTREAM_INSERT_STRAIGHT_2 template std::ostream& operator<<(std::ostream& os,const Straight_2_& cv) { typedef Pm_straight_exact_traits Traits; typedef Straight_2_ Curve; switch(cv.current_state()) { case Curve::SEGMENT: { Segment_2 seg; cv.current(seg); return os << seg; } case Curve::RAY: { Ray_2 ray; cv.current(ray); return os << ray; } case Curve::LINE: { Line_2 line; cv.current(line); return os << line; } case Curve::POINT: { Point_2 p; cv.current(p); return os << p; } case Curve::EMPTY: break; } CGAL_assertion_msg( cv.current_state()==Curve::SEGMENT|| cv.current_state()==Curve::RAY|| cv.current_state()==Curve::LINE|| cv.current_state()==Curve::POINT|| cv.current_state()==Curve::EMPTY, "\nUnknown type in std:: ostream& operator<<( \ std:: ostream& os,const Straight_2&)"); return os; } #endif //CGAL_NO_OSTREAM_INSERT_STRAIGHT_2 #ifndef CGAL_NO_ISTREAM_EXTRACT_STRAIGHT_2 template std:: istream& operator>>(std:: istream& is,Straight_2_& cv) { typedef Pm_straight_exact_traits Traits; typedef Straight_2_ Curve; switch(cv.current_state()) { case Curve::SEGMENT: { Segment_2 seg; cv.current(seg); return os >> seg; } case Curve::RAY: { Ray_2 ray; cv.current(ray); return os >> ray; } case Curve::LINE: { Line_2 line; cv.current(line); return os >> line; } case Curve::POINT: { Point_2 p; cv.current(p); return os >> p; } case Curve::EMPTY: break; } CGAL_assertion_msg( cv.current_state()==Curve::SEGMENT|| cv.current_state()==Curve::RAY|| cv.current_state()==Curve::LINE|| cv.current_state()==Curve::POINT|| cv.current_state()==Curve::EMPTY, "\nUnknown type in std:: ostream& operator>>( \ std:: ostream& os,Straight_2&)"); return os; } #endif //CGAL_NO_ISTREAM_EXTRACT_STRAIGHT_2 CGAL_END_NAMESPACE @} @O@<../include/CGAL/Straight_2.h@>==@{ @@(@- include/CGAL/Straight_2.h@,@- straight_2.fw@,@- Geert-Jan Giezeman@,@- MPI, Saarbruecken@) #ifndef CGAL_STRAIGHT_2_H #define CGAL_STRAIGHT_2_H @<2D Straight declaration@> #endif @} @O@<../include/CGAL/Straight_2_stream.h@>==@{ @@(@- include/CGAL/Straight_2_stream.h@,@- straight_2.fw@,@- Oren Nechushtan@,@- MPI, Saarbruecken@) #ifndef CGAL_STRAIGHT_2_STREAM_H #define CGAL_STRAIGHT_2_STREAM_H @<2D Straight stream declaration@> #endif // CGAL_STRAIGHT_2_STREAM_H @}