1
/****************************************************************************
3
** This file is part of the LibreCAD project, a 2D CAD program
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
9
** This file may be distributed and/or modified under the terms of the
10
** GNU General Public License version 2 as published by the Free Software
11
** Foundation and appearing in the file gpl-2.0.txt included in the
12
** packaging of this file.
14
** This program is distributed in the hope that it will be useful,
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
** GNU General Public License for more details.
19
** You should have received a copy of the GNU General Public License
20
** along with this program; if not, write to the Free Software
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
** This copyright notice MUST APPEAR in all copies of the script!
25
**********************************************************************/
29
#include "rs_entitycontainer.h"
32
#include "rs_dimension.h"
35
#include "rs_insert.h"
36
#include "rs_spline.h"
38
#include "rs_information.h"
39
#include "rs_graphicview.h"
41
#if QT_VERSION < 0x040400
45
bool RS_EntityContainer::autoUpdateBorders = true;
48
* Default constructor.
50
* @param owner True if we own and also delete the entities.
52
RS_EntityContainer::RS_EntityContainer(RS_EntityContainer* parent,
57
RS_DEBUG->print("RS_EntityContainer::RS_EntityContainer: "
58
"owner: %d", (int)owner);
60
//autoUpdateBorders = true;
66
* Copy constructor. Makes a deep copy of all entities.
69
RS_EntityContainer::RS_EntityContainer(const RS_EntityContainer& ec)
80
RS_EntityContainer::~RS_EntityContainer() {
86
RS_Entity* RS_EntityContainer::clone() {
87
RS_DEBUG->print("RS_EntityContainer::clone: ori autoDel: %d",
90
RS_EntityContainer* ec = new RS_EntityContainer(*this);
91
ec->setOwner(autoDelete);
93
RS_DEBUG->print("RS_EntityContainer::clone: clone autoDel: %d",
105
* Detaches shallow copies and creates deep copies of all subentities.
106
* This is called after cloning entity containers.
108
void RS_EntityContainer::detach() {
109
QList<RS_Entity*> tmp;
110
bool autoDel = isOwner();
111
RS_DEBUG->print("RS_EntityContainer::detach: autoDel: %d",
115
// make deep copies of all entities:
116
for (RS_Entity* e=firstEntity();
119
if (!e->getFlag(RS2::FlagTemp)) {
120
tmp.append(e->clone());
124
// clear shared pointers:
128
// point to new deep copies:
129
for (int i = 0; i < tmp.size(); ++i) {
130
RS_Entity* e = tmp.at(i);
138
void RS_EntityContainer::reparent(RS_EntityContainer* parent) {
139
RS_Entity::reparent(parent);
142
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
144
e=nextEntity(RS2::ResolveNone)) {
152
* Called when the undo state changed. Forwards the event to all sub-entities.
154
* @param undone true: entity has become invisible.
155
* false: entity has become visible.
157
void RS_EntityContainer::undoStateChanged(bool undone) {
159
RS_Entity::undoStateChanged(undone);
161
// ! don't pass on to subentities. undo list handles them
163
/*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
165
e=nextEntity(RS2::ResolveNone)) {
166
e->setUndoState(undone);
172
void RS_EntityContainer::setVisible(bool v) {
173
// RS_DEBUG->print("RS_EntityContainer::setVisible: %d", v);
174
RS_Entity::setVisible(v);
177
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
179
e=nextEntity(RS2::ResolveNone)) {
180
// RS_DEBUG->print("RS_EntityContainer::setVisible: subentity: %d", v);
188
* @return Total length of all entities in this container.
190
double RS_EntityContainer::getLength() const {
193
for (RS_Entity* e=const_cast<RS_EntityContainer*>(this)->firstEntity(RS2::ResolveNone);
195
e=const_cast<RS_EntityContainer*>(this)->nextEntity(RS2::ResolveNone)) {
196
if (e->isVisible()) {
197
double l = e->getLength();
212
* Selects this entity.
214
bool RS_EntityContainer::setSelected(bool select) {
215
// This entity's select:
216
if (RS_Entity::setSelected(select)) {
218
// All sub-entity's select:
219
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
221
e=nextEntity(RS2::ResolveNone)) {
222
if (e->isVisible()) {
223
e->setSelected(select);
235
* Toggles select on this entity.
237
bool RS_EntityContainer::toggleSelected() {
238
// Toggle this entity's select:
239
if (RS_Entity::toggleSelected()) {
241
// Toggle all sub-entity's select:
242
/*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
244
e=nextEntity(RS2::ResolveNone)) {
256
* Selects all entities within the given area.
258
* @param select True to select, False to deselect the entities.
260
void RS_EntityContainer::selectWindow(RS_Vector v1, RS_Vector v2,
261
bool select, bool cross) {
265
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
267
e=nextEntity(RS2::ResolveNone)) {
271
if (e->isVisible()) {
272
if (e->isInWindow(v1, v2)) {
273
//e->setSelected(select);
275
} else if (cross==true) {
278
RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))),
279
RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)),
280
RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))),
281
RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1))
283
RS_VectorSolutions sol;
285
if (e->isContainer()) {
286
RS_EntityContainer* ec = (RS_EntityContainer*)e;
287
for (RS_Entity* se=ec->firstEntity(RS2::ResolveAll);
288
se!=NULL && included==false;
289
se=ec->nextEntity(RS2::ResolveAll)) {
291
if (se->rtti() == RS2::EntitySolid){
292
included = ((RS_Solid *)se)->isInCrossWindow(v1,v2);
294
for (int i=0; i<4; ++i) {
295
sol = RS_Information::getIntersection(
297
if (sol.hasValid()) {
304
} else if (e->rtti() == RS2::EntitySolid){
305
included = ((RS_Solid *)e)->isInCrossWindow(v1,v2);
307
for (int i=0; i<4; ++i) {
308
sol = RS_Information::getIntersection(e, &l[i], true);
309
if (sol.hasValid()) {
319
e->setSelected(select);
327
* Adds a entity to this container and updates the borders of this
328
* entity-container if autoUpdateBorders is true.
330
void RS_EntityContainer::addEntity(RS_Entity* entity) {
333
RS_LayerList* lst = getDocument()->getLayerList();
335
RS_Layer* l = lst->getActive();
336
if (l!=NULL && l->isLocked()) {
347
if (entity->rtti()==RS2::EntityImage ||
348
entity->rtti()==RS2::EntityHatch) {
349
entities.prepend(entity);
351
entities.append(entity);
353
if (autoUpdateBorders) {
354
adjustBorders(entity);
360
* Insert a entity at the end of entities list and updates the
361
* borders of this entity-container if autoUpdateBorders is true.
363
void RS_EntityContainer::appendEntity(RS_Entity* entity){
366
entities.append(entity);
367
if (autoUpdateBorders)
368
adjustBorders(entity);
372
* Insert a entity at the start of entities list and updates the
373
* borders of this entity-container if autoUpdateBorders is true.
375
void RS_EntityContainer::prependEntity(RS_Entity* entity){
378
entities.prepend(entity);
379
if (autoUpdateBorders)
380
adjustBorders(entity);
384
* Move a entity list in this container at the given position,
385
* the borders of this entity-container if autoUpdateBorders is true.
387
void RS_EntityContainer::moveEntity(int index, QList<RS_Entity *> entList){
388
if (entList.isEmpty()) return;
389
int ci = 0; //current index for insert without invert order
390
bool ret, into = false;
391
RS_Entity *mid = NULL;
394
} else if (index >= entities.size() ) {
395
ci = entities.size() - entList.size();
398
mid = entities.at(index);
401
for (int i = 0; i < entList.size(); ++i) {
402
RS_Entity *e = entList.at(i);
403
ret = entities.removeOne(e);
404
//if e not exist in entities list remove from entList
410
ci = entities.indexOf(mid);
413
for (int i = 0; i < entList.size(); ++i) {
414
RS_Entity *e = entList.at(i);
415
entities.insert(ci++, e);
420
* Inserts a entity to this container at the given position and updates
421
* the borders of this entity-container if autoUpdateBorders is true.
423
void RS_EntityContainer::insertEntity(int index, RS_Entity* entity) {
428
entities.insert(index, entity);
430
if (autoUpdateBorders) {
431
adjustBorders(entity);
438
* Replaces the entity at the given index with the given entity
439
* and updates the borders of this entity-container if autoUpdateBorders is true.
441
/*RLZ unused function
442
void RS_EntityContainer::replaceEntity(int index, RS_Entity* entity) {
443
//RLZ TODO: is needed to delete the old entity? not documented in Q3PtrList
444
// investigate in qt3support code if reactivate this function.
449
entities.replace(index, entity);
451
if (autoUpdateBorders) {
452
adjustBorders(entity);
459
* Removes an entity from this container and updates the borders of
460
* this entity-container if autoUpdateBorders is true.
462
bool RS_EntityContainer::removeEntity(RS_Entity* entity) {
463
//RLZ TODO: in Q3PtrList if 'entity' is NULL remove the current item-> at.(entIdx)
464
// and sets 'entIdx' in next() or last() if 'entity' is the last item in the list.
465
// in LibreCAD is never called with NULL
467
#if QT_VERSION < 0x040400
468
ret = emu_qt44_removeOne(entities, entity);
470
ret = entities.removeOne(entity);
473
if (autoDelete && ret) {
476
if (autoUpdateBorders) {
485
* Erases all entities in this container and resets the borders..
487
void RS_EntityContainer::clear() {
489
while (!entities.isEmpty())
490
delete entities.takeFirst();
498
* Counts all entities (branches of the tree).
500
unsigned int RS_EntityContainer::count() {
501
return entities.size();
503
unsigned int RS_EntityContainer::count() const{
504
return entities.size();
509
* Counts all entities (leaves of the tree).
511
unsigned int RS_EntityContainer::countDeep() {
512
unsigned long int c=0;
514
for (RS_Entity* t=firstEntity(RS2::ResolveNone);
516
t=nextEntity(RS2::ResolveNone)) {
526
* Counts the selected entities in this container.
528
unsigned int RS_EntityContainer::countSelected() {
531
for (RS_Entity* t=firstEntity(RS2::ResolveNone);
533
t=nextEntity(RS2::ResolveNone)) {
535
if (t->isSelected()) {
544
* Counts the selected entities in this container.
546
double RS_EntityContainer::totalSelectedLength() {
548
for (RS_Entity* e = firstEntity(RS2::ResolveNone);
550
e = nextEntity(RS2::ResolveNone)) {
552
if (e->isVisible() && e->isSelected()) {
553
double l = e->getLength();
564
* Adjusts the borders of this graphic (max/min values)
566
void RS_EntityContainer::adjustBorders(RS_Entity* entity) {
567
//RS_DEBUG->print("RS_EntityContainer::adjustBorders");
571
// make sure a container is not empty (otherwise the border
572
// would get extended to 0/0):
573
if (!entity->isContainer() || entity->count()>0) {
574
minV = RS_Vector::minimum(entity->getMin(),minV);
575
maxV = RS_Vector::maximum(entity->getMax(),maxV);
578
// Notify parents. The border for the parent might
579
// also change TODO: Check for efficiency
581
//parent->adjustBorders(this);
588
* Recalculates the borders of this entity container.
590
void RS_EntityContainer::calculateBorders() {
591
RS_DEBUG->print("RS_EntityContainer::calculateBorders");
594
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
596
e=nextEntity(RS2::ResolveNone)) {
598
RS_Layer* layer = e->getLayer();
600
// RS_DEBUG->print("RS_EntityContainer::calculateBorders: "
601
// "isVisible: %d", (int)e->isVisible());
603
if (e->isVisible() && (layer==NULL || !layer->isFrozen())) {
604
e->calculateBorders();
609
RS_DEBUG->print("RS_EntityContainer::calculateBorders: size 1: %f,%f",
610
getSize().x, getSize().y);
612
// needed for correcting corrupt data (PLANS.dxf)
613
if (minV.x>maxV.x || minV.x>RS_MAXDOUBLE || maxV.x>RS_MAXDOUBLE
614
|| minV.x<RS_MINDOUBLE || maxV.x<RS_MINDOUBLE) {
619
if (minV.y>maxV.y || minV.y>RS_MAXDOUBLE || maxV.y>RS_MAXDOUBLE
620
|| minV.y<RS_MINDOUBLE || maxV.y<RS_MINDOUBLE) {
626
RS_DEBUG->print("RS_EntityCotnainer::calculateBorders: size: %f,%f",
627
getSize().x, getSize().y);
629
//RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
631
//printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
632
//RS_Entity::calculateBorders();
638
* Recalculates the borders of this entity container including
639
* invisible entities.
641
void RS_EntityContainer::forcedCalculateBorders() {
642
//RS_DEBUG->print("RS_EntityContainer::calculateBorders");
645
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
647
e=nextEntity(RS2::ResolveNone)) {
649
//RS_Layer* layer = e->getLayer();
651
if (e->isContainer()) {
652
((RS_EntityContainer*)e)->forcedCalculateBorders();
654
e->calculateBorders();
659
// needed for correcting corrupt data (PLANS.dxf)
660
if (minV.x>maxV.x || minV.x>RS_MAXDOUBLE || maxV.x>RS_MAXDOUBLE
661
|| minV.x<RS_MINDOUBLE || maxV.x<RS_MINDOUBLE) {
666
if (minV.y>maxV.y || minV.y>RS_MAXDOUBLE || maxV.y>RS_MAXDOUBLE
667
|| minV.y<RS_MINDOUBLE || maxV.y<RS_MINDOUBLE) {
673
//RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
675
//printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
676
//RS_Entity::calculateBorders();
682
* Updates all Dimension entities in this container and / or
683
* reposition their labels.
685
* @param autoText Automatically reposition the text label bool autoText=true
687
void RS_EntityContainer::updateDimensions(bool autoText) {
689
RS_DEBUG->print("RS_EntityContainer::updateDimensions()");
691
//for (RS_Entity* e=firstEntity(RS2::ResolveNone);
693
// e=nextEntity(RS2::ResolveNone)) {
696
for (int i = 0; i < entities.size(); ++i) {
698
if (RS_Information::isDimension(e->rtti())) {
699
// update and reposition label:
700
((RS_Dimension*)e)->updateDim(autoText);
701
} else if (e->isContainer()) {
702
((RS_EntityContainer*)e)->updateDimensions(autoText);
706
RS_DEBUG->print("RS_EntityContainer::updateDimensions() OK");
712
* Updates all Insert entities in this container.
714
void RS_EntityContainer::updateInserts() {
716
RS_DEBUG->print("RS_EntityContainer::updateInserts()");
718
//for (RS_Entity* e=firstEntity(RS2::ResolveNone);
720
// e=nextEntity(RS2::ResolveNone)) {
722
for (int i = 0; i < entities.size(); ++i) {
724
//// Only update our own inserts and not inserts of inserts
725
if (e->rtti()==RS2::EntityInsert /*&& e->getParent()==this*/) {
726
((RS_Insert*)e)->update();
727
} else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
728
((RS_EntityContainer*)e)->updateInserts();
732
RS_DEBUG->print("RS_EntityContainer::updateInserts() OK");
738
* Renames all inserts with name 'oldName' to 'newName'. This is
739
* called after a block was rename to update the inserts.
741
void RS_EntityContainer::renameInserts(const QString& oldName,
742
const QString& newName) {
743
RS_DEBUG->print("RS_EntityContainer::renameInserts()");
745
//for (RS_Entity* e=firstEntity(RS2::ResolveNone);
747
// e=nextEntity(RS2::ResolveNone)) {
750
for (int j = 0; j < entities.size(); ++j) {
752
if (e->rtti()==RS2::EntityInsert) {
753
RS_Insert* i = ((RS_Insert*)e);
754
if (i->getName()==oldName) {
757
} else if (e->isContainer()) {
758
((RS_EntityContainer*)e)->renameInserts(oldName, newName);
762
RS_DEBUG->print("RS_EntityContainer::renameInserts() OK");
769
* Updates all Spline entities in this container.
771
void RS_EntityContainer::updateSplines() {
773
RS_DEBUG->print("RS_EntityContainer::updateSplines()");
775
//for (RS_Entity* e=firstEntity(RS2::ResolveNone);
777
// e=nextEntity(RS2::ResolveNone)) {
779
for (int i = 0; i < entities.size(); ++i) {
781
//// Only update our own inserts and not inserts of inserts
782
if (e->rtti()==RS2::EntitySpline /*&& e->getParent()==this*/) {
783
((RS_Spline*)e)->update();
784
} else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
785
((RS_EntityContainer*)e)->updateSplines();
789
RS_DEBUG->print("RS_EntityContainer::updateSplines() OK");
794
* Updates the sub entities of this container.
796
void RS_EntityContainer::update() {
797
//for (RS_Entity* e=firstEntity(RS2::ResolveNone);
799
// e=nextEntity(RS2::ResolveNone)) {
800
for (int i = 0; i < entities.size(); ++i) {
801
entities.at(i)->update();
808
* Returns the first entity or NULL if this graphic is empty.
811
RS_Entity* RS_EntityContainer::firstEntity(RS2::ResolveLevel level) {
815
case RS2::ResolveNone:
816
if (!entities.isEmpty()) {
818
return entities.first();
822
case RS2::ResolveAllButInserts: {
824
if (!entities.isEmpty()) {
826
e = entities.first();
828
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityInsert) {
829
subContainer = (RS_EntityContainer*)e;
830
e = ((RS_EntityContainer*)e)->firstEntity(level);
834
e = nextEntity(level);
841
case RS2::ResolveAllButTextImage:
842
case RS2::ResolveAllButTexts: {
844
if (!entities.isEmpty()) {
846
e = entities.first();
848
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityText && e->rtti()!=RS2::EntityMText) {
849
subContainer = (RS_EntityContainer*)e;
850
e = ((RS_EntityContainer*)e)->firstEntity(level);
854
e = nextEntity(level);
861
case RS2::ResolveAll: {
863
if (!entities.isEmpty()) {
865
e = entities.first();
867
if (e!=NULL && e->isContainer()) {
868
subContainer = (RS_EntityContainer*)e;
869
e = ((RS_EntityContainer*)e)->firstEntity(level);
873
e = nextEntity(level);
887
* Returns the last entity or \p NULL if this graphic is empty.
889
* @param level \li \p 0 Groups are not resolved
890
* \li \p 1 (default) only Groups are resolved
891
* \li \p 2 all Entity Containers are resolved
893
RS_Entity* RS_EntityContainer::lastEntity(RS2::ResolveLevel level) {
895
entIdx = entities.size()-1;
897
case RS2::ResolveNone:
898
if (!entities.isEmpty())
899
return entities.last();
902
case RS2::ResolveAllButInserts: {
903
if (!entities.isEmpty())
906
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityInsert) {
907
subContainer = (RS_EntityContainer*)e;
908
e = ((RS_EntityContainer*)e)->lastEntity(level);
913
case RS2::ResolveAllButTextImage:
914
case RS2::ResolveAllButTexts: {
915
if (!entities.isEmpty())
918
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityText && e->rtti()!=RS2::EntityMText) {
919
subContainer = (RS_EntityContainer*)e;
920
e = ((RS_EntityContainer*)e)->lastEntity(level);
926
case RS2::ResolveAll: {
927
if (!entities.isEmpty())
930
if (e!=NULL && e->isContainer()) {
931
subContainer = (RS_EntityContainer*)e;
932
e = ((RS_EntityContainer*)e)->lastEntity(level);
944
* Returns the next entity or container or \p NULL if the last entity
945
* returned by \p next() was the last entity in the container.
947
RS_Entity* RS_EntityContainer::nextEntity(RS2::ResolveLevel level) {
949
//set entIdx pointing in next entity and check if is out of range
952
case RS2::ResolveNone:
953
if ( entIdx < entities.size() )
954
return entities.at(entIdx);
957
case RS2::ResolveAllButInserts: {
959
if (subContainer!=NULL) {
960
e = subContainer->nextEntity(level);
962
--entIdx; //return a sub-entity, index not advanced
965
if ( entIdx < entities.size() )
966
e = entities.at(entIdx);
969
if ( entIdx < entities.size() )
970
e = entities.at(entIdx);
972
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityInsert) {
973
subContainer = (RS_EntityContainer*)e;
974
e = ((RS_EntityContainer*)e)->firstEntity(level);
978
e = nextEntity(level);
985
case RS2::ResolveAllButTextImage:
986
case RS2::ResolveAllButTexts: {
988
if (subContainer!=NULL) {
989
e = subContainer->nextEntity(level);
991
--entIdx; //return a sub-entity, index not advanced
994
if ( entIdx < entities.size() )
995
e = entities.at(entIdx);
998
if ( entIdx < entities.size() )
999
e = entities.at(entIdx);
1001
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityText && e->rtti()!=RS2::EntityMText ) {
1002
subContainer = (RS_EntityContainer*)e;
1003
e = ((RS_EntityContainer*)e)->firstEntity(level);
1006
subContainer = NULL;
1007
e = nextEntity(level);
1014
case RS2::ResolveAll: {
1016
if (subContainer!=NULL) {
1017
e = subContainer->nextEntity(level);
1019
--entIdx; //return a sub-entity, index not advanced
1022
if ( entIdx < entities.size() )
1023
e = entities.at(entIdx);
1026
if ( entIdx < entities.size() )
1027
e = entities.at(entIdx);
1029
if (e!=NULL && e->isContainer()) {
1030
subContainer = (RS_EntityContainer*)e;
1031
e = ((RS_EntityContainer*)e)->firstEntity(level);
1034
subContainer = NULL;
1035
e = nextEntity(level);
1048
* Returns the prev entity or container or \p NULL if the last entity
1049
* returned by \p prev() was the first entity in the container.
1051
RS_Entity* RS_EntityContainer::prevEntity(RS2::ResolveLevel level) {
1052
//set entIdx pointing in prev entity and check if is out of range
1056
case RS2::ResolveNone:
1058
return entities.at(entIdx);
1061
case RS2::ResolveAllButInserts: {
1063
if (subContainer!=NULL) {
1064
e = subContainer->prevEntity(level);
1069
e = entities.at(entIdx);
1073
e = entities.at(entIdx);
1075
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityInsert) {
1076
subContainer = (RS_EntityContainer*)e;
1077
e = ((RS_EntityContainer*)e)->lastEntity(level);
1080
subContainer = NULL;
1081
e = prevEntity(level);
1087
case RS2::ResolveAllButTextImage:
1088
case RS2::ResolveAllButTexts: {
1090
if (subContainer!=NULL) {
1091
e = subContainer->prevEntity(level);
1096
e = entities.at(entIdx);
1100
e = entities.at(entIdx);
1102
if (e!=NULL && e->isContainer() && e->rtti()!=RS2::EntityText && e->rtti()!=RS2::EntityMText) {
1103
subContainer = (RS_EntityContainer*)e;
1104
e = ((RS_EntityContainer*)e)->lastEntity(level);
1107
subContainer = NULL;
1108
e = prevEntity(level);
1114
case RS2::ResolveAll: {
1116
if (subContainer!=NULL) {
1117
e = subContainer->prevEntity(level);
1119
++entIdx; //return a sub-entity, index not advanced
1123
e = entities.at(entIdx);
1127
e = entities.at(entIdx);
1129
if (e!=NULL && e->isContainer()) {
1130
subContainer = (RS_EntityContainer*)e;
1131
e = ((RS_EntityContainer*)e)->lastEntity(level);
1134
subContainer = NULL;
1135
e = prevEntity(level);
1147
* @return Entity at the given index or NULL if the index is out of range.
1149
RS_Entity* RS_EntityContainer::entityAt(int index) {
1150
if (entities.size() > index && index >= 0)
1151
return entities.at(index);
1159
* @return Current index.
1162
int RS_EntityContainer::entityAt() {
1168
* Finds the given entity and makes it the current entity if found.
1170
int RS_EntityContainer::findEntity(RS_Entity* entity) {
1171
entIdx = entities.indexOf(entity);
1178
* Returns the copy to a new iterator for traversing the entities.
1180
QListIterator<RS_Entity*> RS_EntityContainer::createIterator() {
1181
return QListIterator<RS_Entity*>(entities);
1186
* @return The point which is closest to 'coord'
1187
* (one of the vertexes)
1189
RS_Vector RS_EntityContainer::getNearestEndpoint(const RS_Vector& coord,
1190
double* dist )const {
1192
double minDist = RS_MAXDOUBLE; // minimum measured distance
1193
double curDist; // currently measured distance
1194
RS_Vector closestPoint(false); // closest found endpoint
1195
RS_Vector point; // endpoint found
1197
//QListIterator<RS_Entity> it = createIterator();
1199
//while ( (en = it.current()) != NULL ) {
1201
for (RS_Entity* en = const_cast<RS_EntityContainer*>(this)->firstEntity();
1203
en = const_cast<RS_EntityContainer*>(this)->nextEntity()) {
1206
//&& en->getParent()->rtti() != RS2::EntityInsert /**Insert*/
1207
//&& en->rtti() != RS2::EntityPoint /**Point*/
1208
//&& en->getParent()->rtti() != RS2::EntitySpline
1209
//&& en->getParent()->rtti() != RS2::EntityMText /**< Text 15*/
1210
//&& en->getParent()->rtti() != RS2::EntityText /**< Text 15*/
1211
&& en->getParent()->rtti() != RS2::EntityDimAligned /**< Aligned Dimension */
1212
&& en->getParent()->rtti() != RS2::EntityDimLinear /**< Linear Dimension */
1213
&& en->getParent()->rtti() != RS2::EntityDimRadial /**< Radial Dimension */
1214
&& en->getParent()->rtti() != RS2::EntityDimDiametric /**< Diametric Dimension */
1215
&& en->getParent()->rtti() != RS2::EntityDimAngular /**< Angular Dimension */
1216
&& en->getParent()->rtti() != RS2::EntityDimLeader /**< Leader Dimension */
1217
){//no end point for Insert, text, Dim
1218
point = en->getNearestEndpoint(coord, &curDist);
1219
if (point.valid && curDist<minDist) {
1220
closestPoint = point;
1229
return closestPoint;
1235
* @return The point which is closest to 'coord'
1236
* (one of the vertexes)
1238
RS_Vector RS_EntityContainer::getNearestEndpoint(const RS_Vector& coord,
1239
double* dist, RS_Entity** pEntity)const {
1241
double minDist = RS_MAXDOUBLE; // minimum measured distance
1242
double curDist; // currently measured distance
1243
RS_Vector closestPoint(false); // closest found endpoint
1244
RS_Vector point; // endpoint found
1246
//QListIterator<RS_Entity> it = createIterator();
1248
//while ( (en = it.current()) != NULL ) {
1252
for (RS_Entity* en = const_cast<RS_EntityContainer*>(this)->firstEntity();
1254
en = const_cast<RS_EntityContainer*>(this)->nextEntity()) {
1257
if (/*en->isVisible()*/
1258
//&& en->getParent()->rtti() != RS2::EntityInsert /**Insert*/
1259
//&& en->rtti() != RS2::EntityPoint /**Point*/
1260
//&& en->getParent()->rtti() != RS2::EntitySpline
1261
//&& en->getParent()->rtti() != RS2::EntityMText /**< Text 15*/
1262
//&& en->getParent()->rtti() != RS2::EntityText /**< Text 15*/
1263
/*&&*/ en->getParent()->rtti() != RS2::EntityDimAligned /**< Aligned Dimension */
1264
&& en->getParent()->rtti() != RS2::EntityDimLinear /**< Linear Dimension */
1265
&& en->getParent()->rtti() != RS2::EntityDimRadial /**< Radial Dimension */
1266
&& en->getParent()->rtti() != RS2::EntityDimDiametric /**< Diametric Dimension */
1267
&& en->getParent()->rtti() != RS2::EntityDimAngular /**< Angular Dimension */
1268
&& en->getParent()->rtti() != RS2::EntityDimLeader /**< Leader Dimension */
1269
){//no end point for Insert, text, Dim
1270
// std::cout<<"find nearest for entity "<<i0<<std::endl;
1271
point = en->getNearestEndpoint(coord, &curDist);
1272
if (point.valid && curDist<minDist) {
1273
closestPoint = point;
1286
// std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
1287
// std::cout<<"count()="<<const_cast<RS_EntityContainer*>(this)->count()<<"\tminDist= "<<minDist<<"\tclosestPoint="<<closestPoint;
1288
// if(pEntity != NULL) std::cout<<"\t*pEntity="<<*pEntity;
1289
// std::cout<<std::endl;
1290
return closestPoint;
1295
RS_Vector RS_EntityContainer::getNearestPointOnEntity(const RS_Vector& coord,
1296
bool onEntity, double* dist, RS_Entity** entity)const {
1298
RS_Vector point(false);
1300
RS_Entity* en = const_cast<RS_EntityContainer*>(this)->getNearestEntity(coord, dist, RS2::ResolveNone);
1303
if ( en->isVisible()
1304
&& en->getParent()->rtti() != RS2::EntityInsert /**Insert*/
1305
//&& en->rtti() != RS2::EntityPoint /**Point*/
1306
&& en->getParent()->rtti() != RS2::EntitySpline
1307
&& en->getParent()->rtti() != RS2::EntityMText /**< Text 15*/
1308
&& en->getParent()->rtti() != RS2::EntityText /**< Text 15*/
1309
&& en->getParent()->rtti() != RS2::EntityDimAligned /**< Aligned Dimension */
1310
&& en->getParent()->rtti() != RS2::EntityDimLinear /**< Linear Dimension */
1311
&& en->getParent()->rtti() != RS2::EntityDimRadial /**< Radial Dimension */
1312
&& en->getParent()->rtti() != RS2::EntityDimDiametric /**< Diametric Dimension */
1313
&& en->getParent()->rtti() != RS2::EntityDimAngular /**< Angular Dimension */
1314
&& en->getParent()->rtti() != RS2::EntityDimLeader /**< Leader Dimension */
1315
){//no middle point for Spline, Insert, text, Dim
1316
point = en->getNearestPointOnEntity(coord, onEntity, dist, entity);
1325
RS_Vector RS_EntityContainer::getNearestCenter(const RS_Vector& coord,
1327
double minDist = RS_MAXDOUBLE; // minimum measured distance
1328
double curDist = RS_MAXDOUBLE; // currently measured distance
1329
RS_Vector closestPoint(false); // closest found endpoint
1330
RS_Vector point; // endpoint found
1332
for (RS_Entity* en = const_cast<RS_EntityContainer*>(this)->firstEntity();
1334
en = const_cast<RS_EntityContainer*>(this)->nextEntity()) {
1337
&& en->getParent()->rtti() != RS2::EntitySpline
1338
&& en->getParent()->rtti() != RS2::EntityMText /**< Text 16*/
1339
&& en->getParent()->rtti() != RS2::EntityText /**< Text 17*/
1340
&& en->getParent()->rtti() != RS2::EntityDimAligned /**< Aligned Dimension */
1341
&& en->getParent()->rtti() != RS2::EntityDimLinear /**< Linear Dimension */
1342
&& en->getParent()->rtti() != RS2::EntityDimRadial /**< Radial Dimension */
1343
&& en->getParent()->rtti() != RS2::EntityDimDiametric /**< Diametric Dimension */
1344
&& en->getParent()->rtti() != RS2::EntityDimAngular /**< Angular Dimension */
1345
&& en->getParent()->rtti() != RS2::EntityDimLeader /**< Leader Dimension */
1346
){//no center point for spline, text, Dim
1347
point = en->getNearestCenter(coord, &curDist);
1348
if (point.valid && curDist<minDist) {
1349
closestPoint = point;
1358
return closestPoint;
1361
/** @return the nearest of equidistant middle points of the line. */
1363
RS_Vector RS_EntityContainer::getNearestMiddle(const RS_Vector& coord,
1367
double minDist = RS_MAXDOUBLE; // minimum measured distance
1368
double curDist = RS_MAXDOUBLE; // currently measured distance
1369
RS_Vector closestPoint(false); // closest found endpoint
1370
RS_Vector point; // endpoint found
1372
for (RS_Entity* en = const_cast<RS_EntityContainer*>(this)->firstEntity();
1374
en = const_cast<RS_EntityContainer*>(this)->nextEntity()) {
1377
&& en->getParent()->rtti() != RS2::EntitySpline
1378
&& en->getParent()->rtti() != RS2::EntityMText /**< Text 16*/
1379
&& en->getParent()->rtti() != RS2::EntityText /**< Text 17*/
1380
&& en->getParent()->rtti() != RS2::EntityDimAligned /**< Aligned Dimension */
1381
&& en->getParent()->rtti() != RS2::EntityDimLinear /**< Linear Dimension */
1382
&& en->getParent()->rtti() != RS2::EntityDimRadial /**< Radial Dimension */
1383
&& en->getParent()->rtti() != RS2::EntityDimDiametric /**< Diametric Dimension */
1384
&& en->getParent()->rtti() != RS2::EntityDimAngular /**< Angular Dimension */
1385
&& en->getParent()->rtti() != RS2::EntityDimLeader /**< Leader Dimension */
1386
){//no midle point for spline, text, Dim
1387
point = en->getNearestMiddle(coord, &curDist, middlePoints);
1388
if (point.valid && curDist<minDist) {
1389
closestPoint = point;
1398
return closestPoint;
1403
RS_Vector RS_EntityContainer::getNearestDist(double distance,
1404
const RS_Vector& coord,
1407
RS_Vector point(false);
1408
RS_Entity* closestEntity;
1410
closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1412
if (closestEntity!=NULL) {
1413
point = closestEntity->getNearestDist(distance, coord, dist);
1422
* @return The intersection which is closest to 'coord'
1424
RS_Vector RS_EntityContainer::getNearestIntersection(const RS_Vector& coord,
1427
double minDist = RS_MAXDOUBLE; // minimum measured distance
1428
double curDist = RS_MAXDOUBLE; // currently measured distance
1429
RS_Vector closestPoint(false); // closest found endpoint
1430
RS_Vector point; // endpoint found
1431
RS_VectorSolutions sol;
1432
RS_Entity* closestEntity;
1434
closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAllButTextImage);
1436
if (closestEntity!=NULL) {
1437
for (RS_Entity* en = firstEntity(RS2::ResolveAllButTextImage);
1439
en = nextEntity(RS2::ResolveAllButTextImage)) {
1442
|| en == closestEntity
1443
|| en->rtti() == RS2::EntityPoint /**Point*/
1444
|| en->getParent()->rtti() == RS2::EntityMText /**< Text 15*/
1445
|| en->getParent()->rtti() == RS2::EntityText /**< Text 15*/
1446
|| en->getParent()->rtti() == RS2::EntityDimAligned /**< Aligned Dimension */
1447
|| en->getParent()->rtti() == RS2::EntityDimLinear /**< Linear Dimension */
1448
|| en->getParent()->rtti() == RS2::EntityDimRadial /**< Radial Dimension */
1449
|| en->getParent()->rtti() == RS2::EntityDimDiametric /**< Diametric Dimension */
1450
|| en->getParent()->rtti() == RS2::EntityDimAngular /**< Angular Dimension */
1451
|| en->getParent()->rtti() == RS2::EntityDimLeader /**< Leader Dimension */
1452
|| en->getParent()->rtti() == RS2::EntityImage /**< Leader Dimension */
1453
){//do not do intersection for point, text, Dim
1457
sol = RS_Information::getIntersection(closestEntity,
1461
point=sol.getClosest(coord,&curDist,NULL);
1462
if(sol.getNumber()>0 && curDist<minDist){
1469
if(dist!=NULL && closestPoint.valid) {
1473
return closestPoint;
1478
RS_Vector RS_EntityContainer::getNearestRef(const RS_Vector& coord,
1481
double minDist = RS_MAXDOUBLE; // minimum measured distance
1482
double curDist; // currently measured distance
1483
RS_Vector closestPoint(false); // closest found endpoint
1484
RS_Vector point; // endpoint found
1486
for (RS_Entity* en = firstEntity();
1488
en = nextEntity()) {
1490
if (en->isVisible()) {
1491
point = en->getNearestRef(coord, &curDist);
1492
if (point.valid && curDist<minDist) {
1493
closestPoint = point;
1502
return closestPoint;
1506
RS_Vector RS_EntityContainer::getNearestSelectedRef(const RS_Vector& coord,
1509
double minDist = RS_MAXDOUBLE; // minimum measured distance
1510
double curDist; // currently measured distance
1511
RS_Vector closestPoint(false); // closest found endpoint
1512
RS_Vector point; // endpoint found
1514
for (RS_Entity* en = firstEntity();
1516
en = nextEntity()) {
1518
if (en->isVisible() && en->isSelected() && !en->isParentSelected()) {
1519
point = en->getNearestSelectedRef(coord, &curDist);
1520
if (point.valid && curDist<minDist) {
1521
closestPoint = point;
1530
return closestPoint;
1534
double RS_EntityContainer::getDistanceToPoint(const RS_Vector& coord,
1536
RS2::ResolveLevel level,
1537
double solidDist) const{
1539
RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint");
1542
double minDist = RS_MAXDOUBLE; // minimum measured distance
1543
double curDist; // currently measured distance
1544
RS_Entity* closestEntity = NULL; // closest entity found
1545
RS_Entity* subEntity = NULL;
1548
for (RS_Entity* e =const_cast<RS_EntityContainer*>(this)-> firstEntity(level);
1550
e =const_cast<RS_EntityContainer*>(this)-> nextEntity(level)) {
1552
if (e->isVisible()) {
1553
RS_DEBUG->print("entity: getDistanceToPoint");
1554
RS_DEBUG->print("entity: %d", e->rtti());
1555
// bug#426, need to ignore Images to find nearest intersections
1556
if(level==RS2::ResolveAllButTextImage && e->rtti()==RS2::EntityImage) continue;
1557
curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1559
RS_DEBUG->print("entity: getDistanceToPoint: OK");
1561
if (curDist<minDist) {
1562
if (level!=RS2::ResolveAll) {
1565
closestEntity = subEntity;
1573
*entity = closestEntity;
1575
RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint: OK");
1582
RS_Entity* RS_EntityContainer::getNearestEntity(const RS_Vector& coord,
1584
RS2::ResolveLevel level) {
1586
RS_DEBUG->print("RS_EntityContainer::getNearestEntity");
1588
RS_Entity* e = NULL;
1590
// distance for points inside solids:
1591
double solidDist = RS_MAXDOUBLE;
1596
double d = getDistanceToPoint(coord, &e, level, solidDist);
1598
if (e!=NULL && e->isVisible()==false) {
1602
// if d is negative, use the default distance (used for points inside solids)
1606
RS_DEBUG->print("RS_EntityContainer::getNearestEntity: OK");
1614
* Rearranges the atomic entities in this container in a way that connected
1615
* entities are stored in the right order and direction.
1616
* Non-recoursive. Only affects atomic entities in this container.
1618
* @retval true all contours were closed
1619
* @retval false at least one contour is not closed
1621
* to do: find closed contour by flood-fill
1623
bool RS_EntityContainer::optimizeContours() {
1624
// std::cout<<"RS_EntityContainer::optimizeContours: begin"<<std::endl;
1627
// std::cout<<"loop with count()="<<count()<<std::endl;
1628
RS_DEBUG->print("RS_EntityContainer::optimizeContours");
1630
RS_EntityContainer tmp;
1631
tmp.setAutoUpdateBorders(false);
1634
/** accept all full circles **/
1635
QList<RS_Entity*> enList;
1636
for (unsigned ci=0; ci<count(); ++ci) {
1637
RS_Entity* e1=entityAt(ci);
1638
if (!e1->isEdge() || e1->isContainer() ) {
1642
if(e1->rtti()==RS2::EntityCircle) {
1643
//directly detect circles, bug#3443277
1644
tmp.addEntity(e1->clone());
1648
if(e1->rtti()==RS2::EntityEllipse) {
1649
if(static_cast<RS_Ellipse*>(e1)->isArc() == false){
1650
tmp.addEntity(e1->clone());
1656
// std::cout<<"RS_EntityContainer::optimizeContours: 1"<<std::endl;
1658
/** remove unsupported entities */
1659
const auto itEnd=enList.end();
1660
for(auto it=enList.begin();it!=itEnd;it++){
1664
/** check and form a closed contour **/
1665
// std::cout<<"RS_EntityContainer::optimizeContours: 2"<<std::endl;
1666
/** the first entity **/
1667
RS_Entity* current(NULL);
1669
current=entityAt(0)->clone();
1670
tmp.addEntity(current);
1671
removeEntity(entityAt(0));
1673
if(tmp.count()==0) return false;
1675
// std::cout<<"RS_EntityContainer::optimizeContours: 3"<<std::endl;
1679
vpStart=current->getStartpoint();
1680
vpEnd=current->getEndpoint();
1682
RS_Entity* next(NULL);
1683
// std::cout<<"RS_EntityContainer::optimizeContours: 4"<<std::endl;
1684
/** connect entities **/
1687
// std::cout<<" count()="<<count()<<std::endl;
1688
getNearestEndpoint(vpEnd,&dist,&next);
1690
if(vpEnd.squaredTo(vpStart)<1e-8){
1691
RS_Entity* e2=entityAt(0);
1692
tmp.addEntity(e2->clone());
1693
vpStart=e2->getStartpoint();
1694
vpEnd=e2->getEndpoint();
1700
if(next && closed){ //workaround if next is NULL
1701
next->setProcessed(true);
1702
RS_Entity* eTmp = next->clone();
1703
if(vpEnd.squaredTo(next->getStartpoint())>1e-8)
1704
eTmp->revertDirection();
1705
vpEnd=( vpEnd.squaredTo(next->getStartpoint()) > vpEnd.squaredTo(next->getEndpoint()) )? next->getStartpoint():next->getEndpoint();
1706
tmp.addEntity(eTmp);
1708
} else { //workaround if next is NULL
1709
// std::cout<<"RS_EntityContainer::optimizeContours: next is NULL" <<std::endl;
1711
closed=false; //workaround if next is NULL
1712
break; //workaround if next is NULL
1713
} //workaround if next is NULL
1716
if(vpEnd.valid && vpEnd.squaredTo(vpStart)>1e-8) {
1717
// std::cout<<"ds2="<<vpEnd.squaredTo(vpStart)<<std::endl;
1720
// std::cout<<"RS_EntityContainer::optimizeContours: 5"<<std::endl;
1723
// add new sorted entities:
1724
for (RS_Entity* en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity()) {
1725
en->setProcessed(false);
1726
addEntity(en->clone());
1728
// std::cout<<"RS_EntityContainer::optimizeContours: 6"<<std::endl;
1730
RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
1731
// std::cout<<"RS_EntityContainer::optimizeContours: end: count()="<<count()<<std::endl;
1732
// std::cout<<"RS_EntityContainer::optimizeContours: closed="<<closed<<std::endl;
1737
bool RS_EntityContainer::hasEndpointsWithinWindow(const RS_Vector& v1, const RS_Vector& v2) {
1738
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1740
e=nextEntity(RS2::ResolveNone)) {
1741
if (e->hasEndpointsWithinWindow(v1, v2)) {
1750
void RS_EntityContainer::move(const RS_Vector& offset) {
1751
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1753
e=nextEntity(RS2::ResolveNone)) {
1755
if (autoUpdateBorders) {
1756
e->moveBorders(offset);
1759
if (autoUpdateBorders) {
1760
moveBorders(offset);
1766
void RS_EntityContainer::rotate(const RS_Vector& center, const double& angle) {
1767
RS_Vector angleVector(angle);
1768
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1770
e=nextEntity(RS2::ResolveNone)) {
1771
e->rotate(center, angleVector);
1773
if (autoUpdateBorders) {
1779
void RS_EntityContainer::rotate(const RS_Vector& center, const RS_Vector& angleVector) {
1780
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1782
e=nextEntity(RS2::ResolveNone)) {
1783
e->rotate(center, angleVector);
1785
if (autoUpdateBorders) {
1791
void RS_EntityContainer::scale(const RS_Vector& center, const RS_Vector& factor) {
1792
if (fabs(factor.x)>RS_TOLERANCE && fabs(factor.y)>RS_TOLERANCE) {
1793
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1795
e=nextEntity(RS2::ResolveNone)) {
1796
e->scale(center, factor);
1799
if (autoUpdateBorders) {
1806
void RS_EntityContainer::mirror(const RS_Vector& axisPoint1, const RS_Vector& axisPoint2) {
1807
if (axisPoint1.distanceTo(axisPoint2)>1.0e-6) {
1808
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1810
e=nextEntity(RS2::ResolveNone)) {
1811
e->mirror(axisPoint1, axisPoint2);
1817
void RS_EntityContainer::stretch(const RS_Vector& firstCorner,
1818
const RS_Vector& secondCorner,
1819
const RS_Vector& offset) {
1821
if (getMin().isInWindow(firstCorner, secondCorner) &&
1822
getMax().isInWindow(firstCorner, secondCorner)) {
1826
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1828
e=nextEntity(RS2::ResolveNone)) {
1829
e->stretch(firstCorner, secondCorner, offset);
1833
// some entitiycontainers might need an update (e.g. RS_Leader):
1839
void RS_EntityContainer::moveRef(const RS_Vector& ref,
1840
const RS_Vector& offset) {
1842
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1844
e=nextEntity(RS2::ResolveNone)) {
1845
e->moveRef(ref, offset);
1847
if (autoUpdateBorders) {
1853
void RS_EntityContainer::moveSelectedRef(const RS_Vector& ref,
1854
const RS_Vector& offset) {
1856
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1858
e=nextEntity(RS2::ResolveNone)) {
1859
e->moveSelectedRef(ref, offset);
1861
if (autoUpdateBorders) {
1866
void RS_EntityContainer::revertDirection() {
1867
for(int k = 0; k < entities.size() / 2; k++) {
1868
entities.swap(k, entities.size() - 1 - k);
1871
foreach(RS_Entity* entity, entities) {
1872
entity->revertDirection();
1878
void RS_EntityContainer::draw(RS_Painter* painter, RS_GraphicView* view,
1879
double& /*patternOffset*/) {
1881
if (painter==NULL || view==NULL) {
1885
QList<RS_Entity*> entities;
1886
for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1888
e = nextEntity(RS2::ResolveNone)) {
1889
//view->drawEntity(painter, e);
1892
std::stable_sort(entities.begin(), entities.end(), [](const RS_Entity* e1, const RS_Entity* e2)->bool{
1893
const RS_Layer* l1=e1->getLayer();
1894
const RS_Layer* l2=e2->getLayer();
1895
if(l1 != NULL || l2 != NULL ) {
1896
if(l1==NULL) return false;
1897
if(l2==NULL) return true;
1898
if (e1->getLayer()->getName() < e2->getLayer()->getName()) return true;
1900
if (e1->getLayer()->getName() > e2->getLayer()->getName()) return false;
1902
return e1->getId() < e2->getId();
1904
for(RS_Entity* e: entities){
1905
view->drawEntity(painter, e);
1911
* Dumps the entities to stdout.
1913
std::ostream& operator << (std::ostream& os, RS_EntityContainer& ec) {
1915
static int indent = 0;
1917
char* tab = new char[indent*2+1];
1918
for(int i=0; i<indent*2; ++i) {
1921
tab[indent*2] = '\0';
1925
unsigned long int id = ec.getId();
1927
os << tab << "EntityContainer[" << id << "]: \n";
1928
os << tab << "Borders[" << id << "]: "
1929
<< ec.minV << " - " << ec.maxV << "\n";
1930
//os << tab << "Unit[" << id << "]: "
1931
//<< RS_Units::unit2string (ec.unit) << "\n";
1932
if (ec.getLayer()!=NULL) {
1933
os << tab << "Layer[" << id << "]: "
1934
<< ec.getLayer()->getName().toLatin1().data() << "\n";
1936
os << tab << "Layer[" << id << "]: <NULL>\n";
1938
//os << ec.layerList << "\n";
1940
os << tab << " Flags[" << id << "]: "
1941
<< (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1942
os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1943
os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1947
os << tab << "Entities[" << id << "]: \n";
1948
for (RS_Entity* t=ec.firstEntity();
1950
t=ec.nextEntity()) {
1952
switch (t->rtti()) {
1953
case RS2::EntityInsert:
1954
os << tab << *((RS_Insert*)t);
1955
os << tab << *((RS_Entity*)t);
1956
os << tab << *((RS_EntityContainer*)t);
1959
if (t->isContainer()) {
1960
os << tab << *((RS_EntityContainer*)t);
1967
os << tab << "\n\n";