911124
911124
#include <tools assistant.h=""></tools>
911124
9cf8be
#include <tgl.h></tgl.h>
9cf8be
911124
#include <limits></limits>
911124
911124
911124
//************************************************************************
911124
//    TGuideline implementation
911124
//************************************************************************
911124
4df9cd
void
4df9cd
TGuideline::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, bool active) const {
4df9cd
  double colorBlack[4] = { 0.0, 0.0, 0.0, 0.5 };
4df9cd
  double colorWhite[4] = { 1.0, 1.0, 1.0, 0.5 };
4df9cd
  if (!active) colorBlack[3] = (colorWhite[3] *= 0.5);
4df9cd
4df9cd
  glPushAttrib(GL_ALL_ATTRIB_BITS);
4df9cd
  tglEnableBlending();
4df9cd
  tglEnableLineSmooth(true, 0.5);
4df9cd
  TPointD d = p1 - p0;
4df9cd
  double k = norm2(d);
4df9cd
  if (k > TConsts::epsilon*TConsts::epsilon) {
249386
    k = 0.5*pixelSize/sqrt(k);
4df9cd
    d = TPointD(-k*d.y, k*d.x);
4df9cd
    glColor4dv(colorWhite);
4df9cd
    tglDrawSegment(p0 - d, p1 - d);
4df9cd
    glColor4dv(colorBlack);
4df9cd
    tglDrawSegment(p0 + d, p1 + d);
4df9cd
  }
4df9cd
  glPopAttrib();
4df9cd
}
4df9cd
4df9cd
//---------------------------------------------------------------------------------------------------
4df9cd
911124
double
9cf8be
TGuideline::calcTrackWeight(const TTrack &track, const TAffine &toScreen, bool &outLongEnough) const {
9cf8be
  outLongEnough = false;
9cf8be
  if (track.size() < 2)
911124
    return std::numeric_limits<double>::infinity();</double>
911124
911124
  const double snapLenght = 20.0;
911124
  const double snapScale = 1.0;
362052
  const double maxLength = 2.0*snapLenght*snapScale;
911124
911124
  double sumWeight = 0.0;
911124
  double sumLength = 0.0;
911124
  double sumDeviation = 0.0;
911124
9cf8be
  TPointD prev = toScreen*track[0].position;
911124
  for(int i = 0; i < track.size(); ++i) {
911124
    const TTrackPoint &tp = track[i];
9cf8be
    TPointD p = toScreen*tp.position;
911124
    double length = tdistance(p, prev);
911124
    sumLength += length;
911124
911124
    double midStepLength = sumLength - 0.5*length;
9f0c16
    if (midStepLength > TConsts::epsilon) {
911124
      double weight = length*logNormalDistribuitionUnscaled(midStepLength, snapLenght, snapScale);
911124
      sumWeight += weight;
911124
911124
      TTrackPoint ntp = transformPoint(tp);
9cf8be
      double deviation = tdistance(toScreen*ntp.position, p);
911124
      sumDeviation += weight*deviation;
911124
    }
911124
    prev = p;
9cf8be
9cf8be
    if (sumLength >= maxLength)
9cf8be
      { outLongEnough = true; break; }
911124
  }
9f0c16
  return sumWeight > TConsts::epsilon
9cf8be
       ? sumDeviation/sumWeight
9cf8be
       : std::numeric_limits<double>::infinity();</double>
911124
}
911124
911124
//---------------------------------------------------------------------------------------------------
911124
911124
TGuidelineP
9cf8be
TGuideline::findBest(const TGuidelineList &guidelines, const TTrack &track, const TAffine &toScreen, bool &outLongEnough) {
9cf8be
  outLongEnough = true;
911124
  double bestWeight = 0.0;
911124
  TGuidelineP best;
911124
  for(TGuidelineList::const_iterator i = guidelines.begin(); i != guidelines.end(); ++i) {
9cf8be
    double weight = (*i)->calcTrackWeight(track, toScreen, outLongEnough);
911124
    if (!best || weight < bestWeight)
911124
      { bestWeight = weight; best = *i; }
911124
  }
911124
  return best;
911124
}
911124
911124
911124
//************************************************************************
249386
//    TAssistantPoint implementation
249386
//************************************************************************
249386
249386
TAssistantPoint::TAssistantPoint(
249386
  Type type,
249386
  const TPointD &position
249386
):
249386
  type(type),
249386
  position(position),
249386
  radius(10.0),
249386
  selected() { }
249386
249386
//---------------------------------------------------------------------------------------------------
249386
249386
TAssistantPoint::TAssistantPoint(
249386
  Type type,
249386
  const TPointD &position,
249386
  double radius
249386
):
249386
  type(type),
249386
  position(position),
249386
  radius(radius),
249386
  selected() { }
249386
249386
249386
//************************************************************************
911124
//    TAssistant implementation
911124
//************************************************************************
911124
9cf8be
TAssistant::TAssistant(TMetaObject &object):
9cf8be
  TMetaObjectHandler(object),
9cf8be
  m_idPoints("points"),
9cf8be
  m_idX("x"),
9cf8be
  m_idY("y")
9cf8be
{ }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
const TPointD&
9cf8be
TAssistant::blank() {
9cf8be
  static TPointD point;
9cf8be
  return point;
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
249386
TAssistant::fixPoints()
9cf8be
  { onFixPoints(); }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::movePoint(int index, const TPointD &position)
9cf8be
  { if (index >= 0 && index < (int)m_points.size()) onMovePoint(index, position); }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
249386
TAssistant::setPointSelection(int index, bool selected)  const {
9cf8be
  if (index >= 0 && index < pointsCount())
9cf8be
    m_points[index].selected = selected;
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::onDataChanged(const TVariant &value) {
9cf8be
  const TVariant& pointsData = data()[m_idPoints];
9cf8be
  TVariantPathEntry entry;
9cf8be
9cf8be
  if (&value == &data() || &value == &pointsData)
9cf8be
    onAllDataChanged();
9cf8be
  else
9cf8be
  if (pointsData.getChildPathEntry(value, entry) && entry.isIndex()) {
9cf8be
    const TVariant& pointData = pointsData[entry];
9cf8be
    TPointD position = TPointD(
9cf8be
      pointData[m_idX].getDouble(),
9cf8be
      pointData[m_idY].getDouble() );
9cf8be
    movePoint(entry.index(), position);
9cf8be
  }
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::onAllDataChanged() {
9cf8be
  const TVariant& pointsData = data()[m_idPoints];
9cf8be
  for(int i = 0; i < pointsCount(); ++i) {
9cf8be
    const TVariant& pointData = pointsData[i];
9cf8be
    m_points[i].position = TPointD(
9cf8be
      pointData[m_idX].getDouble(),
9cf8be
      pointData[m_idY].getDouble() );
9cf8be
  }
249386
  fixPoints();
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::onFixPoints()
9cf8be
  { }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::onMovePoint(int index, const TPointD &position)
9cf8be
  { m_points[index].position = position; }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::onFixData() {
9cf8be
  TVariant& pointsData = data()[m_idPoints];
9cf8be
  for(int i = 0; i < pointsCount(); ++i) {
9cf8be
    TVariant& pointData = pointsData[i];
9cf8be
    pointData[m_idX].setDouble( m_points[i].position.x );
9cf8be
    pointData[m_idY].setDouble( m_points[i].position.y );
9cf8be
  }
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
4df9cd
TAssistant::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize) const {
4df9cd
  double colorBlack[4] = { 0.0, 0.0, 0.0, 0.5 };
4df9cd
  double colorWhite[4] = { 1.0, 1.0, 1.0, 0.5 };
4df9cd
4df9cd
  glPushAttrib(GL_ALL_ATTRIB_BITS);
4df9cd
  tglEnableBlending();
4df9cd
  tglEnableLineSmooth(true, 0.5);
4df9cd
  TPointD d = p1 - p0;
4df9cd
  double k = norm2(d);
4df9cd
  if (k > TConsts::epsilon*TConsts::epsilon) {
362052
    k = 0.5*pixelSize/sqrt(k);
4df9cd
    d = TPointD(-k*d.y, k*d.x);
4df9cd
    glColor4dv(colorWhite);
4df9cd
    tglDrawSegment(p0 - d, p1 - d);
4df9cd
    glColor4dv(colorBlack);
4df9cd
    tglDrawSegment(p0 + d, p1 + d);
4df9cd
  }
4df9cd
  glPopAttrib();
4df9cd
}
4df9cd
4df9cd
//---------------------------------------------------------------------------------------------------
4df9cd
4df9cd
void
9cf8be
TAssistant::drawPoint(const TAssistantPoint &point, double pixelSize) const {
249386
  double radius = point.radius;
9cf8be
  double crossSize = 1.2*radius;
9cf8be
9cf8be
  double colorBlack[4] = { 0.0, 0.0, 0.0, 0.5 };
9cf8be
  double colorGray[4]  = { 0.5, 0.5, 0.5, 0.5 };
9cf8be
  double colorWhite[4] = { 1.0, 1.0, 1.0, 0.5 };
249386
  double width = 0.5;
9cf8be
9cf8be
  if (point.selected) {
9cf8be
    colorBlack[2] = 1.0;
9cf8be
    colorGray[2] = 1.0;
249386
    width = 2.0;
9cf8be
  }
9cf8be
9cf8be
  glPushAttrib(GL_ALL_ATTRIB_BITS);
9cf8be
249386
  // fill
9cf8be
  tglEnableBlending();
9cf8be
  if (point.type == TAssistantPoint::CircleFill) {
9cf8be
    glColor4dv(colorGray);
9cf8be
    tglDrawDisk(point.position, radius*pixelSize);
9cf8be
  }
9cf8be
249386
  TPointD crossDx(pixelSize*crossSize, 0.0);
249386
  TPointD crossDy(0.0, pixelSize*crossSize);
9cf8be
249386
  // back line
249386
  tglEnableLineSmooth(true, 2.0*std::max(1.0, width));
249386
  glColor4dv(colorWhite);
249386
  if (point.type == TAssistantPoint::CircleCross) {
249386
    tglDrawSegment(point.position - crossDx, point.position + crossDx);
249386
    tglDrawSegment(point.position - crossDy, point.position + crossDy);
9cf8be
  }
249386
  tglDrawCircle(point.position, radius*pixelSize);
9cf8be
249386
  // front line
249386
  glLineWidth(width);
9cf8be
  glColor4dv(colorBlack);
249386
  if (point.type == TAssistantPoint::CircleCross) {
249386
    tglDrawSegment(point.position - crossDx, point.position + crossDx);
249386
    tglDrawSegment(point.position - crossDy, point.position + crossDy);
249386
  }
249386
  tglDrawCircle(point.position, radius*pixelSize);
9cf8be
9cf8be
  glPopAttrib();
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const
9cf8be
  { }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::draw(TToolViewer *viewer) const
9cf8be
  { }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
9cf8be
TAssistant::drawEdit(TToolViewer *viewer) const {
9cf8be
  // paint all points
4df9cd
  draw(viewer);
9cf8be
  double pixelSize = sqrt(tglGetPixelSize2());
9cf8be
  for(int i = 0; i < pointsCount(); ++i)
9cf8be
    drawPoint(m_points[i], pixelSize);
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------