Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
Ivan Mahonin d5090c
#include <tools/assistants/guidelineline.h>
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
// TnzCore includes
Ivan Mahonin 4df9cd
#include "tgl.h"
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
//    TGuidelineLineBase implementation
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
Ivan Mahonin 8074a5
TGuidelineLineBase::TGuidelineLineBase(bool enabled, double magnetism, const TPointD &p0, const TPointD &p1):
Ivan Mahonin 8074a5
  TGuideline(enabled, magnetism), p0(p0), p1(p1) { }
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
TPointD
Ivan Mahonin 4df9cd
TGuidelineLineBase::calcDirection(const TPointD &p0, const TPointD &p1) {
Ivan Mahonin 4df9cd
  TPointD d = p1 - p0;
Ivan Mahonin 4df9cd
  double k = norm2(d);
Ivan Mahonin 362052
  return k > TConsts::epsilon*TConsts::epsilon ? d*(1.0/sqrt(k)) : TPointD();
Ivan Mahonin 4df9cd
}
Ivan Mahonin 4df9cd
Ivan Mahonin c7854d
Ivan Mahonin c7854d
static bool
Ivan Mahonin 3f8ca2
fitX(double &x0, double &y0, double &x1, double &y1, double minx, double maxx) {
Ivan Mahonin c7854d
  double dx = x1 - x0;
Ivan Mahonin c7854d
  if (fabs(dx) < TConsts::epsilon) return false;
Ivan Mahonin c7854d
  double k = (y1 - y0)/dx;
Ivan Mahonin c7854d
  if (dx > 0.0) {
Ivan Mahonin c7854d
    y0 += k*(minx - x0); x0 = minx;
Ivan Mahonin c7854d
    y1 += k*(maxx - x1); x1 = maxx;
Ivan Mahonin c7854d
  } else {
Ivan Mahonin c7854d
    y0 += k*(maxx - x0); x0 = maxx;
Ivan Mahonin c7854d
    y1 += k*(minx - x1); x1 = minx;
Ivan Mahonin c7854d
  }
Ivan Mahonin c7854d
  return true;
Ivan Mahonin c7854d
}
Ivan Mahonin c7854d
Ivan Mahonin 3f8ca2
static bool
Ivan Mahonin 3f8ca2
truncateX(double &x0, double &y0, double &x1, double &y1, double minx, double maxx) {
Ivan Mahonin 3f8ca2
  if (x0 <= minx && x1 <= minx) return false;
Ivan Mahonin 3f8ca2
  if (x0 >= maxx && x1 >= maxx) return false;
Ivan Mahonin 3f8ca2
  double dx = x1 - x0;
Ivan Mahonin 3f8ca2
  if (fabs(dx) < TConsts::epsilon) return true;
Ivan Mahonin 3f8ca2
  double k = (y1 - y0)/dx;
Ivan Mahonin 3f8ca2
  if (dx > 0.0) {
Ivan Mahonin 3f8ca2
    if (x0 < minx) { y0 += k*(minx - x0); x0 = minx; }
Ivan Mahonin 3f8ca2
    if (x1 > maxx) { y1 += k*(maxx - x1); x1 = maxx; }
Ivan Mahonin 3f8ca2
  } else {
Ivan Mahonin 3f8ca2
    if (x0 > maxx) { y0 += k*(maxx - x0); x0 = maxx; }
Ivan Mahonin 3f8ca2
    if (x1 < minx) { y1 += k*(minx - x1); x1 = minx; }
Ivan Mahonin 3f8ca2
  }
Ivan Mahonin 3f8ca2
  return true;
Ivan Mahonin 3f8ca2
}
Ivan Mahonin 3f8ca2
Ivan Mahonin c7854d
bool
Ivan Mahonin 4df9cd
TGuidelineLineBase::truncateInfiniteLine(const TRectD &bounds, TPointD &p0, TPointD &p1) {
Ivan Mahonin c7854d
  if (bounds.isEmpty()) return false;
Ivan Mahonin 4df9cd
  TPointD d = p0 - p1;
Ivan Mahonin 4df9cd
  TDimensionD size = bounds.getSize();
Ivan Mahonin 7c7225
  if (fabs(d.x)*size.ly > fabs(d.y)*size.lx) {
Ivan Mahonin 4df9cd
    // horizontal
Ivan Mahonin 3f8ca2
    if (!fitX     (p0.x, p0.y, p1.x, p1.y, bounds.x0, bounds.x1)) return false;
Ivan Mahonin 3f8ca2
    if (!truncateX(p0.y, p0.x, p1.y, p1.x, bounds.y0, bounds.y1)) return false;
Ivan Mahonin 4df9cd
  } else {
Ivan Mahonin 4df9cd
    // vertical
Ivan Mahonin 3f8ca2
    if (!fitX     (p0.y, p0.x, p1.y, p1.x, bounds.y0, bounds.y1)) return false;
Ivan Mahonin 3f8ca2
    if (!truncateX(p0.x, p0.y, p1.x, p1.y, bounds.x0, bounds.x1)) return false;
Ivan Mahonin c7854d
  }
Ivan Mahonin c7854d
  return true;
Ivan Mahonin c7854d
}
Ivan Mahonin c7854d
Ivan Mahonin c7854d
bool
Ivan Mahonin 7c7225
TGuidelineLineBase::truncateRay(const TRectD &bounds, TPointD &p0, TPointD &p1) {
Ivan Mahonin c7854d
  if (bounds.isEmpty()) return false;
Ivan Mahonin c7854d
  TRectD b(bounds);
Ivan Mahonin 7c7225
Ivan Mahonin 7c7225
  if (p0.x <= p1.x) { if (b.x0 < p0.x) b.x0 = p0.x; }
Ivan Mahonin 7c7225
               else { if (b.x1 > p0.x) b.x1 = p0.x; }
Ivan Mahonin 7c7225
  if (p0.y <= p1.y) { if (b.y0 < p0.y) b.y0 = p0.y; }
Ivan Mahonin 7c7225
               else { if (b.y1 > p0.y) b.y1 = p0.y; }
Ivan Mahonin 7c7225
Ivan Mahonin 7c7225
  if (b.isEmpty()) return false;
Ivan Mahonin 7c7225
  return truncateInfiniteLine(b, p0, p1);
Ivan Mahonin 7c7225
}
Ivan Mahonin 7c7225
Ivan Mahonin 7c7225
bool
Ivan Mahonin 7c7225
TGuidelineLineBase::truncateLine(const TRectD &bounds, TPointD &p0, TPointD &p1) {
Ivan Mahonin 7c7225
  TRectD b = bounds * boundingBox(p0, p1);
Ivan Mahonin 3f8ca2
  if (b.isEmpty()) return false;
Ivan Mahonin c7854d
  return truncateInfiniteLine(b, p0, p1);
Ivan Mahonin 4df9cd
}
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
void
Ivan Mahonin 7c7225
TGuidelineLineBase::drawLine(const TPointD &p0, const TPointD &p1, bool restrict0, bool restrict1, bool active, bool enabled) const {
Ivan Mahonin 249386
  TAffine4 modelview, projection;
Ivan Mahonin 4df9cd
  glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
Ivan Mahonin 249386
  glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
Ivan Mahonin 4df9cd
Ivan Mahonin 249386
  TAffine matrix = (projection*modelview).get2d();
Ivan Mahonin 4df9cd
  TPointD pp0 = matrix*p0;
Ivan Mahonin 4df9cd
  TPointD pp1 = matrix*p1;
Ivan Mahonin 7c7225
  const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
Ivan Mahonin 7c7225
  if ( restrict0 && restrict1 ? !truncateLine(oneBox, pp0, pp1)
Ivan Mahonin 7c7225
     : restrict0              ? !truncateRay (oneBox, pp0, pp1)
Ivan Mahonin 7c7225
     : restrict1              ? !truncateRay (oneBox, pp1, pp0) // pp1 first
Ivan Mahonin 7c7225
     :                  !truncateInfiniteLine(oneBox, pp0, pp1) ) return;
Ivan Mahonin 4df9cd
Ivan Mahonin 249386
  double pixelSize = sqrt(tglGetPixelSize2());
Ivan Mahonin 4df9cd
  TAffine matrixInv = matrix.inv();
Ivan Mahonin c7854d
  drawSegment(matrixInv*pp0, matrixInv*pp1, pixelSize, active, enabled);
Ivan Mahonin 4df9cd
}
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
//    TGuidelineLine implementation
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
Ivan Mahonin 8074a5
TGuidelineLine::TGuidelineLine(bool enabled, double magnetism, const TPointD &p0, const TPointD &p1):
Ivan Mahonin 8074a5
  TGuidelineLineBase(enabled, magnetism, p0, p1),
Ivan Mahonin 4df9cd
  dir(calcDirection(p0, p1)),
Ivan Mahonin 4df9cd
  dist(norm(p1 - p0)) { }
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
TTrackPoint
Ivan Mahonin 4df9cd
TGuidelineLine::transformPoint(const TTrackPoint &point) const {
Ivan Mahonin 4df9cd
  TTrackPoint p(point);
Ivan Mahonin 4df9cd
  p.position = p0 + dir * std::max(0.0, std::min(dist, ((p.position - p0)*dir)));
Ivan Mahonin 4df9cd
  return p;
Ivan Mahonin 4df9cd
}
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
void
Ivan Mahonin 8074a5
TGuidelineLine::draw(bool active, bool enabled) const
Ivan Mahonin 7c7225
  { drawLine(p0, p1, true, true, active, enabled); }
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
//    TGuidelineInfiniteLine implementation
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
Ivan Mahonin 8074a5
TGuidelineInfiniteLine::TGuidelineInfiniteLine(bool enabled, double magnetism, const TPointD &p0, const TPointD &p1):
Ivan Mahonin 8074a5
  TGuidelineLineBase(enabled, magnetism, p0, p1),
Ivan Mahonin 4df9cd
  dir(calcDirection(p0, p1)) { }
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
TTrackPoint
Ivan Mahonin 4df9cd
TGuidelineInfiniteLine::transformPoint(const TTrackPoint &point) const {
Ivan Mahonin 4df9cd
  TTrackPoint p(point);
Ivan Mahonin 4df9cd
  p.position = p0 + dir * ((p.position - p0)*dir);
Ivan Mahonin 4df9cd
  return p;
Ivan Mahonin 4df9cd
}
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
void
Ivan Mahonin 8074a5
TGuidelineInfiniteLine::draw(bool active, bool enabled) const
Ivan Mahonin 7c7225
  { drawLine(p0, p1, false, false, active, enabled); }
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
//    TGuidelineRay implementation
Ivan Mahonin 4df9cd
//*****************************************************************************************
Ivan Mahonin 4df9cd
Ivan Mahonin 8074a5
TGuidelineRay::TGuidelineRay(bool enabled, double magnetism, const TPointD &p0, const TPointD &p1):
Ivan Mahonin 8074a5
  TGuidelineLineBase(enabled, magnetism, p0, p1),
Ivan Mahonin 4df9cd
  dir(calcDirection(p0, p1)) { }
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
TTrackPoint
Ivan Mahonin 4df9cd
TGuidelineRay::transformPoint(const TTrackPoint &point) const {
Ivan Mahonin 4df9cd
  TTrackPoint p(point);
Ivan Mahonin 4df9cd
  p.position = p0 + dir * std::max(0.0, ((p.position - p0)*dir));
Ivan Mahonin 4df9cd
  return p;
Ivan Mahonin 4df9cd
}
Ivan Mahonin 4df9cd
Ivan Mahonin 4df9cd
void
Ivan Mahonin 8074a5
TGuidelineRay::draw(bool active, bool enabled) const
Ivan Mahonin 7c7225
  { drawLine(p0, p1, true, false, active, enabled); }
Ivan Mahonin 4df9cd