|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
d5090c |
#include <tools/assistants/guidelineellipse.h>
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
// TnzCore includes
|
|
Ivan Mahonin |
9a49d4 |
#include "tgl.h"
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
//*****************************************************************************************
|
|
Ivan Mahonin |
9a49d4 |
// TGuidelineEllipse implementation
|
|
Ivan Mahonin |
9a49d4 |
//*****************************************************************************************
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
TGuidelineEllipse::TGuidelineEllipse(
|
|
Ivan Mahonin |
9a49d4 |
bool enabled,
|
|
Ivan Mahonin |
9a49d4 |
double magnetism,
|
|
Ivan Mahonin |
9a49d4 |
TAffine matrix
|
|
Ivan Mahonin |
9a49d4 |
):
|
|
Ivan Mahonin |
9a49d4 |
TGuideline(enabled, magnetism),
|
|
Ivan Mahonin |
9a49d4 |
matrix(matrix),
|
|
Ivan Mahonin |
9a49d4 |
matrixInv(matrix.inv()) { }
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
TGuidelineEllipse::TGuidelineEllipse(
|
|
Ivan Mahonin |
9a49d4 |
bool enabled,
|
|
Ivan Mahonin |
9a49d4 |
double magnetism,
|
|
Ivan Mahonin |
9a49d4 |
TAffine matrix,
|
|
Ivan Mahonin |
9a49d4 |
TAffine matrixInv
|
|
Ivan Mahonin |
9a49d4 |
):
|
|
Ivan Mahonin |
9a49d4 |
TGuideline(enabled, magnetism),
|
|
Ivan Mahonin |
9a49d4 |
matrix(matrix),
|
|
Ivan Mahonin |
9a49d4 |
matrixInv(matrixInv) { }
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
TTrackPoint
|
|
Ivan Mahonin |
9a49d4 |
TGuidelineEllipse::transformPoint(const TTrackPoint &point) const
|
|
Ivan Mahonin |
9a49d4 |
{
|
|
Ivan Mahonin |
9a49d4 |
TTrackPoint p = point;
|
|
Ivan Mahonin |
9a49d4 |
TPointD pp = matrixInv*p.position;
|
|
Ivan Mahonin |
9a49d4 |
double l2 = norm2(pp);
|
|
Ivan Mahonin |
9a49d4 |
if (l2 > TConsts::epsilon*TConsts::epsilon)
|
|
Ivan Mahonin |
9a49d4 |
p.position = matrix*(pp*(1.0/sqrt(l2)));
|
|
Ivan Mahonin |
9a49d4 |
return p;
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
bool
|
|
Ivan Mahonin |
9a49d4 |
TGuidelineEllipse::truncateEllipse(
|
|
Ivan Mahonin |
9a49d4 |
TAngleRangeSet &ranges,
|
|
Ivan Mahonin |
9a49d4 |
const TAffine &ellipseMatrixInv,
|
|
Ivan Mahonin |
9a49d4 |
const TRectD &bounds )
|
|
Ivan Mahonin |
9a49d4 |
{
|
|
Ivan Mahonin |
9a49d4 |
if (ranges.isEmpty()) return false;
|
|
Ivan Mahonin |
9a49d4 |
if (bounds.isEmpty()) { ranges.clear(); return false; }
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
TPointD o = ellipseMatrixInv*bounds.getP00();
|
|
Ivan Mahonin |
9a49d4 |
TPointD dx = ellipseMatrixInv.transformDirection(TPointD(bounds.getLx(), 0.0));
|
|
Ivan Mahonin |
9a49d4 |
TPointD dy = ellipseMatrixInv.transformDirection(TPointD(0.0, bounds.getLy()));
|
|
Ivan Mahonin |
9a49d4 |
double lx2 = norm2(dx);
|
|
Ivan Mahonin |
9a49d4 |
double ly2 = norm2(dy);
|
|
Ivan Mahonin |
9a49d4 |
if ( lx2 < TConsts::epsilon*TConsts::epsilon
|
|
Ivan Mahonin |
9a49d4 |
|| ly2 < TConsts::epsilon*TConsts::epsilon )
|
|
Ivan Mahonin |
9a49d4 |
{ ranges.clear(); return false; }
|
|
Ivan Mahonin |
9a49d4 |
TPointD nx = rotate90(dx)*(1.0/sqrt(lx2));
|
|
Ivan Mahonin |
9a49d4 |
TPointD ny = rotate90(dy)*(1.0/sqrt(ly2));
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
TAngleI ax = TAngleRangeSet::fromDouble(atan(dx));
|
|
Ivan Mahonin |
9a49d4 |
TAngleI ay = TAngleRangeSet::fromDouble(atan(dy));
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
double sign = nx*dy;
|
|
Ivan Mahonin |
9a49d4 |
if (fabs(sign) <= TConsts::epsilon)
|
|
Ivan Mahonin |
9a49d4 |
{ ranges.clear(); return false; }
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
if (sign < 0.0) {
|
|
Ivan Mahonin |
9a49d4 |
nx = -nx; ny = -ny;
|
|
Ivan Mahonin |
9a49d4 |
ax ^= TAngleRangeSet::half;
|
|
Ivan Mahonin |
9a49d4 |
ay ^= TAngleRangeSet::half;
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
TAngleI angles[] = {
|
|
Ivan Mahonin |
9a49d4 |
ax,
|
|
Ivan Mahonin |
9a49d4 |
ax^TAngleRangeSet::half,
|
|
Ivan Mahonin |
9a49d4 |
ay,
|
|
Ivan Mahonin |
9a49d4 |
ay^TAngleRangeSet::half };
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
double heights[] = {
|
|
Ivan Mahonin |
9a49d4 |
o*nx,
|
|
Ivan Mahonin |
9a49d4 |
-((o+dx+dy)*nx),
|
|
Ivan Mahonin |
9a49d4 |
(o+dx)*ny,
|
|
Ivan Mahonin |
9a49d4 |
-((o+dy)*ny) };
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
for(int i = 0; i < 4; ++i) {
|
|
Ivan Mahonin |
9a49d4 |
double h = heights[i];
|
|
Ivan Mahonin |
9a49d4 |
if (heights[i] <= TConsts::epsilon - 1.0)
|
|
Ivan Mahonin |
9a49d4 |
continue;
|
|
Ivan Mahonin |
9a49d4 |
if (h >= 1.0 - TConsts::epsilon)
|
|
Ivan Mahonin |
9a49d4 |
{ ranges.clear(); return false; }
|
|
Ivan Mahonin |
9a49d4 |
TAngleI a = TAngleRangeSet::fromDouble(asin(h));
|
|
Ivan Mahonin |
9a49d4 |
TAngleI da = angles[i];
|
|
Ivan Mahonin |
9a49d4 |
ranges.subtract(da - a, (da + a)^TAngleRangeSet::half );
|
|
Ivan Mahonin |
9a49d4 |
if (ranges.isEmpty()) return false;
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
return true;
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
int
|
|
Ivan Mahonin |
9a49d4 |
TGuidelineEllipse::calcSegmentsCount(const TAffine &ellipseMatrix, double pixelSize) {
|
|
Ivan Mahonin |
9a49d4 |
const TAffine &em = ellipseMatrix;
|
|
Ivan Mahonin |
9a49d4 |
const int min = 4, max = 1000;
|
|
Ivan Mahonin |
9a49d4 |
double r = sqrt(0.5*(norm2(TPointD(em.a11, em.a21)) + norm2(TPointD(em.a12, em.a22))));
|
|
Ivan Mahonin |
9a49d4 |
double h = 0.5*pixelSize/r;
|
|
Ivan Mahonin |
9a49d4 |
if (h <= TConsts::epsilon) return max;
|
|
Ivan Mahonin |
9a49d4 |
if (h >= 1.0 - TConsts::epsilon) return min;
|
|
Ivan Mahonin |
9a49d4 |
double segments = round(M_2PI/acos(1.0 - h));
|
|
Ivan Mahonin |
9a49d4 |
return segments <= (double)min ? min
|
|
Ivan Mahonin |
9a49d4 |
: segments >= (double)max ? max
|
|
Ivan Mahonin |
9a49d4 |
: (int)segments;
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
void
|
|
Ivan Mahonin |
9a49d4 |
TGuidelineEllipse::draw(bool active, bool enabled) const {
|
|
Ivan Mahonin |
9a49d4 |
TAffine4 modelview, projection;
|
|
Ivan Mahonin |
9a49d4 |
glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
|
|
Ivan Mahonin |
9a49d4 |
glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
|
|
Ivan Mahonin |
9a49d4 |
TAffine screenMatrix = (projection*modelview).get2d();
|
|
Ivan Mahonin |
9a49d4 |
TAffine screenMatrixInv = screenMatrix.inv();
|
|
Ivan Mahonin |
9a49d4 |
double pixelSize = sqrt(tglGetPixelSize2());
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
|
|
Ivan Mahonin |
9a49d4 |
TAngleRangeSet ranges(true);
|
|
Ivan Mahonin |
9a49d4 |
if (!truncateEllipse(ranges, matrixInv*screenMatrixInv, oneBox))
|
|
Ivan Mahonin |
9a49d4 |
return;
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
int segments = calcSegmentsCount(matrix, pixelSize);
|
|
Ivan Mahonin |
9a49d4 |
double da = M_2PI/segments;
|
|
Ivan Mahonin |
9a49d4 |
double s = sin(da);
|
|
Ivan Mahonin |
9a49d4 |
double c = cos(da);
|
|
Ivan Mahonin |
9a49d4 |
|
|
Ivan Mahonin |
9a49d4 |
for(TAngleRangeSet::Iterator i(ranges); i; ++i) {
|
|
Ivan Mahonin |
9a49d4 |
double a0 = i.d0();
|
|
Ivan Mahonin |
9a49d4 |
double a1 = i.d1greater();
|
|
Ivan Mahonin |
9a49d4 |
TPointD r(cos(a0), sin(a0));
|
|
Ivan Mahonin |
9a49d4 |
TPointD p0 = matrix*r;
|
|
Ivan Mahonin |
9a49d4 |
int cnt = (int)floor((a1 - a0)/da);
|
|
Ivan Mahonin |
9a49d4 |
for(int j = 0; j < cnt; ++j) {
|
|
Ivan Mahonin |
9a49d4 |
r = TPointD(r.x*c - r.y*s, r.y*c + r.x*s);
|
|
Ivan Mahonin |
9a49d4 |
TPointD p1 = matrix*r;
|
|
Ivan Mahonin |
9a49d4 |
drawSegment(p0, p1, pixelSize, active, enabled);
|
|
Ivan Mahonin |
9a49d4 |
p0 = p1;
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
drawSegment(p0, matrix*TPointD(cos(a1), sin(a1)), pixelSize, active, enabled);
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
}
|
|
Ivan Mahonin |
9a49d4 |
|