]> Shamusworld >> Repos - architektonas/blobdiff - src/base/ellipse.cpp
Major refactor of Architektonas: Jettisoning old cruft.
[architektonas] / src / base / ellipse.cpp
diff --git a/src/base/ellipse.cpp b/src/base/ellipse.cpp
deleted file mode 100644 (file)
index 5d4fbd5..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-// ellipse.cpp
-//
-// Part of the Architektonas Project
-// Originally part of QCad Community Edition by Andrew Mustun
-// Extensively rewritten and refactored by James L. Hammons
-// Portions copyright (C) 2001-2003 RibbonSoft
-// Copyright (C) 2010 Underground Software
-// See the README and GPLv2 files for licensing and warranty information
-//
-// JLH = James L. Hammons <jlhamm@acm.org>
-//
-// Who  When        What
-// ---  ----------  -----------------------------------------------------------
-// JLH  05/28/2010  Added this text. :-)
-//
-
-#include "ellipse.h"
-
-#include "drawing.h"
-#include "graphicview.h"
-#include "information.h"
-#include "linetypepattern.h"
-#include "paintinterface.h"
-
-/**
- * Constructor.
- */
-Ellipse::Ellipse(EntityContainer * parent, const EllipseData & d):
-       AtomicEntity(parent), data(d)
-{
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-/*virtual*/ Ellipse::~Ellipse()
-{
-}
-
-/*virtual*/ Entity * Ellipse::clone()
-{
-       Ellipse * e = new Ellipse(*this);
-       e->initId();
-       return e;
-}
-
-/**    @return RS2::EntityEllipse */
-/*virtual*/ RS2::EntityType Ellipse::rtti() const
-{
-       return RS2::EntityEllipse;
-}
-
-/**
- * @return Start point of the entity.
- */
-/*virtual*/ Vector Ellipse::getStartpoint() const
-{
-       Vector p;
-       p.set(data.center.x + cos(data.angle1) * getMajorRadius(),
-               data.center.y + sin(data.angle1) * getMinorRadius());
-       p.rotate(data.center, getAngle());
-       return p;
-}
-
-/**
- * @return End point of the entity.
- */
-/*virtual*/ Vector Ellipse::getEndpoint() const
-{
-       Vector p;
-       p.set(data.center.x + cos(data.angle2) * getMajorRadius(),
-               data.center.y + sin(data.angle2) * getMinorRadius());
-       p.rotate(data.center, getAngle());
-       return p;
-}
-
-void Ellipse::moveStartpoint(const Vector & pos)
-{
-       data.angle1 = getEllipseAngle(pos);
-       //data.angle1 = data.center.angleTo(pos);
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-void Ellipse::moveEndpoint(const Vector & pos)
-{
-       data.angle2 = getEllipseAngle(pos);
-       //data.angle2 = data.center.angleTo(pos);
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-RS2::Ending Ellipse::getTrimPoint(const Vector & coord, const Vector & trimPoint)
-{
-       double angEl = getEllipseAngle(trimPoint);
-       double angM = getEllipseAngle(coord);
-
-       if (Math::getAngleDifference(angM, angEl) > M_PI)
-               //if (data.reversed) {
-               //      return RS2::EndingEnd;
-               //}
-               //else {
-               return RS2::EndingStart;
-               //}
-       else
-               //if (data.reversed) {
-               //      return RS2::EndingStart;
-               //}
-               //else {
-               return RS2::EndingEnd;
-               //}
-}
-
-double Ellipse::getEllipseAngle(const Vector & pos)
-{
-       Vector m = pos;
-       m.rotate(data.center, -data.majorP.angle());
-       Vector v = m - data.center;
-       v.scale(Vector(1.0, 1.0 / data.ratio));
-       return v.angle();
-}
-
-/** @return Copy of data that defines the ellipse. **/
-EllipseData Ellipse::getData()
-{
-       return data;
-}
-
-VectorSolutions Ellipse::getRefPoints()
-{
-       VectorSolutions ret(getStartpoint(), getEndpoint(), data.center);
-       return ret;
-}
-
-/**
- * @retval true if the arc is reversed (clockwise),
- * @retval false otherwise
- */
-bool Ellipse::isReversed() const
-{
-       return data.reversed;
-}
-
-/** sets the reversed status. */
-void Ellipse::setReversed(bool r)
-{
-       data.reversed = r;
-}
-
-/** @return The rotation angle of this ellipse */
-double Ellipse::getAngle() const
-{
-       return data.majorP.angle();
-}
-
-/** @return The start angle of this arc */
-double Ellipse::getAngle1()
-{
-       return data.angle1;
-}
-
-/** Sets new start angle. */
-void Ellipse::setAngle1(double a1)
-{
-       data.angle1 = a1;
-}
-
-/** @return The end angle of this arc */
-double Ellipse::getAngle2()
-{
-       return data.angle2;
-}
-
-/** Sets new end angle. */
-void Ellipse::setAngle2(double a2)
-{
-       data.angle2 = a2;
-}
-
-/** @return The center point (x) of this arc */
-Vector Ellipse::getCenter()
-{
-       return data.center;
-}
-
-/** Sets new center. */
-void Ellipse::setCenter(const Vector & c)
-{
-       data.center = c;
-}
-
-/** @return The endpoint of the major axis (relative to center). */
-Vector Ellipse::getMajorP()
-{
-       return data.majorP;
-}
-
-/** Sets new major point (relative to center). */
-void Ellipse::setMajorP(const Vector & p)
-{
-       data.majorP = p;
-}
-
-/** @return The ratio of minor to major axis */
-double Ellipse::getRatio()
-{
-       return data.ratio;
-}
-
-/** Sets new ratio. */
-void Ellipse::setRatio(double r)
-{
-       data.ratio = r;
-}
-
-/**
- * @return Angle length in rad.
- */
-/*virtual*/ double Ellipse::getAngleLength() const
-{
-       if (isReversed())
-               return data.angle1 - data.angle2;
-       else
-               return data.angle2 - data.angle1;
-}
-
-/** @return The major radius of this ellipse. Same as getRadius() */
-double Ellipse::getMajorRadius() const
-{
-       return data.majorP.magnitude();
-}
-
-/** @return The minor radius of this ellipse */
-double Ellipse::getMinorRadius() const
-{
-       return data.majorP.magnitude() * data.ratio;
-}
-
-/**
- * Recalculates the endpoints using the angles and the radius.
- */
-/*
-   void Ellipse::calculateEndpoints() {
-   double angle = data.majorP.angle();
-   double radius1 = getMajorRadius();
-   double radius2 = getMinorRadius();
-
-   startpoint.set(data.center.x + cos(data.angle1) * radius1,
-                  data.center.y + sin(data.angle1) * radius2);
-   startpoint.rotate(data.center, angle);
-   endpoint.set(data.center.x + cos(data.angle2) * radius1,
-                data.center.y + sin(data.angle2) * radius2);
-   endpoint.rotate(data.center, angle);
-   }
- */
-
-/**
- * Calculates the boundary box of this ellipse.
- *
- * @todo Fix that - the algorithm used is really bad / slow.
- */
-void Ellipse::calculateBorders()
-{
-       DEBUG->print("Ellipse::calculateBorders");
-
-       double radius1 = getMajorRadius();
-       double radius2 = getMinorRadius();
-       double angle = getAngle();
-       double a1 = ((!isReversed()) ? data.angle1 : data.angle2);
-       double a2 = ((!isReversed()) ? data.angle2 : data.angle1);
-       Vector startpoint = getStartpoint();
-       Vector endpoint = getEndpoint();
-
-       double minX = std::min(startpoint.x, endpoint.x);
-       double minY = std::min(startpoint.y, endpoint.y);
-       double maxX = std::max(startpoint.x, endpoint.x);
-       double maxY = std::max(startpoint.y, endpoint.y);
-
-       // kind of a brute force. TODO: exact calculation
-       Vector vp;
-       double a = a1;
-
-       do
-       {
-               vp.set(data.center.x + radius1 * cos(a),
-                       data.center.y + radius2 * sin(a));
-               vp.rotate(data.center, angle);
-
-               minX = std::min(minX, vp.x);
-               minY = std::min(minY, vp.y);
-               maxX = std::max(maxX, vp.x);
-               maxY = std::max(maxY, vp.y);
-
-               a += 0.03;
-       }
-       while (Math::isAngleBetween(Math::correctAngle(a), a1, a2, false)
-              && a < 4 * M_PI);
-
-       minV.set(minX, minY);
-       maxV.set(maxX, maxY);
-       DEBUG->print("Ellipse::calculateBorders: OK");
-}
-
-Vector Ellipse::getNearestEndpoint(const Vector & coord, double * dist)
-{
-       double dist1, dist2;
-       Vector nearerPoint;
-       Vector startpoint = getStartpoint();
-       Vector endpoint = getEndpoint();
-
-       dist1 = startpoint.distanceTo(coord);
-       dist2 = endpoint.distanceTo(coord);
-
-       if (dist2 < dist1)
-       {
-               if (dist != NULL)
-                       *dist = dist2;
-               nearerPoint = endpoint;
-       }
-       else
-       {
-               if (dist != NULL)
-                       *dist = dist1;
-               nearerPoint = startpoint;
-       }
-
-       return nearerPoint;
-}
-
-Vector Ellipse::getNearestPointOnEntity(const Vector & coord, bool onEntity, double * dist, Entity * * entity)
-{
-       DEBUG->print("Ellipse::getNearestPointOnEntity");
-
-       Vector ret(false);
-
-       if (entity != NULL)
-               *entity = this;
-       double ang = getAngle();
-
-       Vector normalized = (coord - data.center).rotate(-ang);
-
-       double dU = normalized.x;
-       double dV = normalized.y;
-       double dA = getMajorRadius();
-       double dB = getMinorRadius();
-       double dEpsilon = 1.0e-8;
-       int iMax = 32;
-       int riIFinal = 0;
-       double rdX = 0.0;
-       double rdY = 0.0;
-       double dDistance;
-       bool swap = false;
-       bool majorSwap = false;
-
-       if (dA < dB)
-       {
-               double dum = dA;
-               dA = dB;
-               dB = dum;
-               dum = dU;
-               dU = dV;
-               dV = dum;
-               majorSwap = true;
-       }
-
-       if (dV < 0.0)
-       {
-               dV *= -1.0;
-               swap = true;
-       }
-
-       // initial guess
-       double dT = dB * (dV - dB);
-
-       // Newton s method
-       int i;
-
-       for (i = 0; i < iMax; i++)
-       {
-               DEBUG->print("Ellipse::getNearestPointOnEntity: i: %d", i);
-               double dTpASqr = dT + dA * dA;
-               double dTpBSqr = dT + dB * dB;
-               double dInvTpASqr = 1.0 / dTpASqr;
-               double dInvTpBSqr = 1.0 / dTpBSqr;
-               double dXDivA = dA * dU * dInvTpASqr;
-               double dYDivB = dB * dV * dInvTpBSqr;
-               double dXDivASqr = dXDivA * dXDivA;
-               double dYDivBSqr = dYDivB * dYDivB;
-               double dF = dXDivASqr + dYDivBSqr - 1.0;
-               DEBUG->print("Ellipse::getNearestPointOnEntity: dF: %f", dF);
-
-               if (fabs(dF) < dEpsilon)
-               {
-                       // F(t0) is close enough to zero, terminate the iteration:
-                       rdX = dXDivA * dA;
-                       rdY = dYDivB * dB;
-                       riIFinal = i;
-                       DEBUG->print("Ellipse::getNearestPointOnEntity: rdX,rdY 1: %f,%f", rdX, rdY);
-                       break;
-               }
-               double dFDer = 2.0 * (dXDivASqr * dInvTpASqr + dYDivBSqr * dInvTpBSqr);
-               double dRatio = dF / dFDer;
-               DEBUG->print("Ellipse::getNearestPointOnEntity: dRatio: %f", dRatio);
-
-               if (fabs(dRatio) < dEpsilon)
-               {
-                       // t1-t0 is close enough to zero, terminate the iteration:
-                       rdX = dXDivA * dA;
-                       rdY = dYDivB * dB;
-                       riIFinal = i;
-                       DEBUG->print("Ellipse::getNearestPointOnEntity: rdX,rdY 2: %f,%f", rdX, rdY);
-                       break;
-               }
-               dT += dRatio;
-       }
-
-       if (i == iMax)
-       {
-               // failed to converge:
-               DEBUG->print("Ellipse::getNearestPointOnEntity: failed");
-               dDistance = RS_MAXDOUBLE;
-       }
-       else
-       {
-               double dDelta0 = rdX - dU;
-               double dDelta1 = rdY - dV;
-               dDistance = sqrt(dDelta0 * dDelta0 + dDelta1 * dDelta1);
-               ret = Vector(rdX, rdY);
-               DEBUG->print("Ellipse::getNearestPointOnEntity: rdX,rdY 2: %f,%f", rdX, rdY);
-               DEBUG->print("Ellipse::getNearestPointOnEntity: ret: %f,%f", ret.x, ret.y);
-       }
-
-       if (dist != NULL)
-       {
-               if (ret.valid)
-                       *dist = dDistance;
-               else
-                       *dist = RS_MAXDOUBLE;
-       }
-
-       if (ret.valid)
-       {
-               if (swap)
-                       ret.y *= -1.0;
-
-
-               if (majorSwap)
-               {
-                       double dum = ret.x;
-                       ret.x = ret.y;
-                       ret.y = dum;
-               }
-               ret = (ret.rotate(ang) + data.center);
-
-               if (onEntity)
-               {
-                       double a1 = data.center.angleTo(getStartpoint());
-                       double a2 = data.center.angleTo(getEndpoint());
-                       double a = data.center.angleTo(ret);
-
-                       if (!Math::isAngleBetween(a, a1, a2, data.reversed))
-                               ret = Vector(false);
-               }
-       }
-
-       return ret;
-}
-
-/**
- * @param tolerance Tolerance.
- *
- * @retval true if the given point is on this entity.
- * @retval false otherwise
- */
-bool Ellipse::isPointOnEntity(const Vector & coord, double tolerance)
-{
-       double dist = getDistanceToPoint(coord, NULL, RS2::ResolveNone);
-       return (dist <= tolerance);
-}
-
-Vector Ellipse::getNearestCenter(const Vector & coord, double * dist)
-{
-       if (dist != NULL)
-               *dist = coord.distanceTo(data.center);
-       return data.center;
-}
-
-/**
- * @todo Implement this.
- */
-Vector Ellipse::getNearestMiddle(const Vector & /*coord*/, double * dist)
-{
-       if (dist != NULL)
-               *dist = RS_MAXDOUBLE;
-       return Vector(false);
-}
-
-Vector Ellipse::getNearestDist(double /*distance*/, const Vector & /*coord*/, double * dist)
-{
-       if (dist != NULL)
-               *dist = RS_MAXDOUBLE;
-       return Vector(false);
-}
-
-double Ellipse::getDistanceToPoint(const Vector & coord, Entity * * entity, RS2::ResolveLevel, double /*solidDist*/)
-{
-       double dist = RS_MAXDOUBLE;
-       getNearestPointOnEntity(coord, true, &dist, entity);
-
-       return dist;
-}
-
-void Ellipse::move(Vector offset)
-{
-       data.center.move(offset);
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-void Ellipse::rotate(Vector center, double angle)
-{
-       data.center.rotate(center, angle);
-       data.majorP.rotate(angle);
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-void Ellipse::scale(Vector center, Vector factor)
-{
-       data.center.scale(center, factor);
-       data.majorP.scale(factor);
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-/**
- * @todo deal with angles correctly
- */
-void Ellipse::mirror(Vector axisPoint1, Vector axisPoint2)
-{
-       Vector mp = data.center + data.majorP;
-
-       data.center.mirror(axisPoint1, axisPoint2);
-       mp.mirror(axisPoint1, axisPoint2);
-
-       data.majorP = mp - data.center;
-
-       double a = axisPoint1.angleTo(axisPoint2);
-
-       Vector vec;
-       vec.setPolar(1.0, data.angle1);
-       vec.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
-       data.angle1 = vec.angle() - 2 * a;
-
-       vec.setPolar(1.0, data.angle2);
-       vec.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
-       data.angle2 = vec.angle() - 2 * a;
-
-       data.reversed = (!data.reversed);
-
-       //calculateEndpoints();
-       calculateBorders();
-}
-
-void Ellipse::moveRef(const Vector & ref, const Vector & offset)
-{
-       Vector startpoint = getStartpoint();
-       Vector endpoint = getEndpoint();
-
-       if (ref.distanceTo(startpoint) < 1.0e-4)
-               moveStartpoint(startpoint + offset);
-
-
-       if (ref.distanceTo(endpoint) < 1.0e-4)
-               moveEndpoint(endpoint + offset);
-}
-
-void Ellipse::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
-{
-       if (!painter || !view)
-               return;
-
-       if (getPen().getLineType() == RS2::SolidLine || isSelected()
-           || view->getDrawingMode() == RS2::ModePreview)
-               painter->drawEllipse(view->toGui(getCenter()),
-                       getMajorRadius() * view->getFactor().x,
-                       getMinorRadius() * view->getFactor().x,
-                       getAngle(), getAngle1(), getAngle2(), isReversed());
-       else
-       {
-               double styleFactor = getStyleFactor(view);
-
-               if (styleFactor < 0.0)
-               {
-                       painter->drawEllipse(view->toGui(getCenter()),
-                               getMajorRadius() * view->getFactor().x,
-                               getMinorRadius() * view->getFactor().x,
-                               getAngle(), getAngle1(), getAngle2(), isReversed());
-                       return;
-               }
-
-               // Pattern:
-               LineTypePattern * pat;
-
-               if (isSelected())
-                       pat = &patternSelected;
-               else
-                       pat = view->getPattern(getPen().getLineType());
-
-               if (pat == NULL)
-                       return;
-
-               // Pen to draw pattern is always solid:
-               Pen pen = painter->getPen();
-               pen.setLineType(RS2::SolidLine);
-               painter->setPen(pen);
-
-               double * da;     // array of distances in x.
-               int i;          // index counter
-
-               double length = getAngleLength();
-
-               // create pattern:
-               da = new double[pat->num];
-
-               double tot = 0.0;
-               i = 0;
-               bool done = false;
-               double curA = getAngle1();
-               double curR;
-               Vector cp = view->toGui(getCenter());
-               double r1 = getMajorRadius() * view->getFactor().x;
-               double r2 = getMinorRadius() * view->getFactor().x;
-
-               do
-               {
-                       curR = sqrt(Math::pow(getMinorRadius() * cos(curA), 2.0)
-                                       + Math::pow(getMajorRadius() * sin(curA), 2.0));
-
-                       if (curR > 1.0e-6)
-                       {
-                               da[i] = fabs(pat->pattern[i] * styleFactor) / curR;
-
-                               if (pat->pattern[i] * styleFactor > 0.0)
-                               {
-                                       if (tot + fabs(da[i]) < length)
-                                               painter->drawEllipse(cp, r1, r2, getAngle(), curA, curA + da[i], false);
-                                       else
-                                               painter->drawEllipse(cp, r1, r2, getAngle(), curA, getAngle2(), false);
-                               }
-                       }
-
-                       curA += da[i];
-                       tot += fabs(da[i]);
-                       done = tot > length;
-
-                       i++;
-
-                       if (i >= pat->num)
-                               i = 0;
-               }
-               while (!done);
-
-               delete[] da;
-       }
-}
-
-/**
- * Dumps the point's data to stdout.
- */
-std::ostream & operator<<(std::ostream & os, const Ellipse & a)
-{
-       os << " Ellipse: " << a.data << "\n";
-       return os;
-}
-