/**************************************************************************** ** $Id: rs_creation.cpp 1938 2004-12-09 23:09:53Z 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_creation.h" #include "rs_information.h" #include "rs_fileinfo.h" #include "rs_graphic.h" #include "rs_constructionline.h" #include "rs_graphicview.h" #include "rs_modification.h" /** * Default constructor. * * @param container The container to which we will add * entities. Usually that's an RS_Graphic entity but * it can also be a polyline, text, ... */ RS_Creation::RS_Creation(RS_EntityContainer* container, RS_GraphicView* graphicView, bool handleUndo) { this->container = container; this->graphicView = graphicView; this->handleUndo = handleUndo; if (container!=NULL) { graphic = container->getGraphic(); document = container->getDocument(); } else { graphic = NULL; document = NULL; } } /** * Creates a point entity. * * E.g.:
* * creation.createPoint(RS_Vector(10.0, 15.0)); * * * @param p position */ /*void RS_Creation::createPoint(const RS_Vector& p) { entityContainer->addEntity(new RS_Point(entityContainer, p)); }*/ /** * Creates a line with two points given. * * E.g.:
* * creation.createLine2P(RS_Vector(10.0, 10.0), RS_Vector(100.0, 200.0)); * * * @param p1 start point * @param p2 end point */ /*void RS_Creation::createLine2P(const RS_Vector& p1, const RS_Vector& p2) { entityContainer->addEntity(new RS_Line(entityContainer, RS_LineData(p1, p2))); }*/ /** * Creates a rectangle with two edge points given. * * E.g.:
* * creation.createRectangle(RS_Vector(5.0, 2.0), RS_Vector(7.5, 3.0)); * * * @param p1 edge one * @param p2 edge two */ /*void RS_Creation::createRectangle(const RS_Vector& e1, const RS_Vector& e2) { RS_Vector e21(e2.x, e1.y); RS_Vector e12(e1.x, e2.y); entityContainer->addEntity(new RS_Line(entityContainer, RS_LineData(e1, e12))); entityContainer->addEntity(new RS_Line(entityContainer, RS_LineData(e12, e2))); entityContainer->addEntity(new RS_Line(entityContainer, RS_LineData(e2, e21))); entityContainer->addEntity(new RS_Line(entityContainer, RS_LineData(e21, e1))); }*/ /** * Creates a polyline from the given array of entities. * No checking if the entities actually fit together. * Currently this is like a group. * * E.g.:
* * RS_Polyline *pl = creation.createPolyline(RS_Vector(25.0, 55.0));
* pl->addVertex(RS_Vector(50.0, 75.0));
*
* * @param entities array of entities * @param startPoint Start point of the polyline */ /*RS_Polyline* RS_Creation::createPolyline(const RS_Vector& startPoint) { RS_Polyline* pl = new RS_Polyline(entityContainer, RS_PolylineData(startPoint, RS_Vector(0.0,0.0), 0)); entityContainer->addEntity(pl); return pl; }*/ /** * Creates an entity parallel to the given entity e through the given * 'coord'. * * @param coord Coordinate to define the distance / side (typically a * mouse coordinate). * @param number Number of parallels. * @param e Original entity. * * @return Pointer to the first created parallel or NULL if no * parallel has been created. */ RS_Entity* RS_Creation::createParallelThrough(const RS_Vector& coord, int number, RS_Entity* e) { if (e==NULL) { return NULL; } double dist; if (e->rtti()==RS2::EntityLine) { RS_Line* l = (RS_Line*)e; RS_ConstructionLine cl(NULL, RS_ConstructionLineData(l->getStartpoint(), l->getEndpoint())); dist = cl.getDistanceToPoint(coord); } else { dist = e->getDistanceToPoint(coord); } if (distrtti()) { case RS2::EntityLine: return createParallelLine(coord, distance, number, (RS_Line*)e); break; case RS2::EntityArc: return createParallelArc(coord, distance, number, (RS_Arc*)e); break; case RS2::EntityCircle: return createParallelCircle(coord, distance, number, (RS_Circle*)e); break; default: break; } return NULL; } /** * Creates a line parallel to the given line e. * Out of the 2 possible parallels, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which parallel we want (typically a * mouse coordinate). * @param distance Distance of the parallel. * @param number Number of parallels. * @param e Original entity. * * @return Pointer to the first created parallel or NULL if no * parallel has been created. */ RS_Line* RS_Creation::createParallelLine(const RS_Vector& coord, double distance, int number, RS_Line* e) { if (e==NULL) { return NULL; } double ang = e->getAngle1() + M_PI/2.0; RS_Vector p1, p2; RS_LineData parallelData; RS_Line* ret = NULL; if (document!=NULL && handleUndo) { document->startUndoCycle(); } for (int num=1; num<=number; ++num) { // calculate 1st parallel: p1.setPolar(distance*num, ang); p1 += e->getStartpoint(); p2.setPolar(distance*num, ang); p2 += e->getEndpoint(); RS_Line parallel1(NULL, RS_LineData(p1, p2)); // calculate 2nd parallel: p1.setPolar(distance*num, ang+M_PI); p1 += e->getStartpoint(); p2.setPolar(distance*num, ang+M_PI); p2 += e->getEndpoint(); RS_Line parallel2(NULL, RS_LineData(p1, p2)); double dist1 = parallel1.getDistanceToPoint(coord); double dist2 = parallel2.getDistanceToPoint(coord); double minDist = std::min(dist1, dist2); if (minDistsetLayerToActive(); newLine->setPenToActive(); if (ret==NULL) { ret = newLine; } if (container!=NULL) { container->addEntity(newLine); } if (document!=NULL && handleUndo) { document->addUndoable(newLine); //document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(newLine); } } } if (document!=NULL && handleUndo) { document->endUndoCycle(); } return ret; } /** * Creates a arc parallel to the given arc e. * Out of the 2 possible parallels, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which parallel we want (typically a * mouse coordinate). * @param distance Distance of the parallel. * @param number Number of parallels. * @param e Original entity. * * @return Pointer to the first created parallel or NULL if no * parallel has been created. */ RS_Arc* RS_Creation::createParallelArc(const RS_Vector& coord, double distance, int number, RS_Arc* e) { if (e==NULL) { return NULL; } RS_ArcData parallelData; RS_Arc* ret = NULL; bool inside = (e->getCenter().distanceTo(coord) < e->getRadius()); if (inside) { distance *= -1; } for (int num=1; num<=number; ++num) { // calculate parallel: bool ok = true; RS_Arc parallel1(NULL, e->getData()); parallel1.setRadius(e->getRadius() + distance*num); if (parallel1.getRadius()<0.0) { parallel1.setRadius(RS_MAXDOUBLE); ok = false; } // calculate 2nd parallel: //RS_Arc parallel2(NULL, e->getData()); //parallel2.setRadius(e->getRadius()+distance*num); //double dist1 = parallel1.getDistanceToPoint(coord); //double dist2 = parallel2.getDistanceToPoint(coord); //double minDist = min(dist1, dist2); //if (minDiststartUndoCycle(); } RS_Arc* newArc = new RS_Arc(container, parallelData); newArc->setLayerToActive(); newArc->setPenToActive(); if (ret==NULL) { ret = newArc; } if (container!=NULL) { container->addEntity(newArc); } if (document!=NULL && handleUndo) { document->addUndoable(newArc); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(newArc); } } } return ret; } /** * Creates a circle parallel to the given circle e. * Out of the 2 possible parallels, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which parallel we want (typically a * mouse coordinate). * @param distance Distance of the parallel. * @param number Number of parallels. * @param e Original entity. * * @return Pointer to the first created parallel or NULL if no * parallel has been created. */ RS_Circle* RS_Creation::createParallelCircle(const RS_Vector& coord, double distance, int number, RS_Circle* e) { if (e==NULL) { return NULL; } RS_CircleData parallelData; RS_Circle* ret = NULL; bool inside = (e->getCenter().distanceTo(coord) < e->getRadius()); if (inside) { distance *= -1; } for (int num=1; num<=number; ++num) { // calculate parallel: bool ok = true; RS_Circle parallel1(NULL, e->getData()); parallel1.setRadius(e->getRadius() + distance*num); if (parallel1.getRadius()<0.0) { parallel1.setRadius(RS_MAXDOUBLE); ok = false; } // calculate 2nd parallel: //RS_Circle parallel2(NULL, e->getData()); //parallel2.setRadius(e->getRadius()+distance*num); //double dist1 = parallel1.getDistanceToPoint(coord); //double dist2 = parallel2.getDistanceToPoint(coord); //double minDist = min(dist1, dist2); //if (minDiststartUndoCycle(); } RS_Circle* newCircle = new RS_Circle(container, parallelData); newCircle->setLayerToActive(); newCircle->setPenToActive(); if (ret==NULL) { ret = newCircle; } if (container!=NULL) { container->addEntity(newCircle); } if (document!=NULL && handleUndo) { document->addUndoable(newCircle); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(newCircle); } } } return ret; } /** * Creates a bisecting line of the angle between the entities * e1 and e2. Out of the 4 possible bisectors, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which bisector we want (typically a * mouse coordinate). * @param length Length of the bisecting line. * @param num Number of bisectors * @param l1 First line. * @param l2 Second line. * * @return Pointer to the first bisector created or NULL if no bisectors * were created. */ RS_Line* RS_Creation::createBisector(const RS_Vector& coord1, const RS_Vector& coord2, double length, int num, RS_Line* l1, RS_Line* l2) { RS_VectorSolutions sol; // check given entities: if (l1==NULL || l2==NULL || l1->rtti()!=RS2::EntityLine || l2->rtti()!=RS2::EntityLine) { return NULL; } // intersection between entities: sol = RS_Information::getIntersection(l1, l2, false); RS_Vector inters = sol.get(0); if (inters.valid==false) { return NULL; } double angle1 = inters.angleTo(l1->getNearestPointOnEntity(coord1)); double angle2 = inters.angleTo(l2->getNearestPointOnEntity(coord2)); double angleDiff = RS_Math::getAngleDifference(angle1, angle2); if (angleDiff>M_PI) { angleDiff = angleDiff - 2*M_PI; } RS_Line* ret = NULL; if (document!=NULL && handleUndo) { document->startUndoCycle(); } for (int n=1; n<=num; ++n) { double angle = angle1 + (angleDiff / (num+1) * n); RS_LineData d; RS_Vector v; RS_Vector c; v.setPolar(length, angle); d = RS_LineData(inters, inters + v); RS_Line* newLine = new RS_Line(container, d); if (container!=NULL) { newLine->setLayerToActive(); newLine->setPenToActive(); container->addEntity(newLine); } if (document!=NULL && handleUndo) { document->addUndoable(newLine); } if (graphicView!=NULL) { graphicView->drawEntity(newLine); } if (ret==NULL) { ret = newLine; } } if (document!=NULL && handleUndo) { document->endUndoCycle(); } return ret; } /** * Creates a tangent between a given point and a circle or arc. * Out of the 2 possible tangents, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which tangent we want (typically a * mouse coordinate). * @param point Point. * @param circle Circle, arc or ellipse entity. */ RS_Line* RS_Creation::createTangent1(const RS_Vector& coord, const RS_Vector& point, RS_Entity* circle) { RS_Line* ret = NULL; RS_Vector circleCenter; // check given entities: if (circle==NULL || !point.valid || (circle->rtti()!=RS2::EntityArc && circle->rtti()!=RS2::EntityCircle && circle->rtti()!=RS2::EntityEllipse)) { return NULL; } if (circle->rtti()==RS2::EntityCircle) { circleCenter = ((RS_Circle*)circle)->getCenter(); } else if (circle->rtti()==RS2::EntityArc) { circleCenter = ((RS_Arc*)circle)->getCenter(); } else if (circle->rtti()==RS2::EntityEllipse) { circleCenter = ((RS_Ellipse*)circle)->getCenter(); } // the two tangent points: RS_VectorSolutions sol; // calculate tangent points for arcs / circles: if (circle->rtti()!=RS2::EntityEllipse) { // create temp. thales circle: RS_Vector tCenter = (point + circleCenter)/2.0; double tRadius = point.distanceTo(tCenter); RS_Circle tmp(NULL, RS_CircleData(tCenter, tRadius)); // get the two intersection points which are the tangent points: sol = RS_Information::getIntersection(&tmp, circle, false); } // calculate tangent points for ellipses: else { RS_Ellipse* el = (RS_Ellipse*)circle; sol.alloc(2); //sol.set(0, circleCenter); //sol.set(1, circleCenter); double a = el->getMajorRadius(); // the length of the major axis / 2 double b = el->getMinorRadius(); // the length of the minor axis / 2 // rotate and move point: RS_Vector point2 = point; point2.move(-el->getCenter()); point2.rotate(-el->getAngle()); double xp = point2.x; // coordinates of the given point double yp = point2.y; double xt1; // Tangent point 1 double yt1; double xt2; // Tangent point 2 double yt2; double a2 = a * a; double b2 = b * b; double d = a2 / b2 * yp / xp; double e = a2 / xp; double af = b2 * d * d + a2; double bf = -b2 * d * e * 2.0; double cf = b2 * e * e - a2 * b2; double t = sqrt(bf * bf - af * cf * 4.0); yt1 = (t - bf) / (af * 2.0); xt1 = e - d * yt1; yt2 = (-t - bf) / (af * 2.0); xt2 = e - d * yt2; RS_Vector s1 = RS_Vector(xt1, yt1); RS_Vector s2 = RS_Vector(xt2, yt2); s1.rotate(el->getAngle()); s1.move(el->getCenter()); s2.rotate(el->getAngle()); s2.move(el->getCenter()); sol.set(0, s1); sol.set(1, s2); } if (!sol.get(0).valid || !sol.get(1).valid) { return NULL; } // create all possible tangents: RS_Line* poss[2]; RS_LineData d; d = RS_LineData(sol.get(0), point); poss[0] = new RS_Line(NULL, d); d = RS_LineData(sol.get(1), point); poss[1] = new RS_Line(NULL, d); // find closest tangent: double minDist = RS_MAXDOUBLE; double dist; int idx = -1; for (int i=0; i<2; ++i) { dist = poss[i]->getDistanceToPoint(coord); if (distgetData(); for (int i=0; i<2; ++i) { delete poss[i]; } if (document!=NULL && handleUndo) { document->startUndoCycle(); } ret = new RS_Line(container, d); ret->setLayerToActive(); ret->setPenToActive(); if (container!=NULL) { container->addEntity(ret); } if (document!=NULL && handleUndo) { document->addUndoable(ret); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(ret); } } else { ret = NULL; } return ret; } /** * Creates a tangent between two circles or arcs. * Out of the 4 possible tangents, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which tangent we want (typically a * mouse coordinate). * @param circle1 1st circle or arc entity. * @param circle2 2nd circle or arc entity. */ RS_Line* RS_Creation::createTangent2(const RS_Vector& coord, RS_Entity* circle1, RS_Entity* circle2) { RS_Line* ret = NULL; RS_Vector circleCenter1; RS_Vector circleCenter2; double circleRadius1 = 0.0; double circleRadius2 = 0.0; // check given entities: if (circle1==NULL || circle2==NULL || (circle1->rtti()!=RS2::EntityArc && circle1->rtti()!=RS2::EntityCircle) || (circle2->rtti()!=RS2::EntityArc && circle2->rtti()!=RS2::EntityCircle) ) { return NULL; } if (circle1->rtti()==RS2::EntityCircle) { circleCenter1 = ((RS_Circle*)circle1)->getCenter(); circleRadius1 = ((RS_Circle*)circle1)->getRadius(); } else if (circle1->rtti()==RS2::EntityArc) { circleCenter1 = ((RS_Arc*)circle1)->getCenter(); circleRadius1 = ((RS_Arc*)circle1)->getRadius(); } if (circle2->rtti()==RS2::EntityCircle) { circleCenter2 = ((RS_Circle*)circle2)->getCenter(); circleRadius2 = ((RS_Circle*)circle2)->getRadius(); } else if (circle2->rtti()==RS2::EntityArc) { circleCenter2 = ((RS_Arc*)circle2)->getCenter(); circleRadius2 = ((RS_Arc*)circle2)->getRadius(); } // create all possible tangents: RS_Line* poss[4]; for (int i=0; i<4; ++i) { poss[i] = NULL; } RS_LineData d; double angle1 = circleCenter1.angleTo(circleCenter2); double dist1 = circleCenter1.distanceTo(circleCenter2); if (dist1>1.0e-6) { // outer tangents: double dist2 = circleRadius2 - circleRadius1; if (dist1>dist2) { double angle2 = asin(dist2/dist1); double angt1 = angle1 + angle2 + M_PI/2.0; double angt2 = angle1 - angle2 - M_PI/2.0; RS_Vector offs1; RS_Vector offs2; offs1.setPolar(circleRadius1, angt1); offs2.setPolar(circleRadius2, angt1); d = RS_LineData(circleCenter1 + offs1, circleCenter2 + offs2); poss[0] = new RS_Line(NULL, d); offs1.setPolar(circleRadius1, angt2); offs2.setPolar(circleRadius2, angt2); d = RS_LineData(circleCenter1 + offs1, circleCenter2 + offs2); poss[1] = new RS_Line(NULL, d); } // inner tangents: double dist3 = circleRadius2 + circleRadius1; if (dist1>dist3) { double angle3 = asin(dist3/dist1); double angt3 = angle1 + angle3 + M_PI/2.0; double angt4 = angle1 - angle3 - M_PI/2.0; RS_Vector offs1; RS_Vector offs2; offs1.setPolar(circleRadius1, angt3); offs2.setPolar(circleRadius2, angt3); d = RS_LineData(circleCenter1 - offs1, circleCenter2 + offs2); poss[2] = new RS_Line(NULL, d); offs1.setPolar(circleRadius1, angt4); offs2.setPolar(circleRadius2, angt4); d = RS_LineData(circleCenter1 - offs1, circleCenter2 + offs2); poss[3] = new RS_Line(NULL, d); } } // find closest tangent: double minDist = RS_MAXDOUBLE; double dist; int idx = -1; for (int i=0; i<4; ++i) { if (poss[i]!=NULL) { dist = poss[i]->getDistanceToPoint(coord); if (distgetData(); for (int i=0; i<4; ++i) { if (poss[i]!=NULL) { delete poss[i]; } } if (document!=NULL && handleUndo) { document->startUndoCycle(); } ret = new RS_Line(container, d); ret->setLayerToActive(); ret->setPenToActive(); if (container!=NULL) { container->addEntity(ret); } if (document!=NULL && handleUndo) { document->addUndoable(ret); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(ret); } } else { ret = NULL; } return ret; } /** * Creates a line with a relative angle to the given entity. * * @param coord Coordinate to define the point where the line should end. * (typically a mouse coordinate). * @param entity Pointer to basis entity. The angle is relative to the * angle of this entity. * @param angle Angle of the line relative to the angle of the basis entity. * @param length Length of the line we're creating. */ RS_Line* RS_Creation::createLineRelAngle(const RS_Vector& coord, RS_Entity* entity, double angle, double length) { // check given entity / coord: if (entity==NULL || !coord.valid || (entity->rtti()!=RS2::EntityArc && entity->rtti()!=RS2::EntityCircle && entity->rtti()!=RS2::EntityLine)) { return NULL; } double a1=0.0; switch (entity->rtti()) { case RS2::EntityLine: a1 = ((RS_Line*)entity)->getAngle1(); break; case RS2::EntityArc: a1 = ((RS_Arc*)entity)->getCenter().angleTo(coord) + M_PI/2.0; break; case RS2::EntityCircle: a1 = ((RS_Circle*)entity)->getCenter().angleTo(coord); break; default: // never reached break; } a1 += angle; RS_Vector v1; v1.setPolar(length, a1); //RS_ConstructionLineData(coord-v1, coord+v1); RS_LineData d(coord-v1, coord+v1); RS_Line* ret; if (document!=NULL && handleUndo) { document->startUndoCycle(); } ret = new RS_Line(container, d); ret->setLayerToActive(); ret->setPenToActive(); if (container!=NULL) { container->addEntity(ret); } if (document!=NULL && handleUndo) { document->addUndoable(ret); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(ret); } return ret; } /** * Creates a polygon with 'number' edges. * * @param center Center of the polygon. * @param corner The first corner of the polygon * @param number Number of edges / corners. */ RS_Line* RS_Creation::createPolygon(const RS_Vector& center, const RS_Vector& corner, int number) { // check given coords / number: if (!center.valid || !corner.valid || number<3) { return NULL; } RS_Line* ret = NULL; if (document!=NULL && handleUndo) { document->startUndoCycle(); } RS_Vector c1(false); RS_Vector c2 = corner; RS_Line* line; for (int n=1; n<=number; ++n) { c1 = c2; c2 = c2.rotate(center, (M_PI*2)/number); line = new RS_Line(container, RS_LineData(c1, c2)); line->setLayerToActive(); line->setPenToActive(); if (ret==NULL) { ret = line; } if (container!=NULL) { container->addEntity(line); } if (document!=NULL && handleUndo) { document->addUndoable(line); } if (graphicView!=NULL) { graphicView->drawEntity(line); } } if (document!=NULL && handleUndo) { document->endUndoCycle(); } return ret; } /** * Creates a polygon with 'number' edges. * * @param corner1 The first corner of the polygon. * @param corner2 The second corner of the polygon. * @param number Number of edges / corners. */ RS_Line* RS_Creation::createPolygon2(const RS_Vector& corner1, const RS_Vector& corner2, int number) { // check given coords / number: if (!corner1.valid || !corner2.valid || number<3) { return NULL; } RS_Line* ret = NULL; if (document!=NULL && handleUndo) { document->startUndoCycle(); } double len = corner1.distanceTo(corner2); double ang1 = corner1.angleTo(corner2); double ang = ang1; RS_Vector c1(false); RS_Vector c2 = corner1; RS_Vector edge; RS_Line* line; for (int n=1; n<=number; ++n) { c1 = c2; edge.setPolar(len, ang); c2 = c1 + edge; line = new RS_Line(container, RS_LineData(c1, c2)); line->setLayerToActive(); line->setPenToActive(); if (ret==NULL) { ret = line; } if (container!=NULL) { container->addEntity(line); } if (document!=NULL && handleUndo) { document->addUndoable(line); } if (graphicView!=NULL) { graphicView->drawEntity(line); } // more accurate than incrementing the angle: ang = ang1 + (2*M_PI)/number*n; } if (document!=NULL && handleUndo) { document->endUndoCycle(); } return ret; } /** * Creates an insert with the given data. * * @param data Insert data (position, block name, ..) */ RS_Insert* RS_Creation::createInsert(RS_InsertData& data) { RS_DEBUG->print("RS_Creation::createInsert"); if (document!=NULL && handleUndo) { document->startUndoCycle(); } RS_Insert* ins = new RS_Insert(container, data); // inserts are also on layers ins->setLayerToActive(); ins->setPenToActive(); if (container!=NULL) { container->addEntity(ins); } if (document!=NULL && handleUndo) { document->addUndoable(ins); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(ins); } RS_DEBUG->print("RS_Creation::createInsert: OK"); return ins; } /** * Creates an image with the given data. */ RS_Image* RS_Creation::createImage(RS_ImageData& data) { if (document!=NULL && handleUndo) { document->startUndoCycle(); } RS_Image* img = new RS_Image(container, data); img->setLayerToActive(); img->setPenToActive(); img->update(); if (container!=NULL) { container->addEntity(img); } if (document!=NULL && handleUndo) { document->addUndoable(img); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(img); } return img; } /** * Creates a new block from the currently selected entitiies. * * @param referencePoint Reference point for the block. * @param name Block name * @param remove true: remove existing entities, false: don't touch entities */ RS_Block* RS_Creation::createBlock(const RS_BlockData& data, const RS_Vector& referencePoint, const bool remove) { // start undo cycle for the container if we're deleting the existing entities if (remove && document!=NULL) { document->startUndoCycle(); } RS_Block* block = new RS_Block(container, RS_BlockData(data.name, data.basePoint, data.frozen)); // copy entities into a block for (RS_Entity* e=container->firstEntity(); e!=NULL; e=container->nextEntity()) { //for (uint i=0; icount(); ++i) { //RS_Entity* e = container->entityAt(i); if (e!=NULL && e->isSelected()) { // delete / redraw entity in graphic view: if (remove) { if (graphicView!=NULL) { graphicView->deleteEntity(e); } e->setSelected(false); } else { if (graphicView!=NULL) { graphicView->deleteEntity(e); } e->setSelected(false); if (graphicView!=NULL) { graphicView->drawEntity(e); } } // add entity to block: RS_Entity* c = e->clone(); c->move(-referencePoint); block->addEntity(c); if (remove) { //container->removeEntity(e); //i=0; e->changeUndoState(); if (document!=NULL) { document->addUndoable(e); } } } } if (remove && document!=NULL) { document->endUndoCycle(); } if (graphic!=NULL) { graphic->addBlock(block); } return block; } /** * Inserts a library item from the given path into the drawing. */ RS_Insert* RS_Creation::createLibraryInsert(RS_LibraryInsertData& data) { RS_DEBUG->print("RS_Creation::createLibraryInsert"); RS_Graphic g; if (!g.open(data.file, RS2::FormatUnknown)) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Creation::createLibraryInsert: Cannot open file: %s"); return NULL; } // unit conversion: if (graphic!=NULL) { double uf = RS_Units::convert(1.0, g.getUnit(), graphic->getUnit()); g.scale(RS_Vector(0.0, 0.0), RS_Vector(uf, uf)); } //g.scale(RS_Vector(data.factor, data.factor)); //g.rotate(data.angle); RS_String s; #if QT_VERSION>=0x030000 s = RS_FileInfo(data.file).baseName(true); #else s = data.file.left(data.file.length()-4); #endif RS_Modification m(*container, graphicView); m.paste( RS_PasteData( data.insertionPoint, data.factor, data.angle, true, s), &g); RS_DEBUG->print("RS_Creation::createLibraryInsert: OK"); return NULL; } // EOF