All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines
Public Types | Public Member Functions
QGpCoreTools::Segment Class Reference

Brief description of class still missing. More...

#include <Segment.h>

List of all members.

Public Types

enum  RelativePosition {
  Skew, Crossing, Parallel, Aligned,
  Continuous, SmallOverlap, StrongOverlap
}

Public Member Functions

Point directionVector () const
QVector< SegmentdistanceTo (const Segment &seg, RelativePosition &relPos) const
bool includes (const Point &p, double precision=1e-10) const
bool intersects (const Segment &seg, Point &p) const
bool isSimilar (const Segment &o, double precision) const
double length () const
bool operator< (const Segment &o) const
bool parallelTo (const Segment &o) const
Point point (int index) const
 Segment ()
 Segment (const Point &p1, const Point &p2)
 Segment (double x1, double y1, double z1, double x2, double y2, double z2)
 Segment (const Segment &o)
void set (const Point &p1, const Point &p2)
void set (double x1, double y1, double z1, double x2, double y2, double z2)

Detailed Description

Brief description of class still missing.

Full description of class still missing


Member Enumeration Documentation

Enumerator:
Skew 
Crossing 
Parallel 
Aligned 
Continuous 
SmallOverlap 
StrongOverlap 

Constructor & Destructor Documentation

{}
QGpCoreTools::Segment::Segment ( const Point p1,
const Point p2 
) [inline]
{set(p1,p2);}
QGpCoreTools::Segment::Segment ( double  x1,
double  y1,
double  z1,
double  x2,
double  y2,
double  z2 
) [inline]
                                             {set(x1, y1, z1,
                                                  x2, y2, z2);}

References TRACE.

  {
    TRACE;
    _point[0]=o._point[0];
    _point[1]=o._point[1];
    _limits=o._limits;
  }

Member Function Documentation

References QGpCoreTools::Point::distanceTo(), and TRACE.

Referenced by parallelTo().

  {
    TRACE;
    Point p=_point[1];
    p-=_point[0];
    p/=Point().distanceTo(p);
    return p;
  }
QVector< Segment > QGpCoreTools::Segment::distanceTo ( const Segment seg,
RelativePosition relPos 
) const

Based on http://geomalgorithms.com/a07-_distance.html

The length of the returned segment is the distance between the two segments. The end points are the closest points on the two segments.

relPos is set according relative position of segments:

  • Skew Not crossing each other and not parallel
  • Crossing Crossing segments
  • Parallel Parallel segments, supported by distinct lines
  • Aligned Segments supported by the same line, not continuous, nor overlapping segments
  • Continuous Segments are aligned and touch each other by one of their extreme points
  • SmallOverlap Overlapping segments of less than 20% of their length
  • StrongOverlap Overlapping segments of more than 20% of their length

Two segments are returned in the case of Parallel. They limit the overlapping range. In all other cases, a single segment is returned.

References Aligned, Continuous, Crossing, isSimilar(), QGpCoreTools::Point::isSimilar(), length(), Parallel, parallelTo(), QGpCoreTools::Point::scalarProduct(), Skew, SmallOverlap, StrongOverlap, and TRACE.

  {
    TRACE;
    QVector<Segment> res;
    Point u=_point[1];
    u-=_point[0];
    Point v=seg._point[1];
    v-=seg._point[0];
    Point w0=_point[0];
    w0-=seg._point[0];
    double a=u.scalarProduct(u);
    double b=u.scalarProduct(v);
    double c=v.scalarProduct(v);
    double d=u.scalarProduct(w0);
    double e=v.scalarProduct(w0);
    double denom=a*c-b*b;
    if(denom/(a*c)<1e-10) { // Parallel segments, negative value are theoretically impossible
      Segment s[4];
      s[0]=linkSegment(0.0, d/b, _point[0], u, seg._point[0], v);
      s[1]=linkSegment(1.0, (a+d)/b, _point[0], u, seg._point[0], v);
      s[2]=linkSegment(-d/a, 0.0, _point[0], u, seg._point[0], v);
      s[3]=linkSegment((b-d)/a, 1.0, _point[0], u, seg._point[0], v);
      double minLength=INFINITY;
      for(int i=0; i<4; i++) {
        double l=s[i].length();
        if(fabs(l-minLength)<1e-2) {
          res.append(s[i]);
        } else if(l<minLength) {
          minLength=l;
          res.clear();
          res.append(s[i]);
        }
      }
      if(minLength<1e-10) { // Adjacent or Overlap
        if(_point[0].isSimilar(seg._point[0], 1e-2) ||
           _point[0].isSimilar(seg._point[1], 1e-2) ||
           _point[1].isSimilar(seg._point[0], 1e-2) ||
           _point[1].isSimilar(seg._point[1], 1e-2)) {
          relPos=Continuous;
        } else {
          if(minLength<0.2*length() && minLength<0.2*seg.length()) {
            relPos=SmallOverlap;
          } else {
            relPos=StrongOverlap;
          }
        }
      } else { // Parallel or Aligned
        if(parallelTo(res.first())) {
          relPos=Aligned;
        } else {
          relPos=Parallel;
          qSort(res);
          for(int i=res.count()-1; i>0; i--) {
            if(res.at(i).isSimilar(res.at(i-1), 1e-2)) {
              res.remove(i);
            }
          }
          switch(res.count()) {
          case 0:
            ASSERT(false);
            break;
          case 1:
            relPos=Continuous; // Not really if considering only segments
                               // Just means that there is no overlap
            break;
          case 2:
            break;
          default:
            ASSERT(false);
            break;
          }
        }
      }
    } else {
      denom=1.0/denom;
      Segment s=linkSegment((b*e-c*d)*denom, (a*e-b*d)*denom, _point[0], u, seg._point[0], v);
      if(s.length()<1e-10) {
        relPos=Crossing;
      } else {
        relPos=Skew;
      }
      res.append(s);
    }
    return res;
  }
bool QGpCoreTools::Segment::includes ( const Point p,
double  precision = 1e-10 
) const

Returns true if p is located on the segment (1e-10 precision)

References QGpCoreTools::Parallelepiped::includes(), TRACE, QGpCoreTools::Point2D::x(), QGpCoreTools::Point2D::y(), and QGpCoreTools::Point::z().

  {
    TRACE;
    if(!_limits.includes(p)) return false;
    Point u=_point[1];
    u-=_point[0];
    double k;
    if(u.x()!=0.0) {
      k=(p.x()-_point[0].x())/u.x();
      if(fabs(p.y()-(k*u.y()+_point[0].y()))<precision &&
         fabs(p.z()-(k*u.z()+_point[0].z()))<precision) {
        return true;
      }
    }
    if(u.y()!=0.0) {
      k=(p.y()-_point[0].y())/u.y();
      if(fabs(p.x()-(k*u.x()+_point[0].x()))<precision &&
         fabs(p.z()-(k*u.z()+_point[0].z()))<precision) {
        return true;
      }
    }
    if(u.z()!=0.0) {
      k=(p.z()-_point[0].z())/u.z();
      if(fabs(p.x()-(k*u.x()+_point[0].x()))<precision &&
         fabs(p.y()-(k*u.y()+_point[0].y()))<precision) {
        return true;
      }
    }
    return false;
  }
bool QGpCoreTools::Segment::intersects ( const Segment seg,
Point p 
) const

Returns true if this segment intersects segment seg. The intersection point is returned in p.

References QGpCoreTools::Parallelepiped::includes(), TRACE, QGpCoreTools::Point2D::x(), QGpCoreTools::Point2D::y(), and QGpCoreTools::Point::z().

  {
    TRACE;
    Point u1=_point[1];
    u1-=_point[0];
    Point u2=seg._point[1];
    u2-=seg._point[0];
    double d, k;
    d=u2.x()*u1.y()-u2.y()*u1.x();
    if(d!=0.0) {
      k=(u1.x()*(seg._point[0].y()-_point[0].y())-u1.y()*(seg._point[0].x()-_point[0].x()))/d;
      p=u2*k+seg._point[0];
    } else {
      d=u2.x()*u1.z()-u2.z()*u1.x();
      if(d!=0.0) {
        k=(u1.x()*(seg._point[0].z()-_point[0].z())-u1.z()*(seg._point[0].x()-_point[0].x()))/d;
        p=u2*k+seg._point[0];
      } else {
        d=u2.y()*u1.z()-u2.z()*u1.y();
        if(d!=0.0) {
          k=(u1.y()*(seg._point[0].z()-_point[0].z())-u1.z()*(seg._point[0].y()-_point[0].y()))/d;
          p=u2*k+seg._point[0];
        } else {
          return false;
        }
      }
    }
    if(_limits.includes(p) && seg._limits.includes(p)) return true;
    else return false;
  }
bool QGpCoreTools::Segment::isSimilar ( const Segment o,
double  precision 
) const

References QGpCoreTools::Point::isSimilar().

Referenced by distanceTo().

  {
    return (_point[0].isSimilar(o._point[0], precision) &&
            _point[1].isSimilar(o._point[1], precision)) ||
           (_point[0].isSimilar(o._point[1], precision) &&
            _point[1].isSimilar(o._point[0], precision));
  }
double QGpCoreTools::Segment::length ( ) const [inline]

Referenced by distanceTo().

{return _point[0].distanceTo(_point[1]);}
bool QGpCoreTools::Segment::operator< ( const Segment o) const
  {
    if(_point[0]<o._point[0]) {
      return true;
    } else if(_point[0]>o._point[0]) {
      return false;
    } else {
      return _point[1]<o._point[1];
    }
  }
bool QGpCoreTools::Segment::parallelTo ( const Segment o) const

References directionVector(), and QGpCoreTools::Point::isSimilar().

Referenced by distanceTo().

  {
    Point u=directionVector();
    Point v=o.directionVector();
    return u.isSimilar(v, 1e-5) || u.isSimilar(v*-1, 1e-5);
  }
Point QGpCoreTools::Segment::point ( int  index) const [inline]

Referenced by QGpCoreTools::Matrix4x4::operator*().

{return _point[index];}
void QGpCoreTools::Segment::set ( const Point p1,
const Point p2 
)

References QGpCoreTools::Parallelepiped::setLimits(), TRACE, QGpCoreTools::Point2D::x(), QGpCoreTools::Point2D::y(), and QGpCoreTools::Point::z().

  {
    TRACE;
    _point[0]=p1;
    _point[1]=p2;
    _limits.setLimits(p1.x(), p1.y(), p1.z(),
                      p2.x(), p2.y(), p2.z());
  }
void QGpCoreTools::Segment::set ( double  x1,
double  y1,
double  z1,
double  x2,
double  y2,
double  z2 
)

References QGpCoreTools::Parallelepiped::setLimits(), and TRACE.

  {
    TRACE;
    _point[0]=Point(x1, y1, z1);
    _point[1]=Point(x2, y2, z2);
    _limits.setLimits(x1, y1, z1, x2, y2, z2);
  }

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines