Blob Blame Raw


#include "guidelineline.h"

// TnzTools includes
#include <tools/assistant.h>

// TnzCore includes
#include <tgl.h>


//*****************************************************************************************
//    TAssistantVanishingPoint implementation
//*****************************************************************************************

class DVAPI TAssistantVanishingPoint final : public TAssistant {
  Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint)
public:
  const TStringId m_idPassThrough;
  const TStringId m_idGrid;
  const TStringId m_idPerspective;

protected:
  TAssistantPoint &m_center;
  TAssistantPoint &m_a0;
  TAssistantPoint &m_a1;
  TAssistantPoint &m_b0;
  TAssistantPoint &m_b1;
  TAssistantPoint &m_grid0;
  TAssistantPoint &m_grid1;

public:
  TAssistantVanishingPoint(TMetaObject &object):
    TAssistant(object),
    m_idPassThrough("passThrough"),
    m_idGrid("grid"),
    m_idPerspective("perspective"),
    m_center( addPoint("center", TAssistantPoint::CircleCross) ),
    m_a0    ( addPoint("A0",     TAssistantPoint::Circle, TPointD(-50.0, 0.0)) ),
    m_a1    ( addPoint("A1",     TAssistantPoint::Circle, TPointD(-75.0, 0.0)) ),
    m_b0    ( addPoint("B0",     TAssistantPoint::Circle, TPointD( 50.0, 0.0)) ),
    m_b1    ( addPoint("B1",     TAssistantPoint::Circle, TPointD( 75.0, 0.0)) ),
    m_grid0 ( addPoint("grid0",  TAssistantPoint::CircleGrid) ),
    m_grid1 ( addPoint("grid1",  TAssistantPoint::CircleGrid) )
  {
    addProperty( new TBoolProperty(m_idPassThrough.str(), getPassThrough()) );
    addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) );
    addProperty( new TBoolProperty(m_idPerspective.str(), getPerspective()) );
  }

  static QString getLocalName()
    { return tr("Vanishing Point"); }

  void updateTranslation() const {
    setTranslation(m_idPassThrough, tr("Pass Through"));
    setTranslation(m_idGrid, tr("Grid"));
    setTranslation(m_idPerspective, tr("Perspective"));
  }


  inline bool getPassThrough() const
    { return data()[m_idPassThrough].getBool(); }
  inline bool getGrid() const
    { return data()[m_idGrid].getBool(); }
  inline bool getPerspective() const
    { return data()[m_idPerspective].getBool(); }

  void onDataChanged(const TVariant &value) {
    TAssistant::onDataChanged(value);
    m_grid0.visible = m_grid1.visible = ((const TVariant&)data())[m_idGrid].getBool();
  }

private:
  void fixCenter() {
    if ( !(m_a0.position == m_a1.position)
      && !(m_b0.position == m_b1.position) )
    {
      const TPointD &a = m_a0.position;
      const TPointD &b = m_b0.position;
      const TPointD da = m_a1.position - a;
      const TPointD db = m_b1.position - b;
      const TPointD ab = b - a;
      double k = db.x*da.y - db.y*da.x;
      if (fabs(k) > TConsts::epsilon) {
        double lb = (da.x*ab.y - da.y*ab.x)/k;
        m_center.position.x = lb*db.x + b.x;
        m_center.position.y = lb*db.y + b.y;
      }
    }
  }

  void fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1, TPointD previousP0) {
    if (p0.position != m_center.position && p0.position != p1.position) {
      TPointD dp0 = p0.position - m_center.position;
      TPointD dp1 = p1.position - previousP0;
      double l0 = norm(dp0);
      double l1 = norm(dp1);
      if (l0 > TConsts::epsilon && l0 + l1 > TConsts::epsilon)
        p1.position = m_center.position + dp0*((l0 + l1)/l0);
    }
  }

  void fixSidePoint(TAssistantPoint &p0, TAssistantPoint &p1)
    { fixSidePoint(p0, p1, p0.position); }

public:
  void onFixPoints() override {
    fixSidePoint(m_a0, m_a1);
    fixSidePoint(m_b0, m_b1);
    fixCenter();
  }

  void onMovePoint(TAssistantPoint &point, const TPointD &position) override {
    if (&point == &getBasePoint())
      { move(position); return; }

    TPointD previous = point.position;
    point.position = position;
    if (&point == &m_a0) {
      fixSidePoint(m_a0, m_a1, previous);
      fixSidePoint(m_b0, m_b1);
    } else
    if (&point == &m_b0) {
      fixSidePoint(m_a0, m_a1);
      fixSidePoint(m_b0, m_b1, previous);
    } else
    if (&point == &m_a1) {
      fixCenter();
      fixSidePoint(m_a0, m_a1);
      fixSidePoint(m_b0, m_b1);
    } else
    if (&point == &m_b1) {
      fixCenter();
      fixSidePoint(m_b0, m_b1);
      fixSidePoint(m_a0, m_a1);
    }
  }

  void getGuidelines(
    const TPointD &position,
    const TAffine &toTool,
    TGuidelineList &outGuidelines ) const override
  {
    if (getPassThrough()) {
      outGuidelines.push_back(TGuidelineP(
        new TGuidelineInfiniteLine(
          getEnabled(),
          getMagnetism(),
          toTool * m_center.position,
          position )));
    } else {
      outGuidelines.push_back(TGuidelineP(
        new TGuidelineRay(
          getEnabled(),
          getMagnetism(),
          toTool * m_center.position,
          position )));
    }
  }

  void draw(TToolViewer *viewer, bool enabled) const override {
    double pixelSize = sqrt(tglGetPixelSize2());
    const TPointD &p = m_center.position;
    TPointD dx(20.0*pixelSize, 0.0);
    TPointD dy(0.0, 10.0*pixelSize);
    drawSegment(p-dx-dy, p+dx+dy, pixelSize, enabled);
    drawSegment(p-dx+dy, p+dx-dy, pixelSize, enabled);
  }

  void drawEdit(TToolViewer *viewer) const override {
    double pixelSize = sqrt(tglGetPixelSize2());
    drawSegment(m_center.position, m_a1.position, pixelSize);
    drawSegment(m_center.position, m_b1.position, pixelSize);
    drawDot(m_a0.position);
    drawDot(m_a1.position);
    drawDot(m_b0.position);
    drawDot(m_b1.position);
    TAssistant::drawEdit(viewer);
  }
};


//*****************************************************************************************
//    Registration
//*****************************************************************************************

static TAssistantTypeT<TAssistantVanishingPoint> assistantVanishingPoint("assistantVanishingPoint");