📄 rs_hatch.cpp
字号:
/****************************************************************************** $Id: rs_hatch.cpp 2367 2005-04-04 16:57:36Z andrew $**** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.**** This file is part of the qcadlib Library project.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.ribbonsoft.com for further details.**** Contact info@ribbonsoft.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "rs_hatch.h"#include "rs_graphicview.h"#include "rs_graphic.h"#include "rs_information.h"#include "rs_painter.h"#include "rs_painterqt.h"#include "rs_pointarray.h"#include "rs_pattern.h"#include "rs_patternlist.h"#include <qptrvector.h>/** * Constructor. */RS_Hatch::RS_Hatch(RS_EntityContainer* parent, const RS_HatchData& d) : RS_EntityContainer(parent), data(d) { hatch = NULL; updateRunning = false; needOptimization = true;}/** * Validates the hatch. */bool RS_Hatch::validate() { bool ret = true; // loops: for (RS_Entity* l=firstEntity(RS2::ResolveNone); l!=NULL; l=nextEntity(RS2::ResolveNone)) { if (l->rtti()==RS2::EntityContainer) { RS_EntityContainer* loop = (RS_EntityContainer*)l; ret = loop->optimizeContours() && ret; } } return ret;} RS_Entity* RS_Hatch::clone() { RS_Hatch* t = new RS_Hatch(*this); t->entities.setAutoDelete(entities.autoDelete()); t->initId(); t->detach(); t->hatch = NULL; return t;}/** * @return Number of loops. */int RS_Hatch::countLoops() { if (data.solid) { return count(); } else { return count() - 1; }}/** * Recalculates the borders of this hatch. */void RS_Hatch::calculateBorders() { RS_DEBUG->print("RS_Hatch::calculateBorders"); activateContour(true); RS_EntityContainer::calculateBorders(); RS_DEBUG->print("RS_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 RS_Hatch::update() { RS_DEBUG->print("RS_Hatch::update"); RS_DEBUG->print("RS_Hatch::update: contour has %d loops", count());#if QT_VERSION>=0x030000 if (updateRunning) { return; } if (updateEnabled==false) { return; } if (data.solid==true) { return; } RS_DEBUG->print("RS_Hatch::update"); updateRunning = true; // delete old hatch: if (hatch!=NULL) { removeEntity(hatch); hatch = NULL; } if (isUndone()) { updateRunning = false; return; } if (!validate()) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Hatch::update: invalid contour in hatch found"); updateRunning = false; return; } // search pattern: RS_DEBUG->print("RS_Hatch::update: requesting pattern"); RS_Pattern* pat = RS_PATTERNLIST->requestPattern(data.pattern); if (pat==NULL) { updateRunning = false; RS_DEBUG->print("RS_Hatch::update: requesting pattern: not found"); return; } RS_DEBUG->print("RS_Hatch::update: requesting pattern: OK"); RS_DEBUG->print("RS_Hatch::update: cloning pattern"); pat = (RS_Pattern*)pat->clone(); RS_DEBUG->print("RS_Hatch::update: cloning pattern: OK"); // scale pattern RS_DEBUG->print("RS_Hatch::update: scaling pattern"); pat->scale(RS_Vector(0.0,0.0), RS_Vector(data.scale, data.scale)); pat->calculateBorders(); forcedCalculateBorders(); RS_DEBUG->print("RS_Hatch::update: scaling pattern: OK"); // find out how many pattern-instances we need in x/y: int px1, py1, px2, py2; double f; RS_Hatch* copy = (RS_Hatch*)this->clone(); copy->rotate(RS_Vector(0.0,0.0), -data.angle); copy->forcedCalculateBorders(); // create a pattern over the whole contour. RS_Vector pSize = pat->getSize(); RS_Vector cPos = getMin(); RS_Vector cSize = getSize(); RS_DEBUG->print("RS_Hatch::update: pattern size: %f/%f", pSize.x, pSize.y); RS_DEBUG->print("RS_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; RS_DEBUG->print("RS_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) { RS_DEBUG->print("RS_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; RS_EntityContainer tmp; // container for untrimmed lines // adding array of patterns to tmp: RS_DEBUG->print("RS_Hatch::update: creating pattern carpet"); for (int px=px1; px<=px2; px++) { for (int py=py1; py<=py2; py++) { for (RS_Entity* e=pat->firstEntity(); e!=NULL; e=pat->nextEntity()) { RS_Entity* te = e->clone(); te->rotate(RS_Vector(0.0,0.0), data.angle); RS_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; RS_DEBUG->print("RS_Hatch::update: creating pattern carpet: OK"); RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet"); // cut pattern to contour shape: RS_EntityContainer tmp2; // container for small cut lines RS_Line* line = NULL; RS_Arc* arc = NULL; RS_Circle* circle = NULL; for (RS_Entity* e=tmp.firstEntity(); e!=NULL; e=tmp.nextEntity()) { RS_Vector startPoint; RS_Vector endPoint; RS_Vector center = RS_Vector(false); bool reversed; if (e->rtti()==RS2::EntityLine) { line = (RS_Line*)e; arc = NULL; circle = NULL; startPoint = line->getStartpoint(); endPoint = line->getEndpoint(); center = RS_Vector(false); reversed = false; } else if (e->rtti()==RS2::EntityArc) { arc = (RS_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 = (RS_Circle*)e; line = NULL; arc = NULL; startPoint = circle->getCenter() + RS_Vector(circle->getRadius(), 0.0); endPoint = startPoint; center = circle->getCenter(); reversed = false; } else { continue; } // getting all intersections of this pattern line with the contour: RS_PtrList<RS_Vector> is; is.setAutoDelete(true); is.append(new RS_Vector(startPoint)); for (RS_Entity* loop=firstEntity(); loop!=NULL; loop=nextEntity()) { if (loop->isContainer()) { for (RS_Entity* p=((RS_EntityContainer*)loop)->firstEntity(); p!=NULL; p=((RS_EntityContainer*)loop)->nextEntity()) { RS_VectorSolutions sol = RS_Information::getIntersection(e, p, true); for (int i=0; i<=1; ++i) { if (sol.get(i).valid) { is.append(new RS_Vector(sol.get(i))); RS_DEBUG->print(" pattern line intersection: %f/%f", sol.get(i).x, sol.get(i).y); } } } } } is.append(new RS_Vector(endPoint)); // sort the intersection points into is2: RS_Vector sp = startPoint; double sa = center.angleTo(sp); RS_PtrList<RS_Vector> is2; is2.setAutoDelete(true); bool done; double minDist; double dist = 0.0; RS_Vector* av; RS_Vector last = RS_Vector(false); do { done = true; minDist = RS_MAXDOUBLE; av = NULL; for (RS_Vector* v = is.first(); v!=NULL; v = is.next()) { 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 RS_Vector(*av)); last = *av; } is.remove(av); av = NULL; } } while(!done); // add small cut lines / arcs to tmp2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -