X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fbase%2Fhatch.cpp;fp=src%2Fbase%2Fhatch.cpp;h=0000000000000000000000000000000000000000;hb=9f6ad3fe0b9cb30115a5d38e8af3aebed0d70c08;hp=f7442deb5eb6e5658f421713be0c67e820558e5c;hpb=43c13b052d069ba435277d93867380d00c04931f;p=architektonas diff --git a/src/base/hatch.cpp b/src/base/hatch.cpp deleted file mode 100644 index f7442de..0000000 --- a/src/base/hatch.cpp +++ /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 -// -// Who When What -// --- ---------- ----------------------------------------------------------- -// JLH 05/28/2010 Added this text. :-) -// - -#include "hatch.h" - -#include -#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 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 is2; - QList 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 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; iprint("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; -}