3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_creation.h"
18 #include "rs_constructionline.h"
19 #include "rs_graphic.h"
20 #include "rs_graphicview.h"
21 #include "rs_information.h"
22 #include "rs_modification.h"
26 * Default constructor.
28 * @param container The container to which we will add
29 * entities. Usually that's an RS_Graphic entity but
30 * it can also be a polyline, text, ...
32 RS_Creation::RS_Creation(RS_EntityContainer * container, RS_GraphicView * graphicView,
35 this->container = container;
36 this->graphicView = graphicView;
37 this->handleUndo = handleUndo;
39 if (container != NULL)
41 graphic = container->getGraphic();
42 document = container->getDocument();
52 * Creates a point entity.
56 * creation.createPoint(Vector(10.0, 15.0));
61 /*void RS_Creation::createPoint(const Vector& p) {
62 entityContainer->addEntity(new RS_Point(entityContainer, p));
66 * Creates a line with two points given.
70 * creation.createLine2P(Vector(10.0, 10.0), Vector(100.0, 200.0));
73 * @param p1 start point
76 /*void RS_Creation::createLine2P(const Vector& p1, const Vector& p2) {
77 entityContainer->addEntity(new RS_Line(entityContainer,
78 RS_LineData(p1, p2)));
82 * Creates a rectangle with two edge points given.
86 * creation.createRectangle(Vector(5.0, 2.0), Vector(7.5, 3.0));
92 /*void RS_Creation::createRectangle(const Vector& e1, const Vector& e2) {
93 Vector e21(e2.x, e1.y);
94 Vector e12(e1.x, e2.y);
95 entityContainer->addEntity(new RS_Line(entityContainer,
96 RS_LineData(e1, e12)));
97 entityContainer->addEntity(new RS_Line(entityContainer,
98 RS_LineData(e12, e2)));
99 entityContainer->addEntity(new RS_Line(entityContainer,
100 RS_LineData(e2, e21)));
101 entityContainer->addEntity(new RS_Line(entityContainer,
102 RS_LineData(e21, e1)));
106 * Creates a polyline from the given array of entities.
107 * No checking if the entities actually fit together.
108 * Currently this is like a group.
112 * RS_Polyline *pl = creation.createPolyline(Vector(25.0, 55.0));<br>
113 * pl->addVertex(Vector(50.0, 75.0));<br>
116 * @param entities array of entities
117 * @param startPoint Start point of the polyline
119 /*RS_Polyline* RS_Creation::createPolyline(const Vector& startPoint) {
120 RS_Polyline* pl = new RS_Polyline(entityContainer,
121 RS_PolylineData(startPoint, Vector(0.0,0.0), 0));
122 entityContainer->addEntity(pl);
127 * Creates an entity parallel to the given entity e through the given
130 * @param coord Coordinate to define the distance / side (typically a
132 * @param number Number of parallels.
133 * @param e Original entity.
135 * @return Pointer to the first created parallel or NULL if no
136 * parallel has been created.
138 RS_Entity * RS_Creation::createParallelThrough(const Vector & coord, int number, RS_Entity * e)
145 if (e->rtti() == RS2::EntityLine)
147 RS_Line * l = (RS_Line *)e;
148 RS_ConstructionLine cl(NULL, RS_ConstructionLineData(l->getStartpoint(),
150 dist = cl.getDistanceToPoint(coord);
154 dist = e->getDistanceToPoint(coord);
157 if (dist < RS_MAXDOUBLE)
158 return createParallel(coord, dist, number, e);
164 * Creates an entity parallel to the given entity e.
165 * Out of the 2 possible parallels, the one closest to
166 * the given coordinate is returned.
167 * Lines, Arcs and Circles can have parallels.
169 * @param coord Coordinate to define which parallel we want (typically a
171 * @param distance Distance of the parallel.
172 * @param number Number of parallels.
173 * @param e Original entity.
175 * @return Pointer to the first created parallel or NULL if no
176 * parallel has been created.
178 RS_Entity* RS_Creation::createParallel(const Vector& coord,
179 double distance, int number,
186 case RS2::EntityLine:
187 return createParallelLine(coord, distance, number, (RS_Line*)e);
191 return createParallelArc(coord, distance, number, (RS_Arc*)e);
194 case RS2::EntityCircle:
195 return createParallelCircle(coord, distance, number, (RS_Circle*)e);
208 * Creates a line parallel to the given line e.
209 * Out of the 2 possible parallels, the one closest to
210 * the given coordinate is returned.
212 * @param coord Coordinate to define which parallel we want (typically a
214 * @param distance Distance of the parallel.
215 * @param number Number of parallels.
216 * @param e Original entity.
218 * @return Pointer to the first created parallel or NULL if no
219 * parallel has been created.
221 RS_Line* RS_Creation::createParallelLine(const Vector& coord,
222 double distance, int number,
229 double ang = e->getAngle1() + M_PI/2.0;
231 RS_LineData parallelData;
234 if (document!=NULL && handleUndo) {
235 document->startUndoCycle();
238 for (int num=1; num<=number; ++num) {
240 // calculate 1st parallel:
241 p1.setPolar(distance*num, ang);
242 p1 += e->getStartpoint();
243 p2.setPolar(distance*num, ang);
244 p2 += e->getEndpoint();
245 RS_Line parallel1(NULL, RS_LineData(p1, p2));
247 // calculate 2nd parallel:
248 p1.setPolar(distance*num, ang+M_PI);
249 p1 += e->getStartpoint();
250 p2.setPolar(distance*num, ang+M_PI);
251 p2 += e->getEndpoint();
252 RS_Line parallel2(NULL, RS_LineData(p1, p2));
254 double dist1 = parallel1.getDistanceToPoint(coord);
255 double dist2 = parallel2.getDistanceToPoint(coord);
256 double minDist = std::min(dist1, dist2);
258 if (minDist<RS_MAXDOUBLE) {
260 parallelData = parallel1.getData();
262 parallelData = parallel2.getData();
266 RS_Line* newLine = new RS_Line(container, parallelData);
267 newLine->setLayerToActive();
268 newLine->setPenToActive();
272 if (container!=NULL) {
273 container->addEntity(newLine);
275 if (document!=NULL && handleUndo) {
276 document->addUndoable(newLine);
277 //document->endUndoCycle();
279 if (graphicView!=NULL) {
280 graphicView->drawEntity(newLine);
285 if (document!=NULL && handleUndo) {
286 document->endUndoCycle();
295 * Creates a arc parallel to the given arc e.
296 * Out of the 2 possible parallels, the one closest to
297 * the given coordinate is returned.
299 * @param coord Coordinate to define which parallel we want (typically a
301 * @param distance Distance of the parallel.
302 * @param number Number of parallels.
303 * @param e Original entity.
305 * @return Pointer to the first created parallel or NULL if no
306 * parallel has been created.
308 RS_Arc* RS_Creation::createParallelArc(const Vector& coord,
309 double distance, int number,
316 RS_ArcData parallelData;
319 bool inside = (e->getCenter().distanceTo(coord) < e->getRadius());
325 for (int num=1; num<=number; ++num) {
327 // calculate parallel:
329 RS_Arc parallel1(NULL, e->getData());
330 parallel1.setRadius(e->getRadius() + distance*num);
331 if (parallel1.getRadius()<0.0) {
332 parallel1.setRadius(RS_MAXDOUBLE);
336 // calculate 2nd parallel:
337 //RS_Arc parallel2(NULL, e->getData());
338 //parallel2.setRadius(e->getRadius()+distance*num);
340 //double dist1 = parallel1.getDistanceToPoint(coord);
341 //double dist2 = parallel2.getDistanceToPoint(coord);
342 //double minDist = min(dist1, dist2);
344 //if (minDist<RS_MAXDOUBLE) {
347 parallelData = parallel1.getData();
349 // parallelData = parallel2.getData();
352 if (document!=NULL && handleUndo) {
353 document->startUndoCycle();
356 RS_Arc* newArc = new RS_Arc(container, parallelData);
357 newArc->setLayerToActive();
358 newArc->setPenToActive();
362 if (container!=NULL) {
363 container->addEntity(newArc);
365 if (document!=NULL && handleUndo) {
366 document->addUndoable(newArc);
367 document->endUndoCycle();
369 if (graphicView!=NULL) {
370 graphicView->drawEntity(newArc);
381 * Creates a circle parallel to the given circle e.
382 * Out of the 2 possible parallels, the one closest to
383 * the given coordinate is returned.
385 * @param coord Coordinate to define which parallel we want (typically a
387 * @param distance Distance of the parallel.
388 * @param number Number of parallels.
389 * @param e Original entity.
391 * @return Pointer to the first created parallel or NULL if no
392 * parallel has been created.
394 RS_Circle* RS_Creation::createParallelCircle(const Vector& coord,
395 double distance, int number,
402 RS_CircleData parallelData;
403 RS_Circle* ret = NULL;
405 bool inside = (e->getCenter().distanceTo(coord) < e->getRadius());
411 for (int num=1; num<=number; ++num) {
413 // calculate parallel:
415 RS_Circle parallel1(NULL, e->getData());
416 parallel1.setRadius(e->getRadius() + distance*num);
417 if (parallel1.getRadius()<0.0) {
418 parallel1.setRadius(RS_MAXDOUBLE);
422 // calculate 2nd parallel:
423 //RS_Circle parallel2(NULL, e->getData());
424 //parallel2.setRadius(e->getRadius()+distance*num);
426 //double dist1 = parallel1.getDistanceToPoint(coord);
427 //double dist2 = parallel2.getDistanceToPoint(coord);
428 //double minDist = min(dist1, dist2);
430 //if (minDist<RS_MAXDOUBLE) {
433 parallelData = parallel1.getData();
435 // parallelData = parallel2.getData();
438 if (document!=NULL && handleUndo) {
439 document->startUndoCycle();
442 RS_Circle* newCircle = new RS_Circle(container, parallelData);
443 newCircle->setLayerToActive();
444 newCircle->setPenToActive();
448 if (container!=NULL) {
449 container->addEntity(newCircle);
451 if (document!=NULL && handleUndo) {
452 document->addUndoable(newCircle);
453 document->endUndoCycle();
455 if (graphicView!=NULL) {
456 graphicView->drawEntity(newCircle);
466 * Creates a bisecting line of the angle between the entities
467 * e1 and e2. Out of the 4 possible bisectors, the one closest to
468 * the given coordinate is returned.
470 * @param coord Coordinate to define which bisector we want (typically a
472 * @param length Length of the bisecting line.
473 * @param num Number of bisectors
474 * @param l1 First line.
475 * @param l2 Second line.
477 * @return Pointer to the first bisector created or NULL if no bisectors
480 RS_Line* RS_Creation::createBisector(const Vector& coord1,
481 const Vector& coord2,
489 // check given entities:
490 if (l1==NULL || l2==NULL ||
491 l1->rtti()!=RS2::EntityLine || l2->rtti()!=RS2::EntityLine) {
495 // intersection between entities:
496 sol = RS_Information::getIntersection(l1, l2, false);
497 Vector inters = sol.get(0);
498 if (inters.valid==false) {
502 double angle1 = inters.angleTo(l1->getNearestPointOnEntity(coord1));
503 double angle2 = inters.angleTo(l2->getNearestPointOnEntity(coord2));
504 double angleDiff = RS_Math::getAngleDifference(angle1, angle2);
505 if (angleDiff>M_PI) {
506 angleDiff = angleDiff - 2*M_PI;
510 if (document!=NULL && handleUndo) {
511 document->startUndoCycle();
514 for (int n=1; n<=num; ++n) {
516 double angle = angle1 +
517 (angleDiff / (num+1) * n);
523 v.setPolar(length, angle);
524 d = RS_LineData(inters, inters + v);
526 RS_Line* newLine = new RS_Line(container, d);
527 if (container!=NULL) {
528 newLine->setLayerToActive();
529 newLine->setPenToActive();
530 container->addEntity(newLine);
532 if (document!=NULL && handleUndo) {
533 document->addUndoable(newLine);
535 if (graphicView!=NULL) {
536 graphicView->drawEntity(newLine);
542 if (document!=NULL && handleUndo) {
543 document->endUndoCycle();
552 * Creates a tangent between a given point and a circle or arc.
553 * Out of the 2 possible tangents, the one closest to
554 * the given coordinate is returned.
556 * @param coord Coordinate to define which tangent we want (typically a
558 * @param point Point.
559 * @param circle Circle, arc or ellipse entity.
561 RS_Line* RS_Creation::createTangent1(const Vector& coord,
567 // check given entities:
568 if (circle==NULL || !point.valid ||
569 (circle->rtti()!=RS2::EntityArc && circle->rtti()!=RS2::EntityCircle
570 && circle->rtti()!=RS2::EntityEllipse)) {
575 if (circle->rtti()==RS2::EntityCircle) {
576 circleCenter = ((RS_Circle*)circle)->getCenter();
577 } else if (circle->rtti()==RS2::EntityArc) {
578 circleCenter = ((RS_Arc*)circle)->getCenter();
579 } else if (circle->rtti()==RS2::EntityEllipse) {
580 circleCenter = ((RS_Ellipse*)circle)->getCenter();
583 // the two tangent points:
586 // calculate tangent points for arcs / circles:
587 if (circle->rtti()!=RS2::EntityEllipse) {
588 // create temp. thales circle:
589 Vector tCenter = (point + circleCenter)/2.0;
590 double tRadius = point.distanceTo(tCenter);
592 RS_Circle tmp(NULL, RS_CircleData(tCenter, tRadius));
594 // get the two intersection points which are the tangent points:
595 sol = RS_Information::getIntersection(&tmp, circle, false);
598 // calculate tangent points for ellipses:
600 RS_Ellipse* el = (RS_Ellipse*)circle;
602 //sol.set(0, circleCenter);
603 //sol.set(1, circleCenter);
606 double a = el->getMajorRadius(); // the length of the major axis / 2
607 double b = el->getMinorRadius(); // the length of the minor axis / 2
609 // rotate and move point:
610 Vector point2 = point;
611 point2.move(-el->getCenter());
612 point2.rotate(-el->getAngle());
614 double xp = point2.x; // coordinates of the given point
615 double yp = point2.y;
617 double xt1; // Tangent point 1
619 double xt2; // Tangent point 2
624 double d = a2 / b2 * yp / xp;
626 double af = b2 * d * d + a2;
627 double bf = -b2 * d * e * 2.0;
628 double cf = b2 * e * e - a2 * b2;
629 double t = sqrt(bf * bf - af * cf * 4.0);
630 yt1 = (t - bf) / (af * 2.0);
632 yt2 = (-t - bf) / (af * 2.0);
635 Vector s1 = Vector(xt1, yt1);
636 Vector s2 = Vector(xt2, yt2);
638 s1.rotate(el->getAngle());
639 s1.move(el->getCenter());
641 s2.rotate(el->getAngle());
642 s2.move(el->getCenter());
650 if (!sol.get(0).valid || !sol.get(1).valid) {
654 // create all possible tangents:
659 d = RS_LineData(sol.get(0), point);
660 poss[0] = new RS_Line(NULL, d);
661 d = RS_LineData(sol.get(1), point);
662 poss[1] = new RS_Line(NULL, d);
664 // find closest tangent:
665 double minDist = RS_MAXDOUBLE;
668 for (int i=0; i<2; ++i) {
669 dist = poss[i]->getDistanceToPoint(coord);
676 // create the closest tangent:
678 RS_LineData d = poss[idx]->getData();
680 for (int i=0; i<2; ++i) {
684 if (document!=NULL && handleUndo) {
685 document->startUndoCycle();
688 ret = new RS_Line(container, d);
689 ret->setLayerToActive();
690 ret->setPenToActive();
691 if (container!=NULL) {
692 container->addEntity(ret);
694 if (document!=NULL && handleUndo) {
695 document->addUndoable(ret);
696 document->endUndoCycle();
698 if (graphicView!=NULL) {
699 graphicView->drawEntity(ret);
711 * Creates a tangent between two circles or arcs.
712 * Out of the 4 possible tangents, the one closest to
713 * the given coordinate is returned.
715 * @param coord Coordinate to define which tangent we want (typically a
717 * @param circle1 1st circle or arc entity.
718 * @param circle2 2nd circle or arc entity.
720 RS_Line* RS_Creation::createTangent2(const Vector& coord,
722 RS_Entity* circle2) {
724 Vector circleCenter1;
725 Vector circleCenter2;
726 double circleRadius1 = 0.0;
727 double circleRadius2 = 0.0;
729 // check given entities:
730 if (circle1==NULL || circle2==NULL ||
731 (circle1->rtti()!=RS2::EntityArc &&
732 circle1->rtti()!=RS2::EntityCircle) ||
733 (circle2->rtti()!=RS2::EntityArc &&
734 circle2->rtti()!=RS2::EntityCircle) ) {
739 if (circle1->rtti()==RS2::EntityCircle) {
740 circleCenter1 = ((RS_Circle*)circle1)->getCenter();
741 circleRadius1 = ((RS_Circle*)circle1)->getRadius();
742 } else if (circle1->rtti()==RS2::EntityArc) {
743 circleCenter1 = ((RS_Arc*)circle1)->getCenter();
744 circleRadius1 = ((RS_Arc*)circle1)->getRadius();
747 if (circle2->rtti()==RS2::EntityCircle) {
748 circleCenter2 = ((RS_Circle*)circle2)->getCenter();
749 circleRadius2 = ((RS_Circle*)circle2)->getRadius();
750 } else if (circle2->rtti()==RS2::EntityArc) {
751 circleCenter2 = ((RS_Arc*)circle2)->getCenter();
752 circleRadius2 = ((RS_Arc*)circle2)->getRadius();
755 // create all possible tangents:
757 for (int i=0; i<4; ++i) {
763 double angle1 = circleCenter1.angleTo(circleCenter2);
764 double dist1 = circleCenter1.distanceTo(circleCenter2);
768 double dist2 = circleRadius2 - circleRadius1;
770 double angle2 = asin(dist2/dist1);
771 double angt1 = angle1 + angle2 + M_PI/2.0;
772 double angt2 = angle1 - angle2 - M_PI/2.0;
776 offs1.setPolar(circleRadius1, angt1);
777 offs2.setPolar(circleRadius2, angt1);
779 d = RS_LineData(circleCenter1 + offs1,
780 circleCenter2 + offs2);
781 poss[0] = new RS_Line(NULL, d);
784 offs1.setPolar(circleRadius1, angt2);
785 offs2.setPolar(circleRadius2, angt2);
787 d = RS_LineData(circleCenter1 + offs1,
788 circleCenter2 + offs2);
789 poss[1] = new RS_Line(NULL, d);
793 double dist3 = circleRadius2 + circleRadius1;
795 double angle3 = asin(dist3/dist1);
796 double angt3 = angle1 + angle3 + M_PI/2.0;
797 double angt4 = angle1 - angle3 - M_PI/2.0;
801 offs1.setPolar(circleRadius1, angt3);
802 offs2.setPolar(circleRadius2, angt3);
804 d = RS_LineData(circleCenter1 - offs1,
805 circleCenter2 + offs2);
806 poss[2] = new RS_Line(NULL, d);
809 offs1.setPolar(circleRadius1, angt4);
810 offs2.setPolar(circleRadius2, angt4);
812 d = RS_LineData(circleCenter1 - offs1,
813 circleCenter2 + offs2);
814 poss[3] = new RS_Line(NULL, d);
819 // find closest tangent:
820 double minDist = RS_MAXDOUBLE;
823 for (int i=0; i<4; ++i) {
825 dist = poss[i]->getDistanceToPoint(coord);
834 RS_LineData d = poss[idx]->getData();
835 for (int i=0; i<4; ++i) {
841 if (document!=NULL && handleUndo) {
842 document->startUndoCycle();
845 ret = new RS_Line(container, d);
846 ret->setLayerToActive();
847 ret->setPenToActive();
848 if (container!=NULL) {
849 container->addEntity(ret);
851 if (document!=NULL && handleUndo) {
852 document->addUndoable(ret);
853 document->endUndoCycle();
855 if (graphicView!=NULL) {
856 graphicView->drawEntity(ret);
867 * Creates a line with a relative angle to the given entity.
869 * @param coord Coordinate to define the point where the line should end.
870 * (typically a mouse coordinate).
871 * @param entity Pointer to basis entity. The angle is relative to the
872 * angle of this entity.
873 * @param angle Angle of the line relative to the angle of the basis entity.
874 * @param length Length of the line we're creating.
876 RS_Line* RS_Creation::createLineRelAngle(const Vector& coord,
881 // check given entity / coord:
882 if (entity==NULL || !coord.valid ||
883 (entity->rtti()!=RS2::EntityArc && entity->rtti()!=RS2::EntityCircle
884 && entity->rtti()!=RS2::EntityLine)) {
891 switch (entity->rtti()) {
892 case RS2::EntityLine:
893 a1 = ((RS_Line*)entity)->getAngle1();
896 a1 = ((RS_Arc*)entity)->getCenter().angleTo(coord) + M_PI/2.0;
898 case RS2::EntityCircle:
899 a1 = ((RS_Circle*)entity)->getCenter().angleTo(coord);
909 v1.setPolar(length, a1);
910 //RS_ConstructionLineData(coord-v1, coord+v1);
911 RS_LineData d(coord-v1, coord+v1);
914 if (document!=NULL && handleUndo) {
915 document->startUndoCycle();
918 ret = new RS_Line(container, d);
919 ret->setLayerToActive();
920 ret->setPenToActive();
921 if (container!=NULL) {
922 container->addEntity(ret);
924 if (document!=NULL && handleUndo) {
925 document->addUndoable(ret);
926 document->endUndoCycle();
928 if (graphicView!=NULL) {
929 graphicView->drawEntity(ret);
937 * Creates a polygon with 'number' edges.
939 * @param center Center of the polygon.
940 * @param corner The first corner of the polygon
941 * @param number Number of edges / corners.
943 RS_Line* RS_Creation::createPolygon(const Vector& center,
944 const Vector& corner,
947 // check given coords / number:
948 if (!center.valid || !corner.valid || number<3) {
954 if (document!=NULL && handleUndo) {
955 document->startUndoCycle();
962 for (int n=1; n<=number; ++n) {
964 c2 = c2.rotate(center, (M_PI*2)/number);
966 line = new RS_Line(container, RS_LineData(c1, c2));
967 line->setLayerToActive();
968 line->setPenToActive();
974 if (container!=NULL) {
975 container->addEntity(line);
977 if (document!=NULL && handleUndo) {
978 document->addUndoable(line);
980 if (graphicView!=NULL) {
981 graphicView->drawEntity(line);
985 if (document!=NULL && handleUndo) {
986 document->endUndoCycle();
995 * Creates a polygon with 'number' edges.
997 * @param corner1 The first corner of the polygon.
998 * @param corner2 The second corner of the polygon.
999 * @param number Number of edges / corners.
1001 RS_Line* RS_Creation::createPolygon2(const Vector& corner1,
1002 const Vector& corner2,
1005 // check given coords / number:
1006 if (!corner1.valid || !corner2.valid || number<3) {
1010 RS_Line* ret = NULL;
1012 if (document!=NULL && handleUndo) {
1013 document->startUndoCycle();
1016 double len = corner1.distanceTo(corner2);
1017 double ang1 = corner1.angleTo(corner2);
1021 Vector c2 = corner1;
1025 for (int n=1; n<=number; ++n) {
1027 edge.setPolar(len, ang);
1030 line = new RS_Line(container, RS_LineData(c1, c2));
1031 line->setLayerToActive();
1032 line->setPenToActive();
1038 if (container!=NULL) {
1039 container->addEntity(line);
1041 if (document!=NULL && handleUndo) {
1042 document->addUndoable(line);
1044 if (graphicView!=NULL) {
1045 graphicView->drawEntity(line);
1048 // more accurate than incrementing the angle:
1049 ang = ang1 + (2*M_PI)/number*n;
1052 if (document!=NULL && handleUndo) {
1053 document->endUndoCycle();
1062 * Creates an insert with the given data.
1064 * @param data Insert data (position, block name, ..)
1066 RS_Insert* RS_Creation::createInsert(RS_InsertData& data) {
1068 RS_DEBUG->print("RS_Creation::createInsert");
1070 if (document!=NULL && handleUndo) {
1071 document->startUndoCycle();
1074 RS_Insert* ins = new RS_Insert(container, data);
1075 // inserts are also on layers
1076 ins->setLayerToActive();
1077 ins->setPenToActive();
1079 if (container!=NULL) {
1080 container->addEntity(ins);
1082 if (document!=NULL && handleUndo) {
1083 document->addUndoable(ins);
1084 document->endUndoCycle();
1086 if (graphicView!=NULL) {
1087 graphicView->drawEntity(ins);
1090 RS_DEBUG->print("RS_Creation::createInsert: OK");
1098 * Creates an image with the given data.
1100 RS_Image* RS_Creation::createImage(RS_ImageData& data) {
1102 if (document!=NULL && handleUndo) {
1103 document->startUndoCycle();
1106 RS_Image* img = new RS_Image(container, data);
1107 img->setLayerToActive();
1108 img->setPenToActive();
1111 if (container!=NULL) {
1112 container->addEntity(img);
1114 if (document!=NULL && handleUndo) {
1115 document->addUndoable(img);
1116 document->endUndoCycle();
1118 if (graphicView!=NULL) {
1119 graphicView->drawEntity(img);
1126 * Creates a new block from the currently selected entitiies.
1128 * @param referencePoint Reference point for the block.
1129 * @param name Block name
1130 * @param remove true: remove existing entities, false: don't touch entities
1132 RS_Block * RS_Creation::createBlock(const RS_BlockData & data,
1133 const Vector & referencePoint, const bool remove)
1135 // start undo cycle for the container if we're deleting the existing entities
1136 if (remove && document!=NULL) {
1137 document->startUndoCycle();
1141 new RS_Block(container,
1142 RS_BlockData(data.name, data.basePoint, data.frozen));
1144 // copy entities into a block
1145 for(RS_Entity * e=container->firstEntity(); e!=NULL; e=container->nextEntity())
1147 //for (uint i=0; i<container->count(); ++i) {
1148 //RS_Entity* e = container->entityAt(i);
1150 if (e != NULL && e->isSelected())
1152 // delete / redraw entity in graphic view:
1155 if (graphicView != NULL)
1156 graphicView->deleteEntity(e);
1158 e->setSelected(false);
1162 if (graphicView != NULL)
1163 graphicView->deleteEntity(e);
1165 e->setSelected(false);
1167 if (graphicView != NULL)
1168 graphicView->drawEntity(e);
1171 // add entity to block:
1172 RS_Entity * c = e->clone();
1173 c->move(-referencePoint);
1174 block->addEntity(c);
1178 //container->removeEntity(e);
1180 e->changeUndoState();
1182 if (document != NULL)
1183 document->addUndoable(e);
1188 if (remove && document != NULL)
1189 document->endUndoCycle();
1191 if (graphic != NULL)
1192 graphic->addBlock(block);
1198 * Inserts a library item from the given path into the drawing.
1200 RS_Insert * RS_Creation::createLibraryInsert(RS_LibraryInsertData & data)
1202 RS_DEBUG->print("RS_Creation::createLibraryInsert");
1205 if (!g.open(data.file, RS2::FormatUnknown))
1207 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Creation::createLibraryInsert: Cannot open file: %s");
1212 if (graphic != NULL)
1214 double uf = RS_Units::convert(1.0, g.getUnit(), graphic->getUnit());
1215 g.scale(Vector(0.0, 0.0), Vector(uf, uf));
1218 //g.scale(Vector(data.factor, data.factor));
1219 //g.rotate(data.angle);
1221 // QString s = QFileInfo(data.file).baseName(true);
1222 QString s = QFileInfo(data.file).completeBaseName();
1224 RS_Modification m(*container, graphicView);
1225 m.paste(RS_PasteData(data.insertionPoint, data.factor, data.angle, true, s), &g);
1227 RS_DEBUG->print("RS_Creation::createLibraryInsert: OK");