+++ /dev/null
-// entitycontainer.cpp
-//
-// Part of the Architektonas Project
-// Originally part of QCad Community Edition by Andrew Mustun
-// Extensively rewritten and refactored by James L. Hammons
-// Portions copyright (C) 2001-2003 RibbonSoft
-// Copyright (C) 2010 Underground Software
-// See the README and GPLv2 files for licensing and warranty information
-//
-// JLH = James L. Hammons <jlhamm@acm.org>
-//
-// Who When What
-// --- ---------- -----------------------------------------------------------
-// JLH 05/28/2010 Added this text. :-)
-//
-
-#include "entitycontainer.h"
-
-#include "debug.h"
-#include "dimension.h"
-#include "mathextra.h"
-#include "layer.h"
-#include "line.h"
-#include "polyline.h"
-#include "text.h"
-#include "insert.h"
-#include "spline.h"
-#include "information.h"
-#include "graphicview.h"
-#include "paintinterface.h"
-
-bool EntityContainer::autoUpdateBorders = true;
-
-/**
- * Default constructor.
- *
- * @param owner True if we own and also delete the entities.
- */
-EntityContainer::EntityContainer(EntityContainer * parent/*= NULL*/, bool owner/*= true*/):
- Entity(parent), entityIterator(entities)
-//NOTE: This constructor may not be explicitly OR implicitly called, meaning that
-// entityIterator will not get initialized!
-{
-#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
-// entities.setAutoDelete(owner);
- DEBUG->print("EntityContainer::EntityContainer: owner: %d", (int)owner);
- subContainer = NULL;
- //autoUpdateBorders = true;
-}
-
-/**
- * Copy constructor. Makes a deep copy of all entities.
- */
-/*
-EntityContainer::EntityContainer(const EntityContainer& ec)
- : Entity(ec)
-{
-}
-*/
-
-/**
- * Destructor.
- */
-EntityContainer::~EntityContainer()
-{
- clear();
-}
-
-Entity * EntityContainer::clone()
-{
-// DEBUG->print("EntityContainer::clone: ori autoDel: %d", entities.autoDelete());
- EntityContainer * ec = new EntityContainer(*this);
-#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
-// ec->entities.setAutoDelete(entities.autoDelete());
-// DEBUG->print("EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete());
- ec->detach();
- ec->initId();
-
- return ec;
-}
-
-/**
- * Detaches shallow copies and creates deep copies of all subentities.
- * This is called after cloning entity containers.
- */
-void EntityContainer::detach()
-{
-// Q3PtrList<Entity> tmp;
- QList<Entity *> tmp;
-#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
-// bool autoDel = entities.autoDelete();
-// DEBUG->print("EntityContainer::detach: autoDel: %d", (int)autoDel);
-// entities.setAutoDelete(false);
-
- // make deep copies of all entities:
- for(Entity * e=firstEntity(); e!=NULL; e=nextEntity())
- {
- if (!e->getFlag(RS2::FlagTemp))
- {
- tmp.append(e->clone());
- }
- }
-
- // clear shared pointers:
- entities.clear();
-// entities.setAutoDelete(autoDel);
-
- // point to new deep copies:
-// for(Entity * e=tmp.first(); e!=NULL; e=tmp.next())
- for(int i=0; i<tmp.size(); i++)
- {
- Entity * e = tmp[i];
- entities.append(e);
- e->reparent(this);
- }
-}
-
-/** @return RS2::EntityContainer */
-/*virtual*/ RS2::EntityType EntityContainer::rtti() const
-{
- return RS2::EntityContainer;
-}
-
-void EntityContainer::reparent(EntityContainer * parent)
-{
- Entity::reparent(parent);
-
- // All sub-entities:
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->reparent(parent);
-}
-
-/**
- * @return true: because entities made from this class
- * and subclasses are containers for other entities.
- */
-/*virtual*/ bool EntityContainer::isContainer() const
-{
- return true;
-}
-
-/**
- * @return false: because entities made from this class
- * and subclasses are containers for other entities.
- */
-/*virtual*/ bool EntityContainer::isAtomic() const
-{
- return false;
-}
-
-/**
- * Called when the undo state changed. Forwards the event to all sub-entities.
- *
- * @param undone true: entity has become invisible.
- * false: entity has become visible.
- */
-void EntityContainer::undoStateChanged(bool undone)
-{
- Entity::undoStateChanged(undone);
-
- // ! don't pass on to subentities. undo list handles them
- // All sub-entities:
- /*for (Entity* e=firstEntity(RS2::ResolveNone);
- e!=NULL;
- e=nextEntity(RS2::ResolveNone)) {
- e->setUndoState(undone);
-}*/
-}
-
-void EntityContainer::setVisible(bool v)
-{
- DEBUG->print("EntityContainer::setVisible: %d", v);
- Entity::setVisible(v);
-
- // All sub-entities:
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- DEBUG->print("EntityContainer::setVisible: subentity: %d", v);
- e->setVisible(v);
- }
-}
-
-/**
- * @return Total length of all entities in this container.
- */
-double EntityContainer::getLength()
-{
- double ret = 0.0;
-
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- if (e->isVisible())
- {
- double l = e->getLength();
-
- if (l < 0.0)
- {
- ret = -1.0;
- break;
- }
- else
- {
- ret += l;
- }
- }
- }
-
- return ret;
-}
-
-/**
- * Selects this entity.
- */
-bool EntityContainer::setSelected(bool select)
-{
- // This entity's select:
- if (Entity::setSelected(select))
- {
- // All sub-entity's select:
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- if (e->isVisible())
- {
- e->setSelected(select);
- }
- }
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-/**
- * Toggles select on this entity.
- */
-bool EntityContainer::toggleSelected()
-{
- // Toggle this entity's select:
- if (Entity::toggleSelected())
- {
-
- // Toggle all sub-entity's select:
- /*for (Entity* e=firstEntity(RS2::ResolveNone);
- e!=NULL;
- e=nextEntity(RS2::ResolveNone)) {
- e->toggleSelected();
- }*/
- return true;
- }
- else
- {
- return false;
- }
-}
-
-/**
- * Selects all entities within the given area.
- *
- * @param select True to select, False to deselect the entities.
- */
-void EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross)
-{
- bool included;
-
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- included = false;
-
- if (e->isVisible())
- {
- if (e->isInWindow(v1, v2))
- {
- //e->setSelected(select);
- included = true;
- }
- else if (cross == true)
- {
- Line l[] =
- {
- Line(NULL, LineData(v1, Vector(v2.x, v1.y))),
- Line(NULL, LineData(Vector(v2.x, v1.y), v2)),
- Line(NULL, LineData(v2, Vector(v1.x, v2.y))),
- Line(NULL, LineData(Vector(v1.x, v2.y), v1))
- };
- VectorSolutions sol;
-
- if (e->isContainer())
- {
- EntityContainer * ec = (EntityContainer *)e;
-
- for(Entity * se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false;
- se=ec->nextEntity(RS2::ResolveAll))
- {
- for(int i=0; i<4; ++i)
- {
- sol = Information::getIntersection(se, &l[i], true);
-
- if (sol.hasValid())
- {
- included = true;
- break;
- }
- }
- }
- }
- else
- {
- for(int i=0; i<4; ++i)
- {
- sol = Information::getIntersection(e, &l[i], true);
-
- if (sol.hasValid())
- {
- included = true;
- break;
- }
- }
- }
- }
- }
-
- if (included)
- {
- e->setSelected(select);
- }
- }
-}
-
-/**
- * Adds a entity to this container and updates the borders of this
- * entity-container if autoUpdateBorders is true.
- */
-void EntityContainer::addEntity(Entity * entity)
-{
- /*
- if (isDocument()) {
- LayerList* lst = getDocument()->getLayerList();
- if (lst!=NULL) {
- Layer* l = lst->getActive();
- if (l!=NULL && l->isLocked()) {
- return;
- }
- }
- }
- */
-//printf("EntityContainer::addEntity(): entity=%08X\n", entity);
-
- if (!entity)
- return;
-
- if (entity->rtti() == RS2::EntityImage || entity->rtti() == RS2::EntityHatch)
- entities.prepend(entity);
- else
- entities.append(entity);
-
- if (autoUpdateBorders)
- adjustBorders(entity);
-//printf(" # of entities=%d\n", entities.size());
-}
-
-/**
- * Inserts a entity to this container at the given position and updates
- * the borders of this entity-container if autoUpdateBorders is true.
- */
-void EntityContainer::insertEntity(int index, Entity * entity)
-{
- if (entity == NULL)
- return;
-
- entities.insert(index, entity);
-
- if (autoUpdateBorders)
- adjustBorders(entity);
-}
-
-/**
- * Replaces the entity at the given index with the given entity
- * and updates the borders of this entity-container if autoUpdateBorders is true.
- */
-void EntityContainer::replaceEntity(int index, Entity * entity)
-{
- if (entity == NULL)
- return;
-
- entities.replace(index, entity);
-
- if (autoUpdateBorders)
- adjustBorders(entity);
-}
-
-/**
- * Removes an entity from this container and updates the borders of
- * this entity-container if autoUpdateBorders is true.
- */
-bool EntityContainer::removeEntity(Entity * entity)
-{
-// bool ret = entities.remove(entity);
- bool ret = (bool)entities.removeAll(entity);
-
- if (autoUpdateBorders)
- calculateBorders();
-
- return ret;
-}
-
-/**
- * Erases all entities in this container and resets the borders..
- */
-void EntityContainer::clear()
-{
- entities.clear();
- resetBorders();
-}
-
-/**
- * Counts all entities (branches of the tree).
- */
-unsigned long int EntityContainer::count()
-{
- return entities.count();
-}
-
-/**
- * Counts all entities (leaves of the tree).
- */
-unsigned long int EntityContainer::countDeep()
-{
- unsigned long int c = 0;
-
- for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
- {
- c += t->countDeep();
- }
-
- return c;
-}
-
-/**
- * Counts the selected entities in this container.
- */
-unsigned long int EntityContainer::countSelected()
-{
- unsigned long int c = 0;
-
- for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
- {
- if (t->isSelected())
- {
- c++;
- }
- }
-
- return c;
-}
-
-/**
- * Enables / disables automatic update of borders on entity removals
- * and additions. By default this is turned on.
- */
-/*virtual*/ void EntityContainer::setAutoUpdateBorders(bool enable)
-{
- autoUpdateBorders = enable;
-}
-
-/**
- * Adjusts the borders of this graphic (max/min values)
- */
-void EntityContainer::adjustBorders(Entity * entity)
-{
- //DEBUG->print("EntityContainer::adjustBorders");
- //resetBorders();
-
- if (entity == NULL)
- return;
-
- // make sure a container is not empty (otherwise the border
- // would get extended to 0/0):
- if (!entity->isContainer() || entity->count() > 0)
- {
- minV = Vector::minimum(entity->getMin(), minV);
- maxV = Vector::maximum(entity->getMax(), maxV);
- }
-
- // Notify parents. The border for the parent might
- // also change TODO: Check for efficiency
- //if(parent!=NULL) {
- //parent->adjustBorders(this);
- //}
-}
-
-/**
- * Recalculates the borders of this entity container.
- */
-void EntityContainer::calculateBorders()
-{
- DEBUG->print("EntityContainer::calculateBorders");
-
- resetBorders();
-
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- Layer * layer = e->getLayer();
-
- DEBUG->print("EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible());
-
- if (e->isVisible() && (layer == NULL || !layer->isFrozen()))
- {
- e->calculateBorders();
- adjustBorders(e);
- }
- }
-
- DEBUG->print("EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y);
-
- // needed for correcting corrupt data (PLANS.dxf)
- if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
- || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
- {
- minV.x = 0.0;
- maxV.x = 0.0;
- }
-
- if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
- || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
- {
- minV.y = 0.0;
- maxV.y = 0.0;
- }
-
- DEBUG->print("EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y);
-
- //DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
-
- //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
- //Entity::calculateBorders();
-}
-
-/**
- * Recalculates the borders of this entity container including
- * invisible entities.
- */
-void EntityContainer::forcedCalculateBorders()
-{
- //DEBUG->print("EntityContainer::calculateBorders");
-
- resetBorders();
-
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- //Layer* layer = e->getLayer();
-
- if (e->isContainer())
- {
- ((EntityContainer *)e)->forcedCalculateBorders();
- }
- else
- {
- e->calculateBorders();
- }
-
- adjustBorders(e);
- }
-
- // needed for correcting corrupt data (PLANS.dxf)
- if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
- || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
- {
- minV.x = 0.0;
- maxV.x = 0.0;
- }
-
- if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
- || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
- {
- minV.y = 0.0;
- maxV.y = 0.0;
- }
-
- //DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
-
- //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
- //Entity::calculateBorders();
-}
-
-/**
- * Updates all Dimension entities in this container and
- * reposition their labels.
- */
-void EntityContainer::updateDimensions()
-{
- DEBUG->print("EntityContainer::updateDimensions()");
-
- //for (Entity* e=firstEntity(RS2::ResolveNone);
- // e!=NULL;
- // e=nextEntity(RS2::ResolveNone)) {
-
-#if 0
-// Q3PtrListIterator<Entity> it = createIterator();
- QListIterator<Entity *> it = createIterator();
-// return QListIterator<Entity *>(entities);
-
- Entity * e;
-
- while ((e = it.current()) != NULL)
- {
- ++it;
-
- if (Information::isDimension(e->rtti()))
- {
- // update and reposition label:
- ((Dimension *)e)->update(true);
- }
- else if (e->isContainer())
- {
- ((EntityContainer *)e)->updateDimensions();
- }
- }
-#else
- for(int i=0; i<entities.size(); i++)
- {
- Entity * e = entities[i];
-
- if (Information::isDimension(e->rtti()))
- // update and reposition label:
- ((Dimension *)e)->update(true);
- else if (e->isContainer())
- ((EntityContainer *)e)->updateDimensions();
- }
-#endif
-
- DEBUG->print("EntityContainer::updateDimensions() OK");
-}
-
-/**
- * Updates all Insert entities in this container.
- */
-void EntityContainer::updateInserts()
-{
- DEBUG->print("EntityContainer::updateInserts()");
-
- //for (Entity* e=firstEntity(RS2::ResolveNone);
- // e!=NULL;
- // e=nextEntity(RS2::ResolveNone)) {
-#if 0
- Q3PtrListIterator<Entity> it = createIterator();
- Entity * e;
-
- while ((e = it.current()) != NULL)
- {
- ++it;
- //// Only update our own inserts and not inserts of inserts
- if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/)
- {
- ((Insert *)e)->update();
- }
- else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
- {
- ((EntityContainer *)e)->updateInserts();
- }
- }
-#else
- for(int i=0; i<entities.size(); i++)
- {
- Entity * e = entities[i];
-
- //// Only update our own inserts and not inserts of inserts
- if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/)
- ((Insert *)e)->update();
- else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
- ((EntityContainer *)e)->updateInserts();
- }
-#endif
-
- DEBUG->print("EntityContainer::updateInserts() OK");
-}
-
-/**
- * Renames all inserts with name 'oldName' to 'newName'. This is
- * called after a block was rename to update the inserts.
- */
-void EntityContainer::renameInserts(const QString& oldName, const QString& newName)
-{
- DEBUG->print("EntityContainer::renameInserts()");
-
- //for (Entity* e=firstEntity(RS2::ResolveNone);
- // e!=NULL;
- // e=nextEntity(RS2::ResolveNone)) {
-
-#if 0
- Q3PtrListIterator<Entity> it = createIterator();
- Entity* e;
- while ( (e = it.current()) != NULL ) {
- ++it;
-
- if (e->rtti()==RS2::EntityInsert) {
- Insert* i = ((Insert*)e);
- if (i->getName()==oldName) {
- i->setName(newName);
- }
- } else if (e->isContainer()) {
- ((EntityContainer*)e)->renameInserts(oldName, newName);
- }
- }
-#else
- for(int i=0; i<entities.size(); i++)
- {
- Entity * e = entities[i];
-
- if (e->rtti() == RS2::EntityInsert)
- {
- Insert * i = ((Insert *)e);
-
- if (i->getName() == oldName)
- i->setName(newName);
- }
- else if (e->isContainer())
- ((EntityContainer *)e)->renameInserts(oldName, newName);
- }
-#endif
-
- DEBUG->print("EntityContainer::renameInserts() OK");
-
-}
-
-/**
- * Updates all Spline entities in this container.
- */
-void EntityContainer::updateSplines()
-{
- DEBUG->print("EntityContainer::updateSplines()");
-
- //for (Entity* e=firstEntity(RS2::ResolveNone);
- // e!=NULL;
- // e=nextEntity(RS2::ResolveNone)) {
-#if 0
- Q3PtrListIterator<Entity> it = createIterator();
- Entity* e;
- while ( (e = it.current()) != NULL ) {
- ++it;
- //// Only update our own inserts and not inserts of inserts
- if (e->rtti()==RS2::EntitySpline /*&& e->getParent()==this*/) {
- ((Spline*)e)->update();
- } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
- ((EntityContainer*)e)->updateSplines();
- }
- }
-#else
- for(int i=0; i<entities.size(); i++)
- {
- Entity * e = entities[i];
-
- //// Only update our own inserts and not inserts of inserts
- if (e->rtti() == RS2::EntitySpline /*&& e->getParent()==this*/)
- ((Spline *)e)->update();
- else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
- ((EntityContainer *)e)->updateSplines();
- }
-#endif
-
- DEBUG->print("EntityContainer::updateSplines() OK");
-}
-
-/**
- * Updates the sub entities of this container.
- */
-void EntityContainer::update()
-{
- //for (Entity* e=firstEntity(RS2::ResolveNone);
- // e!=NULL;
- // e=nextEntity(RS2::ResolveNone)) {
-#if 0
- Q3PtrListIterator<Entity> it = createIterator();
- Entity* e;
- while ( (e = it.current()) != NULL ) {
- ++it;
- e->update();
- }
-#else
- for(int i=0; i<entities.size(); i++)
- {
-// Entity * e = entities[i];
-// e->update();
- entities[i]->update();
- }
-#endif
-}
-
-/**
- * Returns the first entity or NULL if this graphic is empty.
- * @param level
- */
-Entity * EntityContainer::firstEntity(RS2::ResolveLevel level)
-{
- switch (level)
- {
- case RS2::ResolveNone:
-// return entities.first();
-// entityIterator.toFront();
- entityIterator = entities;
- return (entityIterator.hasNext() ? entityIterator.next() : NULL);
- break;
-
- case RS2::ResolveAllButInserts:
- {
- subContainer = NULL;
-// Entity * e = entities.first();
-// entityIterator.toFront();
- entityIterator = entities;
- Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
-
- if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->firstEntity(level);
-
- // emtpy container:
- if (e == NULL)
- {
- subContainer = NULL;
- e = nextEntity(level);
- }
- }
-
- return e;
- }
- break;
-
- case RS2::ResolveAll:
- {
- subContainer = NULL;
-// Entity * e = entities.first();
-// entityIterator.toFront();
- entityIterator = entities;
- Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
-
- if (e != NULL && e->isContainer())
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->firstEntity(level);
-
- // emtpy container:
- if (e == NULL)
- {
- subContainer = NULL;
- e = nextEntity(level);
- }
- }
-
- return e;
- }
- break;
- }
-
- return NULL;
-}
-
-/**
- * Returns the last entity or \p NULL if this graphic is empty.
- *
- * @param level \li \p 0 Groups are not resolved
- * \li \p 1 (default) only Groups are resolved
- * \li \p 2 all Entity Containers are resolved
- */
-Entity * EntityContainer::lastEntity(RS2::ResolveLevel level)
-{
- switch (level)
- {
- case RS2::ResolveNone:
-// return entities.last();
- entityIterator = entities;
- entityIterator.toBack();
- return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- break;
-
- case RS2::ResolveAllButInserts:
- {
-// Entity * e = entities.last();
- entityIterator = entities;
- entityIterator.toBack();
- Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- subContainer = NULL;
-
- if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->lastEntity(level);
- }
-
- return e;
- }
- break;
-
- case RS2::ResolveAll:
- {
-// Entity * e = entities.last();
- entityIterator = entities;
- entityIterator.toBack();
- Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- subContainer = NULL;
-
- if (e != NULL && e->isContainer())
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->lastEntity(level);
- }
-
- return e;
- }
- break;
- }
-
- return NULL;
-}
-
-/**
- * Returns the next entity or container or \p NULL if the last entity
- * returned by \p next() was the last entity in the container.
- */
-Entity * EntityContainer::nextEntity(RS2::ResolveLevel level)
-{
- switch (level)
- {
- case RS2::ResolveNone:
-// return entities.next();
- return (entityIterator.hasNext() ? entityIterator.next() : NULL);
- break;
-
- case RS2::ResolveAllButInserts:
- {
- Entity * e = NULL;
-
- if (subContainer != NULL)
- {
- e = subContainer->nextEntity(level);
-
- if (e != NULL)
- {
- return e;
- }
- else
- {
-// e = entities.next();
- e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
- }
- }
- else
- {
-// e = entities.next();
- e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
- }
-
- if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->firstEntity(level);
-
- // emtpy container:
- if (e == NULL)
- {
- subContainer = NULL;
- e = nextEntity(level);
- }
- }
-
- return e;
- }
- break;
-
- case RS2::ResolveAll:
- {
- Entity * e = NULL;
-
- if (subContainer != NULL)
- {
- e = subContainer->nextEntity(level);
-
- if (e != NULL)
- return e;
- else
-// e = entities.next();
- e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
- }
- else
- {
-// e = entities.next();
- e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
- }
-
- if (e != NULL && e->isContainer())
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->firstEntity(level);
-
- // emtpy container:
- if (e == NULL)
- {
- subContainer = NULL;
- e = nextEntity(level);
- }
- }
-
- return e;
- }
- break;
- }
- return NULL;
-}
-
-/**
- * Returns the prev entity or container or \p NULL if the last entity
- * returned by \p prev() was the first entity in the container.
- */
-Entity * EntityContainer::prevEntity(RS2::ResolveLevel level)
-{
- Entity * e = NULL;
-
- switch (level)
- {
- case RS2::ResolveNone:
-// return entities.prev();
- return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- break;
-
- case RS2::ResolveAllButInserts:
- e = NULL;
-
- if (subContainer != NULL)
- {
- e = subContainer->prevEntity(level);
-
- if (e != NULL)
- return e;
- else
-// e = entities.prev();
- e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- }
- else
- {
-// e = entities.prev();
- e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- }
-
- if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->lastEntity(level);
-
- // emtpy container:
- if (e == NULL)
- {
- subContainer = NULL;
- e = prevEntity(level);
- }
- }
-
- return e;
-
- case RS2::ResolveAll:
- e = NULL;
-
- if (subContainer != NULL)
- {
- e = subContainer->prevEntity(level);
-
- if (e != NULL)
- return e;
- else
-// e = entities.prev();
- e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- }
- else
- {
-// e = entities.prev();
- e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
- }
-
- if (e != NULL && e->isContainer())
- {
- subContainer = (EntityContainer *)e;
- e = ((EntityContainer *)e)->lastEntity(level);
-
- // emtpy container:
- if (e == NULL)
- {
- subContainer = NULL;
- e = prevEntity(level);
- }
- }
-
- return e;
- }
-
- return NULL;
-}
-
-/**
- * @return Entity at the given index or NULL if the index is out of range.
- */
-Entity * EntityContainer::entityAt(uint index)
-{
- return entities.at(index);
-}
-
-/**
- * @return Current index.
- */
-int EntityContainer::entityAt()
-{
-#warning "!!! Not sure how to convert this from Qt3 -> Qt4 !!! (it seems we can ignore this for now as nothing calls it)"
-// return entities.at();
- return 0;
-}
-
-/**
- * Finds the given entity and makes it the current entity if found.
- */
-int EntityContainer::findEntity(Entity * entity)
-{
-// return entities.find(entity);
-
- entityIterator.toFront();
- entityIterator.findNext(entity);
-
- return entities.indexOf(entity);
-}
-
-/**
- * @return The current entity.
- */
-Entity * EntityContainer::currentEntity()
-{
-// return entities.current();
-
-// We really need to refactor this crap, this is the way it is now to support
-// the old broken way of doing things
- return entityIterator.peekNext();
-}
-
-#if 0
-#warning "!!! Not needed anymore !!!"
-/**
- * Returns the copy to a new iterator for traversing the entities.
- */
-//Q3PtrListIterator<Entity> EntityContainer::createIterator()
-QListIterator<Entity *> EntityContainer::createIterator()
-{
-// return Q3PtrListIterator<Entity>(entities);
- return QListIterator<Entity *>(entities);
-}
-#endif
-
-/*virtual*/ bool EntityContainer::isEmpty()
-{
- return (count() == 0);
-}
-
-/**
- * @return The point which is closest to 'coord'
- * (one of the vertexes)
- */
-Vector EntityContainer::getNearestEndpoint(const Vector & coord, double * dist)
-{
- double minDist = RS_MAXDOUBLE; // minimum measured distance
- double curDist; // currently measured distance
- Vector closestPoint(false); // closest found endpoint
- Vector point; // endpoint found
-
- //Q3PtrListIterator<Entity> it = createIterator();
- //Entity* en;
- //while ( (en = it.current()) != NULL ) {
- // ++it;
- for (Entity* en = firstEntity();
- en != NULL;
- en = nextEntity()) {
-
- if (en->isVisible()) {
- point = en->getNearestEndpoint(coord, &curDist);
- if (point.valid && curDist<minDist) {
- closestPoint = point;
- minDist = curDist;
- if (dist!=NULL) {
- *dist = curDist;
- }
- }
- }
- }
-
- return closestPoint;
-}
-
-Vector EntityContainer::getNearestPointOnEntity(const Vector & coord,
- bool onEntity, double * dist, Entity ** entity)
-{
- Vector point(false);
-
- Entity * e = getNearestEntity(coord, dist, RS2::ResolveNone);
-
- if (e && e->isVisible())
- point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
-
- return point;
-}
-
-Vector EntityContainer::getNearestCenter(const Vector & coord, double * dist)
-{
- Vector point(false);
- Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
-
- if (closestEntity)
- point = closestEntity->getNearestCenter(coord, dist);
-
- return point;
-}
-
-Vector EntityContainer::getNearestMiddle(const Vector & coord, double * dist)
-{
- Vector point(false);
- Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
-
- if (closestEntity)
- point = closestEntity->getNearestMiddle(coord, dist);
-
- return point;
-}
-
-Vector EntityContainer::getNearestDist(double distance, const Vector & coord,
- double * dist)
-{
- Vector point(false);
- Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
-
- if (closestEntity)
- point = closestEntity->getNearestDist(distance, coord, dist);
-
- return point;
-}
-
-/**
- * @return The intersection which is closest to 'coord'
- */
-Vector EntityContainer::getNearestIntersection(const Vector & coord,
- double * dist)
-{
- double minDist = RS_MAXDOUBLE; // minimum measured distance
- double curDist; // currently measured distance
- Vector closestPoint(false); // closest found endpoint
- Vector point; // endpoint found
- VectorSolutions sol;
- Entity * closestEntity;
-
- closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
-
- if (closestEntity)
- {
- for(Entity * en=firstEntity(RS2::ResolveAll); en!=NULL;
- en = nextEntity(RS2::ResolveAll))
- {
- if (en->isVisible() && en!=closestEntity)
- {
- sol = Information::getIntersection(closestEntity, en, true);
-
- for(int i=0; i<4; i++)
- {
- point = sol.get(i);
-
- if (point.valid)
- {
- curDist = coord.distanceTo(point);
-
- if (curDist < minDist)
- {
- closestPoint = point;
- minDist = curDist;
-
- if (dist)
- *dist = curDist;
- }
- }
- }
- }
- }
- }
-
- return closestPoint;
-}
-
-Vector EntityContainer::getNearestRef(const Vector & coord, double * dist)
-{
- double minDist = RS_MAXDOUBLE; // minimum measured distance
- double curDist; // currently measured distance
- Vector closestPoint(false); // closest found endpoint
- Vector point; // endpoint found
-
- for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
- {
- if (en->isVisible())
- {
- point = en->getNearestRef(coord, &curDist);
-
- if (point.valid && curDist < minDist)
- {
- closestPoint = point;
- minDist = curDist;
-
- if (dist)
- *dist = curDist;
- }
- }
- }
-
- return closestPoint;
-}
-
-Vector EntityContainer::getNearestSelectedRef(const Vector & coord,
- double * dist)
-{
- double minDist = RS_MAXDOUBLE; // minimum measured distance
- double curDist; // currently measured distance
- Vector closestPoint(false); // closest found endpoint
- Vector point; // endpoint found
-
- for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
- {
- if (en->isVisible() && en->isSelected() && !en->isParentSelected())
- {
- point = en->getNearestSelectedRef(coord, &curDist);
-
- if (point.valid && curDist < minDist)
- {
- closestPoint = point;
- minDist = curDist;
-
- if (dist)
- *dist = curDist;
- }
- }
- }
-
- return closestPoint;
-}
-
-double EntityContainer::getDistanceToPoint(const Vector & coord,
- Entity ** entity, RS2::ResolveLevel level, double solidDist)
-{
- DEBUG->print("EntityContainer::getDistanceToPoint");
-
- double minDist = RS_MAXDOUBLE; // minimum measured distance
- double curDist; // currently measured distance
- Entity * closestEntity = NULL; // closest entity found
- Entity * subEntity = NULL;
-
- //int k=0;
- for(Entity * e=firstEntity(level); e!=NULL; e=nextEntity(level))
- {
- if (e->isVisible())
- {
- DEBUG->print("entity: getDistanceToPoint");
- DEBUG->print("entity: %d", e->rtti());
- curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
- DEBUG->print("entity: getDistanceToPoint: OK");
-
- if (curDist<minDist)
- {
- if (level != RS2::ResolveAll)
- closestEntity = e;
- else
- closestEntity = subEntity;
-
- minDist = curDist;
- }
- }
- }
-
- if (entity)
- *entity = closestEntity;
-
- DEBUG->print("EntityContainer::getDistanceToPoint: OK");
- return minDist;
-}
-
-Entity * EntityContainer::getNearestEntity(const Vector & coord,
- double * dist, RS2::ResolveLevel level)
-{
- DEBUG->print("EntityContainer::getNearestEntity");
- Entity * e = NULL;
-
- // distance for points inside solids:
- double solidDist = RS_MAXDOUBLE;
-
- if (dist)
- solidDist = *dist;
-
- double d = getDistanceToPoint(coord, &e, level, solidDist);
-
- if (e && e->isVisible() == false)
- e = NULL;
-
- // if d is negative, use the default distance (used for points inside solids)
- if (dist)
- *dist = d;
-
- DEBUG->print("EntityContainer::getNearestEntity: OK");
- return e;
-}
-
-/**
- * Rearranges the atomic entities in this container in a way that connected
- * entities are stored in the right order and direction.
- * Non-recoursive. Only affects atomic entities in this container.
- *
- * @retval true all contours were closed
- * @retval false at least one contour is not closed
- */
-bool EntityContainer::optimizeContours()
-{
- DEBUG->print("EntityContainer::optimizeContours");
-
- Vector current(false);
- Vector start(false);
- EntityContainer tmp;
-
- bool changed = false;
- bool closed = true;
-
- for(uint ci=0; ci<count(); ++ci)
- {
- Entity * e1=entityAt(ci);
-
- if (e1 && e1->isEdge() && !e1->isContainer() && !e1->isProcessed())
- {
- AtomicEntity * ce = (AtomicEntity *)e1;
-
- // next contour start:
- ce->setProcessed(true);
- tmp.addEntity(ce->clone());
- current = ce->getEndpoint();
- start = ce->getStartpoint();
-
- // find all connected entities:
- bool done;
-
- do
- {
- done = true;
- for(uint ei=0; ei<count(); ++ei)
- {
- Entity * e2=entityAt(ei);
-
- if (e2 != NULL && e2->isEdge() && !e2->isContainer() &&
- !e2->isProcessed())
- {
- AtomicEntity * e = (AtomicEntity *)e2;
-
- if (e->getStartpoint().distanceTo(current) < 1.0e-4)
- {
- e->setProcessed(true);
- tmp.addEntity(e->clone());
- current = e->getEndpoint();
- done = false;
- }
- else if (e->getEndpoint().distanceTo(current) < 1.0e-4)
- {
- e->setProcessed(true);
- AtomicEntity * cl = (AtomicEntity *)e->clone();
- cl->reverse();
- tmp.addEntity(cl);
- current = cl->getEndpoint();
- changed = true;
- done = false;
- }
- }
- }
-
- if (!done)
- changed = true;
- }
- while (!done);
-
- if (current.distanceTo(start) > 1.0e-4)
- closed = false;
- }
- }
-
- // remove all atomic entities:
- bool done;
-
- do
- {
- done = true;
-
- for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
- {
- if (!en->isContainer())
- {
- removeEntity(en);
- done = false;
- break;
- }
- }
- }
- while (!done);
-
- // add new sorted entities:
- for(Entity * en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity())
- {
- en->setProcessed(false);
- addEntity(en->clone());
- }
-
- DEBUG->print("EntityContainer::optimizeContours: OK");
- return closed;
-}
-
-bool EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2)
-{
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- {
- if (e->hasEndpointsWithinWindow(v1, v2))
- return true;
- }
-
- return false;
-}
-
-void EntityContainer::move(Vector offset)
-{
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->move(offset);
-
- if (autoUpdateBorders)
- calculateBorders();
-}
-
-void EntityContainer::rotate(Vector center, double angle)
-{
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->rotate(center, angle);
-
- if (autoUpdateBorders)
- calculateBorders();
-}
-
-void EntityContainer::scale(Vector center, Vector factor)
-{
- if (fabs(factor.x) > RS_TOLERANCE && fabs(factor.y) > RS_TOLERANCE)
- {
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->scale(center, factor);
- }
-
- if (autoUpdateBorders)
- calculateBorders();
-}
-
-void EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2)
-{
- if (axisPoint1.distanceTo(axisPoint2) > 1.0e-6)
- {
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->mirror(axisPoint1, axisPoint2);
- }
-}
-
-void EntityContainer::stretch(Vector firstCorner, Vector secondCorner,
- Vector offset)
-{
- if (getMin().isInWindow(firstCorner, secondCorner) &&
- getMax().isInWindow(firstCorner, secondCorner))
- {
- move(offset);
- }
- else
- {
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->stretch(firstCorner, secondCorner, offset);
- }
-
- // some entitiycontainers might need an update (e.g. Leader):
- update();
-}
-
-void EntityContainer::moveRef(const Vector & ref, const Vector & offset)
-{
- for(Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->moveRef(ref, offset);
-
- if (autoUpdateBorders)
- calculateBorders();
-}
-
-void EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
-{
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
- e->moveSelectedRef(ref, offset);
-
- if (autoUpdateBorders)
- calculateBorders();
-}
-
-void EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
-{
- if (!painter || !view)
- return;
-
- for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
-#if 0
-{
-if (e->rtti() == RS2::EntityText)
-{
- std::cout << "About to draw TEXT entity... "
- << "TEXT=\"" << ((Text *)e)->getText().toAscii().data() << "\"" << std::endl;
-}
-//OK, we have text, but no insert entities at least none that are drawn...
-//Ah! But with a standard text entity, it DOES have them!
-else if (e->rtti() == RS2::EntityInsert)
-{
- std::cout << "About to draw INSERT entity... "
- << "INSERT=\"" << ((Insert *)e)->getData().name.toAscii().data() << "\"" << std::endl;
-}
-#endif
- view->drawEntity(e);
-#if 0
-}
-#endif
-}
-
-/**
- * Dumps the entities to stdout.
- */
-std::ostream & operator<<(std::ostream & os, EntityContainer & ec)
-{
- static int indent = 0;
- char * tab = new char[indent * 2 + 1];
-
- for(int i=0; i<indent*2; i++)
- tab[i] = ' ';
-
- tab[indent * 2] = '\0';
- indent++;
- unsigned long int id = ec.getId();
-
- os << tab << "EntityContainer[" << id << "]: \n";
- os << tab << "Borders[" << id << "]: "
- << ec.minV << " - " << ec.maxV << "\n";
- //os << tab << "Unit[" << id << "]: "
- //<< Units::unit2string (ec.unit) << "\n";
- if (ec.getLayer())
- {
- os << tab << "Layer[" << id << "]: "
- << ec.getLayer()->getName().toLatin1().data() << "\n";
- }
- else
- {
- os << tab << "Layer[" << id << "]: <NULL>\n";
- }
- //os << ec.layerList << "\n";
-
- os << tab << " Flags[" << id << "]: "
- << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
- os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
- os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
- os << "\n";
-
- os << tab << "Entities[" << id << "]: \n";
-
-QString s;
-os << "(# of entities in this = " << ec.entities.size() << ")\n";
-for(int i=0; i<ec.entities.size(); i++)
-{
- Entity * t = ec.entities[i];
- s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
- os << s.toAscii().data();
-}
-s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
-os << s.toAscii().data();
-
- for(Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
- {
- switch (t->rtti())
- {
- case RS2::EntityInsert:
- os << tab << *((Insert *)t);
- os << tab << *((Entity *)t);
- os << tab << *((EntityContainer *)t);
- break;
- default:
- if (t->isContainer())
- os << tab << *((EntityContainer *)t);
- else
- os << tab << *t;
-
- break;
- }
- }
-
- os << tab << "\n\n";
- indent--;
-
- delete[] tab;
- return os;
-}