]> Shamusworld >> Repos - architektonas/blobdiff - src/base/hatch.cpp
Major refactor of Architektonas: Jettisoning old cruft.
[architektonas] / src / base / hatch.cpp
diff --git a/src/base/hatch.cpp b/src/base/hatch.cpp
deleted file mode 100644 (file)
index f7442de..0000000
+++ /dev/null
@@ -1,818 +0,0 @@
-// hatch.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 "hatch.h"
-
-#include <QtCore>
-#include "drawing.h"
-#include "graphicview.h"
-#include "information.h"
-#include "paintinterface.h"
-#include "pattern.h"
-#include "patternlist.h"
-
-/**
- * Constructor.
- */
-Hatch::Hatch(EntityContainer * parent, const HatchData & d):
-       EntityContainer(parent), data(d)
-{
-       hatch = NULL;
-       updateRunning = false;
-       needOptimization = true;
-}
-
-/*virtual*/ Hatch::~Hatch()
-{
-}
-
-Entity * Hatch::clone()
-{
-       Hatch * t = new Hatch(*this);
-#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
-//     t->entities.setAutoDelete(entities.autoDelete());
-       t->initId();
-       t->detach();
-       t->hatch = NULL;
-       return t;
-}
-
-/**    @return RS2::EntityHatch */
-/*virtual*/ RS2::EntityType Hatch::rtti() const
-{
-       return RS2::EntityHatch;
-}
-
-/**
- * @return true: if this is a hatch with lines (hatch pattern),
- *         false: if this is filled with a solid color.
- */
-/*virtual*/ bool Hatch::isContainer() const
-{
-       if (isSolid())
-               return false;
-
-       return true;
-}
-
-/** @return Copy of data that defines the hatch. */
-HatchData Hatch::getData() const
-{
-       return data;
-}
-
-/**
- * Validates the hatch.
- */
-bool Hatch::validate()
-{
-       bool ret = true;
-
-       // loops:
-       for(Entity * l=firstEntity(RS2::ResolveNone); l!=NULL; l=nextEntity(RS2::ResolveNone))
-       {
-               if (l->rtti() == RS2::EntityContainer)
-               {
-                       EntityContainer * loop = (EntityContainer *)l;
-                       ret = loop->optimizeContours() && ret;
-               }
-       }
-
-       return ret;
-}
-
-/**
- * @return Number of loops.
- */
-int Hatch::countLoops()
-{
-       if (data.solid)
-               return count();
-       else
-               return count() - 1;
-}
-
-/** @return true if this is a solid fill. false if it is a pattern hatch. */
-bool Hatch::isSolid() const
-{
-       return data.solid;
-}
-
-void Hatch::setSolid(bool solid)
-{
-       data.solid = solid;
-}
-
-QString Hatch::getPattern()
-{
-       return data.pattern;
-}
-
-void Hatch::setPattern(const QString & pattern)
-{
-       data.pattern = pattern;
-}
-
-double Hatch::getScale()
-{
-       return data.scale;
-}
-
-void Hatch::setScale(double scale)
-{
-       data.scale = scale;
-}
-
-double Hatch::getAngle()
-{
-       return data.angle;
-}
-
-void Hatch::setAngle(double angle)
-{
-       data.angle = angle;
-}
-
-/**
- * Recalculates the borders of this hatch.
- */
-void Hatch::calculateBorders()
-{
-       DEBUG->print("Hatch::calculateBorders");
-
-       activateContour(true);
-       EntityContainer::calculateBorders();
-
-       DEBUG->print("Hatch::calculateBorders: size: %f,%f", getSize().x, getSize().y);
-
-       activateContour(false);
-}
-
-/**
- * Updates the Hatch. Called when the
- * hatch or it's data, position, alignment, .. changes.
- */
-void Hatch::update()
-{
-       DEBUG->print("Hatch::update");
-       DEBUG->print("Hatch::update: contour has %d loops", count());
-
-       if (updateRunning)
-               return;
-
-       if (updateEnabled == false)
-               return;
-
-       if (data.solid == true)
-               return;
-
-       DEBUG->print("Hatch::update");
-       updateRunning = true;
-
-       // delete old hatch:
-       if (hatch != NULL)
-       {
-               removeEntity(hatch);
-               hatch = NULL;
-       }
-
-       if (isUndone())
-       {
-               updateRunning = false;
-               return;
-       }
-
-       if (!validate())
-       {
-               DEBUG->print(Debug::D_WARNING, "Hatch::update: invalid contour in hatch found");
-               updateRunning = false;
-               return;
-       }
-
-       // search pattern:
-       DEBUG->print("Hatch::update: requesting pattern");
-       Pattern * pat = PATTERNLIST->requestPattern(data.pattern);
-
-       if (pat == NULL)
-       {
-               updateRunning = false;
-               DEBUG->print("Hatch::update: requesting pattern: not found");
-               return;
-       }
-
-       DEBUG->print("Hatch::update: requesting pattern: OK");
-
-       DEBUG->print("Hatch::update: cloning pattern");
-       pat = (Pattern*)pat->clone();
-       DEBUG->print("Hatch::update: cloning pattern: OK");
-
-       // scale pattern
-       DEBUG->print("Hatch::update: scaling pattern");
-       pat->scale(Vector(0.0,0.0), Vector(data.scale, data.scale));
-       pat->calculateBorders();
-       forcedCalculateBorders();
-       DEBUG->print("Hatch::update: scaling pattern: OK");
-
-       // find out how many pattern-instances we need in x/y:
-       int px1, py1, px2, py2;
-       double f;
-       Hatch * copy = (Hatch *)this->clone();
-       copy->rotate(Vector(0.0, 0.0), -data.angle);
-       copy->forcedCalculateBorders();
-
-       // create a pattern over the whole contour.
-       Vector pSize = pat->getSize();
-       Vector cPos = getMin();
-       Vector cSize = getSize();
-
-       DEBUG->print("Hatch::update: pattern size: %f/%f", pSize.x, pSize.y);
-       DEBUG->print("Hatch::update: contour size: %f/%f", cSize.x, cSize.y);
-
-       if (cSize.x < 1.0e-6 || cSize.y < 1.0e-6 || pSize.x < 1.0e-6 || pSize.y < 1.0e-6
-               || cSize.x > RS_MAXDOUBLE - 1 || cSize.y > RS_MAXDOUBLE - 1
-               || pSize.x > RS_MAXDOUBLE - 1 || pSize.y > RS_MAXDOUBLE - 1)
-       {
-               delete pat;
-               delete copy;
-               updateRunning = false;
-               DEBUG->print("Hatch::update: contour size or pattern size too small");
-               return;
-       }
-       // avoid huge memory consumption:
-       else if (cSize.x / pSize.x > 100 || cSize.y / pSize.y > 100)
-       {
-               DEBUG->print("Hatch::update: contour size too large or pattern size too small");
-               return;
-       }
-
-       f = copy->getMin().x/pat->getSize().x;
-       px1 = (int)floor(f);
-       f = copy->getMin().y/pat->getSize().y;
-       py1 = (int)floor(f);
-       f = copy->getMax().x/pat->getSize().x;
-       px2 = (int)ceil(f) - 1;
-       f = copy->getMax().y/pat->getSize().y;
-       py2 = (int)ceil(f) - 1;
-
-       EntityContainer tmp;   // container for untrimmed lines
-
-       // adding array of patterns to tmp:
-       DEBUG->print("Hatch::update: creating pattern carpet");
-
-       for(int px=px1; px<=px2; px++)
-       {
-               for(int py=py1; py<=py2; py++)
-               {
-                       for(Entity * e=pat->firstEntity(); e!=NULL; e=pat->nextEntity())
-                       {
-                               Entity * te = e->clone();
-                               te->rotate(Vector(0.0, 0.0), data.angle);
-                               Vector v1, v2;
-                               v1.setPolar(px * pSize.x, data.angle);
-                               v2.setPolar(py * pSize.y, data.angle + M_PI / 2.0);
-                               te->move(v1 + v2);
-                               tmp.addEntity(te);
-                       }
-               }
-       }
-
-       delete pat;
-       pat = NULL;
-       DEBUG->print("Hatch::update: creating pattern carpet: OK");
-
-       DEBUG->print("Hatch::update: cutting pattern carpet");
-       // cut pattern to contour shape:
-       EntityContainer tmp2;   // container for small cut lines
-       Line * line = NULL;
-       Arc * arc = NULL;
-       Circle * circle = NULL;
-
-       for(Entity * e=tmp.firstEntity(); e!=NULL; e=tmp.nextEntity())
-       {
-               Vector startPoint;
-               Vector endPoint;
-               Vector center = Vector(false);
-               bool reversed;
-
-               if (e->rtti() == RS2::EntityLine)
-               {
-                       line = (Line *)e;
-                       arc = NULL;
-                       circle = NULL;
-                       startPoint = line->getStartpoint();
-                       endPoint = line->getEndpoint();
-                       center = Vector(false);
-                       reversed = false;
-               }
-               else if (e->rtti() == RS2::EntityArc)
-               {
-                       arc = (Arc *)e;
-                       line = NULL;
-                       circle = NULL;
-                       startPoint = arc->getStartpoint();
-                       endPoint = arc->getEndpoint();
-                       center = arc->getCenter();
-                       reversed = arc->isReversed();
-               }
-               else if (e->rtti() == RS2::EntityCircle)
-               {
-                       circle = (Circle *)e;
-                       line = NULL;
-                       arc = NULL;
-                       startPoint = circle->getCenter() + Vector(circle->getRadius(), 0.0);
-                       endPoint = startPoint;
-                       center = circle->getCenter();
-                       reversed = false;
-               }
-               else
-               {
-                       continue;
-               }
-
-               // getting all intersections of this pattern line with the contour:
-               QList<Vector *> is;
-#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
-//        is.setAutoDelete(true);
-               is.append(new Vector(startPoint));
-
-               for(Entity * loop=firstEntity(); loop!=NULL; loop=nextEntity())
-               {
-                       if (loop->isContainer())
-                       {
-                               for(Entity * p=((EntityContainer *)loop)->firstEntity(); p!=NULL; p=((EntityContainer*)loop)->nextEntity())
-                               {
-                                       VectorSolutions sol = Information::getIntersection(e, p, true);
-
-                                       for(int i=0; i<=1; ++i)
-                                       {
-                                               if (sol.get(i).valid)
-                                               {
-                                                       is.append(new Vector(sol.get(i)));
-                                                       DEBUG->print("  pattern line intersection: %f/%f", sol.get(i).x, sol.get(i).y);
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               is.append(new Vector(endPoint));
-
-               // sort the intersection points into is2:
-               Vector sp = startPoint;
-               double sa = center.angleTo(sp);
-//             Q3PtrList<Vector> is2;
-               QList<Vector *> is2;
-#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
-//             is2.setAutoDelete(true);
-               bool done;
-               double minDist;
-               double dist = 0.0;
-               Vector * av;
-               Vector last = Vector(false);
-
-               do
-               {
-                       done = true;
-                       minDist = RS_MAXDOUBLE;
-                       av = NULL;
-
-//                     for(Vector * v=is.first(); v!=NULL; v=is.next())
-                       for(int i=0; i<is.size(); i++)
-                       {
-                               Vector * v = is[i];
-
-                               if (line != NULL)
-                               {
-                                       dist = sp.distanceTo(*v);
-                               }
-                               else if (arc != NULL || circle != NULL)
-                               {
-                                       double a = center.angleTo(*v);
-
-                                       if (reversed)
-                                       {
-                                               if (a > sa)
-                                               {
-                                                       a -= 2 * M_PI;
-                                               }
-
-                                               dist = sa - a;
-                                       }
-                                       else
-                                       {
-                                               if (a < sa)
-                                               {
-                                                       a += 2 * M_PI;
-                                               }
-
-                                               dist = a - sa;
-                                       }
-
-                                       if (fabs(dist - 2 * M_PI) < 1.0e-6)
-                                       {
-                                               dist = 0.0;
-                                       }
-                               }
-
-                               if (dist < minDist)
-                               {
-                                       minDist = dist;
-                                       done = false;
-                                       av = v;
-                                       //idx = is.at();
-                               }
-                       }
-
-                       // copy to sorted list, removing double points
-                       if (!done && av != NULL)
-                       {
-                               if (last.valid == false || last.distanceTo(*av) > 1.0e-10)
-                               {
-                                       is2.append(new Vector(*av));
-                                       last = *av;
-                               }
-
-//                             is.remove(av);
-                               int idx = is.indexOf(av);
-
-                               if (idx != -1)
-                                       delete is.takeAt(idx);
-
-                               av = NULL;
-                       }
-               }
-               while(!done);
-
-               // add small cut lines / arcs to tmp2:
-//             for(Vector * v1=is2.first(); v1!=NULL;)
-               Vector * v1 = is2[0];
-
-               for(int i=1; i<is2.size(); i++)
-               {
-//                     Vector * v2 = is2.next();
-                       Vector * v2 = is2[i];
-
-                       if (v1 != NULL && v2 != NULL)
-                       {
-                               if (line != NULL)
-                               {
-                                       tmp2.addEntity(new Line(&tmp2, LineData(*v1, *v2)));
-                               }
-                               else if (arc != NULL || circle != NULL)
-                               {
-                                       tmp2.addEntity(new Arc(&tmp2, ArcData(center, center.distanceTo(*v1),
-                                               center.angleTo(*v1), center.angleTo(*v2), reversed)));
-                               }
-                       }
-
-                       v1 = v2;
-               }
-       }
-
-       // updating hatch / adding entities that are inside
-       DEBUG->print("Hatch::update: cutting pattern carpet: OK");
-
-       // the hatch pattern entities:
-       hatch = new EntityContainer(this);
-       hatch->setPen(Pen(RS2::FlagInvalid));
-       hatch->setLayer(NULL);
-       hatch->setFlag(RS2::FlagTemp);
-
-       //calculateBorders();
-
-       for(Entity * e=tmp2.firstEntity(); e!=NULL; e=tmp2.nextEntity())
-       {
-               Vector middlePoint;
-               Vector middlePoint2;
-
-               if (e->rtti() == RS2::EntityLine)
-               {
-                       Line * line = (Line *)e;
-                       middlePoint = line->getMiddlepoint();
-                       middlePoint2 = line->getNearestDist(line->getLength() / 2.1, line->getStartpoint());
-               }
-               else if (e->rtti() == RS2::EntityArc)
-               {
-                       Arc * arc = (Arc *)e;
-                       middlePoint = arc->getMiddlepoint();
-                       middlePoint2 = arc->getNearestDist(arc->getLength() / 2.1, arc->getStartpoint());
-               }
-               else
-               {
-                       middlePoint = Vector(false);
-                       middlePoint2 = Vector(false);
-               }
-
-               if (middlePoint.valid)
-               {
-                       bool onContour = false;
-
-                       if (Information::isPointInsideContour(middlePoint, this, &onContour)
-                               || Information::isPointInsideContour(middlePoint2, this))
-                       {
-                               Entity * te = e->clone();
-                               te->setPen(Pen(RS2::FlagInvalid));
-                               te->setLayer(NULL);
-                               te->reparent(hatch);
-                               hatch->addEntity(te);
-                       }
-               }
-       }
-
-       addEntity(hatch);
-       //getGraphic()->addEntity(rubbish);
-
-       forcedCalculateBorders();
-
-       // deactivate contour:
-       activateContour(false);
-
-       updateRunning = false;
-
-       DEBUG->print("Hatch::update: OK");
-}
-
-/**
- * Activates of deactivates the hatch boundary.
- */
-void Hatch::activateContour(bool on)
-{
-       DEBUG->print("Hatch::activateContour: %d", (int)on);
-
-       for(Entity * e=firstEntity(); e!=NULL; e=nextEntity())
-       {
-               if (!e->isUndone())
-               {
-                       if (!e->getFlag(RS2::FlagTemp))
-                       {
-                               DEBUG->print("Hatch::activateContour: set visible");
-                               e->setVisible(on);
-                       }
-                       else
-                       {
-                               DEBUG->print("Hatch::activateContour: entity temp");
-                       }
-               }
-               else
-               {
-                       DEBUG->print("Hatch::activateContour: entity undone");
-               }
-       }
-
-       DEBUG->print("Hatch::activateContour: OK");
-}
-
-/**
- * Overrides drawing of subentities. This is only ever called for solid fills.
- */
-void Hatch::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
-{
-       if (!data.solid)
-       {
-               for(Entity * se=firstEntity(); se!=NULL; se = nextEntity())
-                       view->drawEntity(se);
-
-               return;
-       }
-
-//     Q3PointArray pa;
-//     Q3PointArray jp;   // jump points
-       QPolygon pa;
-       QPolygon jp;   // jump points
-       uint s = 0;
-       uint sj = 0;
-       int lastX = 0;
-       int lastY = 0;
-       bool lastValid = false;
-
-       // loops:
-       if (needOptimization == true)
-       {
-               for(Entity * l=firstEntity(RS2::ResolveNone); l!=NULL; l=nextEntity(RS2::ResolveNone))
-               {
-                       if (l->rtti() == RS2::EntityContainer)
-                       {
-                               EntityContainer * loop = (EntityContainer *)l;
-                               loop->optimizeContours();
-                       }
-               }
-
-               needOptimization = false;
-       }
-
-       // loops:
-       for(Entity * l=firstEntity(RS2::ResolveNone); l!=NULL; l=nextEntity(RS2::ResolveNone))
-       {
-               l->setLayer(getLayer());
-
-               if (l->rtti() == RS2::EntityContainer)
-               {
-                       EntityContainer * loop = (EntityContainer *)l;
-
-                       // edges:
-                       for(Entity * e=loop->firstEntity(RS2::ResolveNone); e!=NULL; e=loop->nextEntity(RS2::ResolveNone))
-                       {
-                               e->setLayer(getLayer());
-
-                               switch (e->rtti())
-                               {
-                               case RS2::EntityLine:
-                               {
-                                       Line * line = (Line *)e;
-
-                                       int x1 = Math::round(view->toGuiX(line->getStartpoint().x));
-                                       int y1 = Math::round(view->toGuiY(line->getStartpoint().y));
-                                       int x2 = Math::round(view->toGuiX(line->getEndpoint().x));
-                                       int y2 = Math::round(view->toGuiY(line->getEndpoint().y));
-
-                                       if (lastValid && (lastX != x1 || lastY != y1))
-                                       {
-                                               jp.resize(++sj);
-                                               jp.setPoint(sj - 1, x1, y1);
-                                       }
-
-                                       pa.resize(++s);
-                                       pa.setPoint(s - 1, x1, y1);
-
-                                       pa.resize(++s);
-                                       pa.setPoint(s - 1, x2, y2);
-
-                                       lastX = x2;
-                                       lastY = y2;
-                                       lastValid = true;
-                               }
-                                       break;
-
-                               case RS2::EntityArc:
-                               {
-                                       Arc * arc = (Arc *)e;
-
-                                       int x1 = Math::round(view->toGuiX(arc->getStartpoint().x));
-                                       int y1 = Math::round(view->toGuiY(arc->getStartpoint().y));
-                                       int x2 = Math::round(view->toGuiX(arc->getEndpoint().x));
-                                       int y2 = Math::round(view->toGuiY(arc->getEndpoint().y));
-
-                                       if (lastValid && (lastX != x1 || lastY != y1))
-                                       {
-                                               jp.resize(++sj);
-                                               jp.setPoint(sj - 1, x1, y1);
-                                       }
-
-                                       pa.resize(++s);
-                                       pa.setPoint(s - 1, x1, y1);
-
-//                                     Q3PointArray pa2;
-                                       QPolygon pa2;
-                                       painter->createArc(pa2, view->toGui(arc->getCenter()),
-                                               view->toGuiDX(arc->getRadius()), arc->getAngle1(),
-                                               arc->getAngle2(), arc->isReversed());
-
-                                       pa.resize(s + pa2.size());
-                                       pa.putPoints(s, pa2.size(), pa2);
-                                       s += pa2.size() - 1;
-
-                                       pa.resize(++s);
-                                       pa.setPoint(s - 1, x2, y2);
-
-                                       lastX = x2;
-                                       lastY = y2;
-                                       lastValid = true;
-                               }
-                                       break;
-
-                               case RS2::EntityCircle:
-                               {
-                                       Circle * circle = (Circle *)e;
-
-                                       int x1 = Math::round(view->toGuiX(circle->getCenter().x + circle->getRadius()));
-                                       int y1 = Math::round(view->toGuiY(circle->getCenter().y));
-                                       int x2 = x1;
-                                       int y2 = y1;
-
-                                       if (lastValid && (lastX != x1 || lastY != y1))
-                                       {
-                                               jp.resize(++sj);
-                                               jp.setPoint(sj - 1, x1, y1);
-                                       }
-
-                                       pa.resize(++s);
-                                       pa.setPoint(s - 1, x1, y1);
-
-//                                     Q3PointArray pa2;
-                                       QPolygon pa2;
-                                       painter->createArc(pa2, view->toGui(circle->getCenter()),
-                                               view->toGuiDX(circle->getRadius()), 0.0, 2 * M_PI, false);
-
-                                       pa.resize(s + pa2.size());
-                                       pa.putPoints(s, pa2.size(), pa2);
-                                       s += pa2.size() - 1;
-
-                                       pa.resize(++s);
-                                       pa.setPoint(s - 1, x2, y2);
-
-                                       lastX = x2;
-                                       lastY = y2;
-                                       lastValid = true;
-                               }
-                                       break;
-
-                               default:
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       for(int i=(int)jp.count()-1; i>=0; --i)
-       {
-               pa.resize(++s);
-               pa.setPoint(s - 1, jp.point(i));
-       }
-
-       painter->setBrush(painter->getPen().getColor());
-       painter->disablePen();
-       painter->drawPolygon(pa);
-}
-
-/*virtual*/ double Hatch::getLength()
-{
-       return -1.0;
-}
-
-double Hatch::getDistanceToPoint(const Vector & coord, Entity ** entity,
-       RS2::ResolveLevel level, double solidDist)
-{
-       if (data.solid == true)
-       {
-               if (entity != NULL)
-                       *entity = this;
-
-               bool onContour;
-
-               if (Information::isPointInsideContour(coord, this, &onContour))
-                       // distance is the snap range:
-                       return solidDist;
-
-               return RS_MAXDOUBLE;
-       }
-       else
-       {
-               return EntityContainer::getDistanceToPoint(coord, entity, level, solidDist);
-       }
-}
-
-void Hatch::move(Vector offset)
-{
-       EntityContainer::move(offset);
-       update();
-}
-
-void Hatch::rotate(Vector center, double angle)
-{
-       EntityContainer::rotate(center, angle);
-       data.angle = Math::correctAngle(data.angle + angle);
-       update();
-}
-
-void Hatch::scale(Vector center, Vector factor)
-{
-       EntityContainer::scale(center, factor);
-       data.scale *= factor.x;
-       update();
-}
-
-void Hatch::mirror(Vector axisPoint1, Vector axisPoint2)
-{
-       EntityContainer::mirror(axisPoint1, axisPoint2);
-       double ang = axisPoint1.angleTo(axisPoint2);
-       data.angle = Math::correctAngle(data.angle + ang*2.0);
-       update();
-}
-
-void Hatch::stretch(Vector firstCorner, Vector secondCorner, Vector offset)
-{
-       EntityContainer::stretch(firstCorner, secondCorner, offset);
-       update();
-}
-
-/**
- * Dumps the point's data to stdout.
- */
-std::ostream & operator<<(std::ostream & os, const Hatch & p)
-{
-       os << " Hatch: " << p.getData() << "\n";
-       return os;
-}