|
|
166af2 |
|
|
|
166af2 |
|
|
|
166af2 |
// TnzTools includes
|
|
|
d9135c |
#include "assistantline.h"
|
|
|
d5090c |
|
|
|
166af2 |
|
|
|
166af2 |
|
|
|
166af2 |
//*****************************************************************************************
|
|
|
166af2 |
// TAssistantLine implementation
|
|
|
166af2 |
//*****************************************************************************************
|
|
|
166af2 |
|
|
|
166af2 |
|
|
|
d9135c |
TAssistantLine::TAssistantLine(TMetaObject &object):
|
|
|
d9135c |
TAssistant(object),
|
|
|
d9135c |
m_idRestricktA("restrictA"),
|
|
|
d9135c |
m_idRestricktB("restrictB"),
|
|
|
d9135c |
m_idParallel("parallel"),
|
|
|
d9135c |
m_idGrid("grid"),
|
|
|
d9135c |
m_idPerspective("perspective"),
|
|
|
d9135c |
m_a( addPoint("a", TAssistantPoint::CircleCross) ),
|
|
|
d9135c |
m_b( addPoint("b", TAssistantPoint::Circle, TPointD(100.0, 0.0)) ),
|
|
|
d9135c |
m_grid0( addPoint("grid0", TAssistantPoint::CircleDoubleDots, TPointD( 0.0,-50.0)) ),
|
|
|
d9135c |
m_grid1( addPoint("grid1", TAssistantPoint::CircleDots, TPointD( 25.0,-75.0)) )
|
|
|
d9135c |
{
|
|
|
d9135c |
addProperty( new TBoolProperty(m_idRestricktA.str(), getRestrictA()) );
|
|
|
d9135c |
addProperty( new TBoolProperty(m_idRestricktB.str(), getRestrictB()) );
|
|
|
d9135c |
addProperty( new TBoolProperty(m_idParallel.str(), getParallel()) );
|
|
|
d9135c |
addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) );
|
|
|
d9135c |
addProperty( new TBoolProperty(m_idPerspective.str(), getPerspective()) );
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
QString TAssistantLine::getLocalName()
|
|
|
d9135c |
{ return tr("Line"); }
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::updateTranslation() const {
|
|
|
d9135c |
TAssistant::updateTranslation();
|
|
|
d9135c |
setTranslation(m_idRestricktA, tr("Restrict A"));
|
|
|
d9135c |
setTranslation(m_idRestricktB, tr("Restrict B"));
|
|
|
d9135c |
setTranslation(m_idParallel, tr("Parallel"));
|
|
|
d9135c |
setTranslation(m_idGrid, tr("Grid"));
|
|
|
d9135c |
setTranslation(m_idPerspective, tr("Perspective"));
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::onDataChanged(const TVariant &value) {
|
|
|
d9135c |
TAssistant::onDataChanged(value);
|
|
|
d9135c |
m_grid0.visible = getGrid()
|
|
|
d9135c |
|| (getParallel() && (getRestrictA() || getRestrictB()));
|
|
|
d9135c |
m_grid1.visible = getGrid();
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::fixGrid(const TPointD &prevA, const TPointD &prevB) {
|
|
|
d9135c |
TPointD dx0 = prevB - prevA;
|
|
|
d9135c |
TPointD dx1 = m_b.position - m_a.position;
|
|
|
d9135c |
double l0 = norm2(dx0);
|
|
|
d9135c |
double l1 = norm2(dx1);
|
|
|
d9135c |
if (!( l0 > TConsts::epsilon*TConsts::epsilon
|
|
|
d9135c |
&& l1 > TConsts::epsilon*TConsts::epsilon )) return;
|
|
|
d9135c |
dx0 *= 1/sqrt(l0);
|
|
|
d9135c |
dx1 *= 1/sqrt(l1);
|
|
|
d9135c |
TPointD dy0(-dx0.y, dx0.x);
|
|
|
d9135c |
TPointD dy1(-dx1.y, dx1.x);
|
|
|
d9135c |
|
|
|
d9135c |
if (getParallel()) {
|
|
|
166af2 |
TPointD g1 = m_grid1.position - m_grid0.position;
|
|
|
d9135c |
m_grid1.position = m_grid0.position + g1*dx0*dx1 + g1*dy0*dy1;
|
|
|
d9135c |
} else {
|
|
|
d9135c |
TPointD g0 = m_grid0.position - prevA;
|
|
|
d9135c |
TPointD g1 = m_grid1.position - prevA;
|
|
|
d9135c |
m_grid0.position = m_a.position + g0*dx0*dx1 + g0*dy0*dy1;
|
|
|
d9135c |
m_grid1.position = m_a.position + g1*dx0*dx1 + g1*dy0*dy1;
|
|
|
166af2 |
}
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::onMovePoint(TAssistantPoint &point, const TPointD &position) {
|
|
|
d9135c |
TPointD prevA = m_a.position;
|
|
|
d9135c |
TPointD prevB = m_b.position;
|
|
|
d9135c |
point.position = position;
|
|
|
de8863 |
if (&point == &m_a)
|
|
|
de8863 |
m_b.position += m_a.position - prevA;
|
|
|
d9135c |
if (&point != &m_grid1)
|
|
|
d9135c |
fixGrid(prevA, prevB);
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::getGuidelines(
|
|
|
d9135c |
const TPointD &position,
|
|
|
d9135c |
const TAffine &toTool,
|
|
|
d9135c |
TGuidelineList &outGuidelines ) const
|
|
|
d9135c |
{
|
|
|
d9135c |
bool restrictA = getRestrictA();
|
|
|
d9135c |
bool restrictB = getRestrictB();
|
|
|
d9135c |
bool parallel = getParallel();
|
|
|
d9135c |
bool perspective = getPerspective();
|
|
|
d9135c |
|
|
|
d9135c |
TPointD a = toTool*m_a.position;
|
|
|
d9135c |
TPointD b = toTool*m_b.position;
|
|
|
d9135c |
TPointD ab = b - a;
|
|
|
d9135c |
double abLen2 = norm2(ab);
|
|
|
d9135c |
if (abLen2 < TConsts::epsilon*TConsts::epsilon) return;
|
|
|
d9135c |
|
|
|
d9135c |
if (parallel) {
|
|
|
d9135c |
TPointD abp = rotate90(ab);
|
|
|
d9135c |
TPointD ag = toTool*m_grid0.position - a;
|
|
|
d9135c |
double k = abp*ag;
|
|
|
d9135c |
if (fabs(k) <= TConsts::epsilon) {
|
|
|
d9135c |
if (restrictA || restrictB) return;
|
|
|
d9135c |
a = position;
|
|
|
d9135c |
} else {
|
|
|
d9135c |
k = (abp*(position - a))/k;
|
|
|
d9135c |
a = a + ag*k;
|
|
|
166af2 |
}
|
|
|
d9135c |
if (perspective && (restrictA || restrictB))
|
|
|
d9135c |
ab = ab*k;
|
|
|
d9135c |
b = a + ab;
|
|
|
166af2 |
}
|
|
|
166af2 |
|
|
|
d9135c |
if (restrictA && restrictB)
|
|
|
d9135c |
outGuidelines.push_back(TGuidelineP(
|
|
|
d9135c |
new TGuidelineLine(
|
|
|
d9135c |
getEnabled(), getMagnetism(), a, b )));
|
|
|
d9135c |
else if (restrictA)
|
|
|
d9135c |
outGuidelines.push_back(TGuidelineP(
|
|
|
d9135c |
new TGuidelineRay(
|
|
|
d9135c |
getEnabled(), getMagnetism(), a, b )));
|
|
|
d9135c |
else if (restrictB)
|
|
|
d9135c |
outGuidelines.push_back(TGuidelineP(
|
|
|
d9135c |
new TGuidelineRay(
|
|
|
d9135c |
getEnabled(), getMagnetism(), b, a ))); // b first
|
|
|
d9135c |
else
|
|
|
d9135c |
outGuidelines.push_back(TGuidelineP(
|
|
|
d9135c |
new TGuidelineInfiniteLine(
|
|
|
d9135c |
getEnabled(), getMagnetism(), a, b )));
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::drawRuler(
|
|
|
d9135c |
const TPointD &a,
|
|
|
d9135c |
const TPointD &b,
|
|
|
d9135c |
const TPointD &grid0,
|
|
|
d9135c |
const TPointD &grid1,
|
|
|
d9135c |
const TPointD *perspectiveBase,
|
|
|
d9135c |
double alpha )
|
|
|
d9135c |
{
|
|
|
d9135c |
double pixelSize = sqrt(tglGetPixelSize2());
|
|
|
d9135c |
double minStep = (perspectiveBase ? 5 : 10)*pixelSize;
|
|
|
d9135c |
|
|
|
d9135c |
TPointD direction = b - a;
|
|
|
d9135c |
double l2 = norm2(direction);
|
|
|
d9135c |
if (l2 <= TConsts::epsilon*TConsts::epsilon) return;
|
|
|
d9135c |
double dirLen = sqrt(l2);
|
|
|
d9135c |
TPointD dirProj = direction*(1.0/l2);
|
|
|
d9135c |
TPointD normal = TPointD(-direction.y, direction.x)*(1.0/dirLen);
|
|
|
d9135c |
|
|
|
d9135c |
double xg0 = dirProj*(grid0 - a);
|
|
|
d9135c |
double xg1 = dirProj*(grid1 - a);
|
|
|
d9135c |
|
|
|
d9135c |
if (perspectiveBase) {
|
|
|
d9135c |
// draw perspective
|
|
|
d9135c |
double xa0 = dirProj*(*perspectiveBase - a);
|
|
|
d9135c |
double w, i0, i1;
|
|
|
d9135c |
if (!calcPerspectiveStep(minStep/dirLen, 0, 1, xa0, xg0, xg1, w, i0, i1)) return;
|
|
|
d9135c |
for(double i = i0; i < i1; i += 1) {
|
|
|
d9135c |
double x = xa0 + 1/(i*w + 1);
|
|
|
d9135c |
drawMark(a + direction*x, normal, pixelSize, alpha);
|
|
|
166af2 |
}
|
|
|
d9135c |
} else {
|
|
|
d9135c |
// draw linear
|
|
|
d9135c |
double dx = fabs(xg1 - xg0);
|
|
|
d9135c |
if (dx*dirLen < minStep) return;
|
|
|
d9135c |
for(double x = xg0 - floor(xg0/dx)*dx; x < 1.0; x += dx)
|
|
|
d9135c |
drawMark(a + direction*x, normal, pixelSize, alpha);
|
|
|
d9135c |
}
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::drawLine(
|
|
|
d9135c |
const TAffine &matrix,
|
|
|
d9135c |
const TAffine &matrixInv,
|
|
|
d9135c |
double pixelSize,
|
|
|
d9135c |
const TPointD &a,
|
|
|
d9135c |
const TPointD &b,
|
|
|
d9135c |
bool restrictA,
|
|
|
d9135c |
bool restrictB,
|
|
|
d9135c |
double alpha )
|
|
|
d9135c |
{
|
|
|
d9135c |
const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
|
|
|
d9135c |
TPointD aa = matrix*a;
|
|
|
d9135c |
TPointD bb = matrix*b;
|
|
|
d9135c |
if ( restrictA && restrictB ? TGuidelineLineBase::truncateLine(oneBox, aa, bb)
|
|
|
d9135c |
: restrictA ? TGuidelineLineBase::truncateRay (oneBox, aa, bb)
|
|
|
d9135c |
: restrictB ? TGuidelineLineBase::truncateRay (oneBox, bb, aa) // aa first
|
|
|
d9135c |
: TGuidelineLineBase::truncateInfiniteLine(oneBox, aa, bb) )
|
|
|
d9135c |
drawSegment(matrixInv*aa, matrixInv*bb, pixelSize, alpha);
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::drawGrid(
|
|
|
d9135c |
const TPointD &a,
|
|
|
d9135c |
const TPointD &b,
|
|
|
d9135c |
const TPointD &grid0,
|
|
|
d9135c |
const TPointD &grid1,
|
|
|
d9135c |
bool restrictA,
|
|
|
d9135c |
bool restrictB,
|
|
|
d9135c |
bool perspective,
|
|
|
d9135c |
double alpha )
|
|
|
d9135c |
{
|
|
|
d9135c |
TAffine4 modelview, projection;
|
|
|
d9135c |
glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
|
|
|
d9135c |
glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
|
|
|
d9135c |
TAffine matrix = (projection*modelview).get2d();
|
|
|
d9135c |
TAffine matrixInv = matrix.inv();
|
|
|
d9135c |
double pixelSize = sqrt(tglGetPixelSize2());
|
|
|
d9135c |
double minStep = (perspective ? 2.5 : 10)*pixelSize;
|
|
|
d9135c |
|
|
|
d9135c |
TPointD ab = b - a;
|
|
|
d9135c |
double abLen2 = norm2(ab);
|
|
|
d9135c |
if (abLen2 < TConsts::epsilon*TConsts::epsilon) return;
|
|
|
d9135c |
double abLen = sqrt(abLen2);
|
|
|
d9135c |
|
|
|
d9135c |
TPointD abp = rotate90(ab);
|
|
|
d9135c |
TPointD ag = grid0 - a;
|
|
|
d9135c |
if (fabs(abp*ag) <= TConsts::epsilon) {
|
|
|
d9135c |
if (restrictA || restrictB) return;
|
|
|
d9135c |
ag = abp;
|
|
|
d9135c |
}
|
|
|
d9135c |
double agLen2 = norm2(ag);
|
|
|
d9135c |
if (agLen2 < TConsts::epsilon*TConsts::epsilon) return;
|
|
|
d9135c |
double abpAgK = 1.0/(abp*ag);
|
|
|
d9135c |
TPointD abpAgProj = abp*abpAgK;
|
|
|
d9135c |
|
|
|
d9135c |
// draw restriction lines
|
|
|
d9135c |
if (perspective) {
|
|
|
d9135c |
if (restrictA) drawLine(matrix, matrixInv, pixelSize, a, a + ag, false, false, alpha);
|
|
|
d9135c |
if (restrictB) drawLine(matrix, matrixInv, pixelSize, a, a + ag + ab, false, false, alpha);
|
|
|
d9135c |
// horizon
|
|
|
d9135c |
if (!restrictA) drawLine(matrix, matrixInv, pixelSize, a - ab, a, restrictA, restrictB, alpha); else
|
|
|
d9135c |
if (!restrictB) drawLine(matrix, matrixInv, pixelSize, a, a + ab, restrictA, restrictB, alpha);
|
|
|
d9135c |
} else {
|
|
|
d9135c |
if (restrictA) drawLine(matrix, matrixInv, pixelSize, a, a + ag, false, false, alpha);
|
|
|
d9135c |
if (restrictB) drawLine(matrix, matrixInv, pixelSize, b, b + ag, false, false, alpha);
|
|
|
166af2 |
}
|
|
|
166af2 |
|
|
|
d9135c |
double minStepX = fabs(minStep*abLen*abpAgK);
|
|
|
d9135c |
if (minStepX <= TConsts::epsilon) return;
|
|
|
d9135c |
|
|
|
d9135c |
// calculate bounds
|
|
|
d9135c |
const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
|
|
|
d9135c |
TPointD corners[4] = {
|
|
|
d9135c |
TPointD(oneBox.x0, oneBox.y0),
|
|
|
d9135c |
TPointD(oneBox.x0, oneBox.y1),
|
|
|
d9135c |
TPointD(oneBox.x1, oneBox.y0),
|
|
|
d9135c |
TPointD(oneBox.x1, oneBox.y1) };
|
|
|
d9135c |
double minX = 0.0, maxX = 0.0;
|
|
|
d9135c |
for(int i = 0; i < 4; ++i) {
|
|
|
d9135c |
double x = abpAgProj * (matrixInv*corners[i] - a);
|
|
|
d9135c |
if (i == 0 || x < minX) minX = x;
|
|
|
d9135c |
if (i == 0 || x > maxX) maxX = x;
|
|
|
166af2 |
}
|
|
|
d9135c |
if (maxX <= minX) return;
|
|
|
166af2 |
|
|
|
d9135c |
double x0 = abpAgProj*(grid0 - a);
|
|
|
d9135c |
double x1 = abpAgProj*(grid1 - a);
|
|
|
166af2 |
|
|
|
d9135c |
if (perspective) {
|
|
|
d9135c |
double w, i0, i1;
|
|
|
d9135c |
minStepX /= 2;
|
|
|
d9135c |
|
|
|
d9135c |
if (!calcPerspectiveStep(minStepX, minX, maxX, 0, x0, x1, w, i0, i1)) return;
|
|
|
d9135c |
double abk = 1.0/fabs(x0);
|
|
|
d9135c |
for(double i = i0; i < i1; i += 1) {
|
|
|
d9135c |
double x = 1/(i*w + 1);
|
|
|
d9135c |
|
|
|
d9135c |
double curStep = fabs(w*x*x);
|
|
|
d9135c |
double curAlpha = (curStep - minStepX)/minStepX;
|
|
|
d9135c |
if (curAlpha < 0) continue;
|
|
|
d9135c |
if (curAlpha > 1) curAlpha = 1;
|
|
|
d9135c |
|
|
|
d9135c |
TPointD ca = a + ag*x;
|
|
|
d9135c |
TPointD cb = ca + ab*(abk*x);
|
|
|
d9135c |
drawLine(matrix, matrixInv, pixelSize, ca, cb, restrictA, restrictB, alpha*curAlpha);
|
|
|
166af2 |
}
|
|
|
d9135c |
} else {
|
|
|
d9135c |
double dx = fabs(x1 - x0);
|
|
|
d9135c |
if (dx < minStepX) return;
|
|
|
d9135c |
for(double x = x0 + ceil((minX - x0)/dx)*dx; x < maxX; x += dx) {
|
|
|
d9135c |
TPointD ca = a + ag*x;
|
|
|
d9135c |
drawLine(matrix, matrixInv, pixelSize, ca, ca + ab, restrictA, restrictB, alpha);
|
|
|
166af2 |
}
|
|
|
d9135c |
}
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
|
|
|
d9135c |
void TAssistantLine::draw(TToolViewer*, bool enabled) const {
|
|
|
d9135c |
double alpha = getDrawingAlpha(enabled);
|
|
|
d9135c |
bool restrictA = getRestrictA();
|
|
|
d9135c |
bool restrictB = getRestrictB();
|
|
|
d9135c |
bool parallel = getParallel();
|
|
|
d9135c |
bool grid = getGrid();
|
|
|
d9135c |
bool perspective = getPerspective();
|
|
|
d9135c |
|
|
|
d9135c |
// common data about viewport
|
|
|
d9135c |
const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
|
|
|
d9135c |
TAffine4 modelview, projection;
|
|
|
d9135c |
glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
|
|
|
d9135c |
glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
|
|
|
d9135c |
TAffine matrix = (projection*modelview).get2d();
|
|
|
d9135c |
TAffine matrixInv = matrix.inv();
|
|
|
d9135c |
double pixelSize = sqrt(tglGetPixelSize2());
|
|
|
d9135c |
|
|
|
d9135c |
// calculate range
|
|
|
d9135c |
TPointD aa = matrix*m_a.position;
|
|
|
d9135c |
TPointD bb = matrix*m_b.position;
|
|
|
d9135c |
bool success = false;
|
|
|
d9135c |
if (restrictA && restrictB)
|
|
|
d9135c |
success = TGuidelineLineBase::truncateLine(oneBox, aa, bb);
|
|
|
d9135c |
else if (restrictA)
|
|
|
d9135c |
success = TGuidelineLineBase::truncateRay(oneBox, aa, bb);
|
|
|
d9135c |
else if (restrictB)
|
|
|
d9135c |
success = TGuidelineLineBase::truncateRay(oneBox, bb, aa);
|
|
|
d9135c |
else
|
|
|
d9135c |
success = TGuidelineLineBase::truncateInfiniteLine(oneBox, aa, bb);
|
|
|
d9135c |
|
|
|
d9135c |
if (!success) {
|
|
|
d9135c |
// line is out of screen, bud grid still can be visible
|
|
|
d9135c |
if (grid && getParallel())
|
|
|
d9135c |
drawGrid(
|
|
|
d9135c |
m_a.position,
|
|
|
d9135c |
m_b.position,
|
|
|
d9135c |
m_grid0.position,
|
|
|
d9135c |
m_grid1.position,
|
|
|
d9135c |
restrictA,
|
|
|
d9135c |
restrictB,
|
|
|
d9135c |
perspective,
|
|
|
d9135c |
getDrawingGridAlpha() );
|
|
|
d9135c |
return;
|
|
|
d9135c |
}
|
|
|
d9135c |
|
|
|
d9135c |
TPointD a = matrixInv*aa;
|
|
|
d9135c |
TPointD b = matrixInv*bb;
|
|
|
d9135c |
|
|
|
d9135c |
// draw line
|
|
|
d9135c |
drawSegment(a, b, pixelSize, alpha);
|
|
|
d9135c |
|
|
|
d9135c |
// draw restriction marks
|
|
|
d9135c |
if (restrictA || (!parallel && grid && perspective))
|
|
|
d9135c |
drawDot(m_a.position);
|
|
|
d9135c |
if (restrictB)
|
|
|
d9135c |
drawDot(m_b.position);
|
|
|
d9135c |
|
|
|
d9135c |
if (grid) {
|
|
|
d9135c |
if (getParallel()) {
|
|
|
d9135c |
drawGrid(
|
|
|
d9135c |
m_a.position,
|
|
|
d9135c |
m_b.position,
|
|
|
d9135c |
m_grid0.position,
|
|
|
d9135c |
m_grid1.position,
|
|
|
d9135c |
restrictA,
|
|
|
d9135c |
restrictB,
|
|
|
d9135c |
perspective,
|
|
|
d9135c |
getDrawingGridAlpha() );
|
|
|
166af2 |
} else {
|
|
|
d9135c |
drawRuler(
|
|
|
d9135c |
a, b, m_grid0.position, m_grid1.position,
|
|
|
d9135c |
perspective ? &m_a.position : nullptr, getDrawingAlpha() );
|
|
|
166af2 |
}
|
|
|
166af2 |
}
|
|
|
d9135c |
}
|
|
|
166af2 |
|
|
|
166af2 |
|
|
|
166af2 |
|
|
|
166af2 |
//*****************************************************************************************
|
|
|
166af2 |
// Registration
|
|
|
166af2 |
//*****************************************************************************************
|
|
|
166af2 |
|
|
|
166af2 |
static TAssistantTypeT<tassistantline> assistantLine("assistantLine");</tassistantline>
|