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 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/28/2010 Added this text. :-)
26 #include "graphicview.h"
36 * Default constructor.
37 * @param parent The parent entity of this entity.
38 * E.g. a line might have a graphic entity or
39 * a polyline entity as parent.
41 Entity::Entity(EntityContainer * parent)
43 this->parent = parent;
50 /*Entity::Entity(const Entity& e) : Flags(e.getFlags()) {
51 cout << "copy constructor called\n";
55 //setFlag(e.getFlags());
68 /*virtual*/ void Entity::reparent(EntityContainer * parent)
70 this->parent = parent;
74 * Initialisation. Called from all constructors.
80 setFlag(RS2::FlagVisible);
90 * Gives this entity a new unique id.
94 static unsigned long int idCounter = 0;
99 * Resets the borders of this element.
101 void Entity::resetBorders()
103 // TODO: Check that. windoze XP crashes with MAXDOUBLE
104 double maxd = RS_MAXDOUBLE;
105 double mind = RS_MINDOUBLE;
107 minV.set(maxd, maxd, maxd);
108 maxV.set(mind, mind, mind);
112 * Must be overwritten to return the rtti of this entity
113 * (e.g. RS2::EntityArc).
115 /*virtual*/ RS2::EntityType Entity::rtti() const
117 return RS2::EntityUnknown;
121 * Identify all entities as undoable entities.
122 * @return RS2::UndoableEntity
124 /*virtual*/ RS2::UndoableType Entity::undoRtti()
126 return RS2::UndoableEntity;
130 * @return Unique Id of this entity.
132 unsigned long int Entity::getId() const
138 * Must be overwritten to return true if an entity type
139 * is a potential edge entity of a contour. By default
140 * this returns false.
142 /*virtual*/ bool Entity::isEdge() const
148 * @return true for all document entities (e.g. Graphics or Blocks).
151 /*virtual*/ bool Entity::isDocument() const
157 * Selects or deselects this entity.
159 * @param select True to select, false to deselect.
161 bool Entity::setSelected(bool select)
164 if (select && isLocked())
168 setFlag(RS2::FlagSelected);
170 delFlag(RS2::FlagSelected);
176 * Toggles select on this entity.
178 bool Entity::toggleSelected()
180 return setSelected(!isSelected());
181 //toggleFlag(RS2::FlagSelected);
185 * @return True if the entity is selected. Note that an entity might
186 * not be selected but one of its parents is selected. In that case
187 * this function returns false.
189 bool Entity::isSelected() const
191 return getFlag(RS2::FlagSelected);
195 * @return true if a parent entity of this entity is selected.
197 bool Entity::isParentSelected()
205 if (p && p->isSelected() == true)
214 * Sets or resets the processed flag of this entity.
216 * @param on True to set, false to reset.
218 void Entity::setProcessed(bool on)
221 setFlag(RS2::FlagProcessed);
223 delFlag(RS2::FlagProcessed);
227 * @return True if the processed flag is set.
229 bool Entity::isProcessed() const
231 return getFlag(RS2::FlagProcessed);
235 * Called when the undo state changed.
237 * @param undone true: entity has become invisible.
238 * false: entity has become visible.
240 void Entity::undoStateChanged(bool /*undone*/)
247 * @return true if this entity or any parent entities are undone.
249 bool Entity::isUndone() const
252 return Undoable::isUndone();
254 return Undoable::isUndone() || parent->isUndone();
258 * @return True if the entity is in the given range.
260 bool Entity::isInWindow(Vector v1, Vector v2)
262 double right, left, top, bottom;
264 right = std::max(v1.x, v2.x);
265 left = std::min(v1.x, v2.x);
266 top = std::max(v1.y, v2.y);
267 bottom = std::min(v1.y, v2.y);
269 return (getMin().x >= left && getMax().x <= right
270 && getMin().y >= bottom && getMax().y <= top);
274 * @param tolerance Tolerance.
276 * @retval true if the given point is on this entity.
277 * @retval false otherwise
279 bool Entity::isPointOnEntity(const Vector & coord, double tolerance)
281 double dist = getDistanceToPoint(coord, NULL, RS2::ResolveNone);
282 return (dist <= tolerance);
285 /*virtual*/ bool Entity::hasEndpointsWithinWindow(Vector /*v1*/, Vector /*v2*/)
291 * Is this entity visible?
293 * @return true Only if the entity and the layer it is on are visible.
294 * The Layer might also be NULL. In that case the layer visiblity
297 /*virtual*/ bool Entity::isVisible()
299 if (!getFlag(RS2::FlagVisible))
305 /*EntityCotnainer* parent = getParent();
306 if (parent!=NULL && parent->isUndone()) {
310 if (getLayer() == NULL)
313 // inserts are usually visible - the entities in them have their own
314 // layers which might be frozen
315 // upd: i'm not sure if that is the best behaviour
316 //if (rtti()==RS2::EntityInsert) {
320 if (layer != NULL /*&& layer->getName()!="ByBlock"*/)
322 if (!layer->isFrozen())
328 if (layer == NULL /*&& getLayer()->getName()!="ByBlock"*/)
330 if (getLayer() == NULL)
334 if (!getLayer()->isFrozen())
341 if (getBlockOrInsert() == NULL)
344 if (getBlockOrInsert()->rtti() == RS2::EntityBlock)
346 if (getLayer(false) == NULL || !getLayer(false)->isFrozen())
353 if (getBlockOrInsert()->getLayer() == NULL)
356 if (!getBlockOrInsert()->getLayer()->isFrozen())
362 /*virtual*/ void Entity::setVisible(bool v)
365 setFlag(RS2::FlagVisible);
367 delFlag(RS2::FlagVisible);
371 * Sets the highlight status of the entity. Highlighted entities
372 * usually indicate a feedback to a user action.
374 void Entity::setHighlighted(bool on)
377 setFlag(RS2::FlagHighlighted);
379 delFlag(RS2::FlagHighlighted);
383 * @return true if the entity is highlighted.
385 bool Entity::isHighlighted()
387 return getFlag(RS2::FlagHighlighted);
391 * @return true if the layer this entity is on is locked.
393 bool Entity::isLocked()
395 if (getLayer(true) != NULL && getLayer()->isLocked())
402 * Implementations must return the total length of the entity
403 * or a negative number if the entity has no length (e.g. a text or hatch).
405 /*virtual*/ double Entity::getLength()
411 * @return Parent of this entity or NULL if this is a root entity.
413 EntityContainer * Entity::getParent() const
419 * Reparents this entity.
421 void Entity::setParent(EntityContainer * p)
427 * @return The parent graphic in which this entity is stored
428 * or the parent's parent graphic or NULL if none of the parents
429 * are stored in a graphic.
431 Drawing * Entity::getGraphic()
433 if (rtti() == RS2::EntityGraphic)
434 return (Drawing *)this;
435 else if (parent == NULL)
438 return parent->getGraphic();
442 * @return The parent block in which this entity is stored
443 * or the parent's parent block or NULL if none of the parents
444 * are stored in a block.
446 Block * Entity::getBlock()
448 if (rtti() == RS2::EntityBlock)
449 return (Block *)this;
450 else if (parent == NULL)
453 return parent->getBlock();
457 * @return The parent insert in which this entity is stored
458 * or the parent's parent block or NULL if none of the parents
459 * are stored in a block.
461 Insert * Entity::getInsert()
463 if (rtti() == RS2::EntityInsert)
464 return (Insert *)this;
465 else if (parent == NULL)
468 return parent->getInsert();
472 * @return The parent block or insert in which this entity is stored
473 * or the parent's parent block or insert or NULL if none of the parents
474 * are stored in a block or insert.
476 Entity * Entity::getBlockOrInsert()
478 if (rtti() == RS2::EntityBlock || rtti() == RS2::EntityInsert)
480 else if (parent == NULL)
483 return parent->getBlockOrInsert();
487 * @return The parent document in which this entity is stored
488 * or the parent's parent document or NULL if none of the parents
489 * are stored in a document. Note that a document is usually
490 * either a Graphic or a Block.
492 Document * Entity::getDocument()
494 if (isDocument() == true)
495 return (Document *)this;
496 else if (parent == NULL)
499 return parent->getDocument();
503 * Can be implemented by child classes to update the entities
504 * temporary subentities. update() is called if the entity's
505 * paramters or undo state changed.
507 /*virtual*/ void Entity::update()
511 /*virtual*/ void Entity::setUpdateEnabled(bool on)
517 * This method doesn't do any calculations.
518 * @return minimum coordinate of the entity.
519 * @see calculateBorders()
521 Vector Entity::getMin() const
527 * This method doesn't do any calculations.
528 * @return minimum coordinate of the entity.
529 * @see calculateBorders()
531 Vector Entity::getMax() const
537 * This method returns the difference of max and min returned
538 * by the above functions.
539 * @return size of the entity.
540 * @see calculateBorders()
544 Vector Entity::getSize() const
550 * Sets a variable value for the parent graphic object.
552 * @param key Variable name (e.g. "$DIMASZ")
553 * @param val Default value
555 void Entity::addGraphicVariable(const QString & key, double val, int code)
557 Drawing * graphic = getGraphic();
560 graphic->addVariable(key, val, code);
564 * Sets a variable value for the parent graphic object.
566 * @param key Variable name (e.g. "$DIMASZ")
567 * @param val Default value
569 void Entity::addGraphicVariable(const QString & key, int val, int code)
571 Drawing * graphic = getGraphic();
574 graphic->addVariable(key, val, code);
578 * Sets a variable value for the parent graphic object.
580 * @param key Variable name (e.g. "$DIMASZ")
581 * @param val Default value
583 void Entity::addGraphicVariable(const QString & key, const QString & val, int code)
585 Drawing * graphic = getGraphic();
588 graphic->addVariable(key, val, code);
592 * A safe member function to return the given variable.
594 * @param key Variable name (e.g. "$DIMASZ")
595 * @param def Default value
597 * @return value of variable or default value if the given variable
600 double Entity::getGraphicVariableDouble(const QString & key, double def)
602 Drawing * graphic = getGraphic();
606 ret = graphic->getVariableDouble(key, def);
612 * A safe member function to return the given variable.
614 * @param key Variable name (e.g. "$DIMASZ")
615 * @param def Default value
617 * @return value of variable or default value if the given variable
620 int Entity::getGraphicVariableInt(const QString & key, int def)
622 Drawing * graphic = getGraphic();
626 ret = graphic->getVariableInt(key, def);
632 * A safe member function to return the given variable.
634 * @param key Variable name (e.g. "$DIMASZ")
635 * @param def Default value
637 * @return value of variable or default value if the given variable
640 QString Entity::getGraphicVariableString(const QString & key, const QString & def)
642 Drawing * graphic = getGraphic();
646 ret = graphic->getVariableString(key, def);
652 * @return The unit the parent graphic works on or None if there's no
655 RS2::Unit Entity::getGraphicUnit()
657 Drawing * graphic = getGraphic();
658 RS2::Unit ret = RS2::None;
661 ret = graphic->getUnit();
667 * Must be overwritten to get all reference points of the entity.
669 /*virtual*/ VectorSolutions Entity::getRefPoints()
676 * Must be overwritten to get the point with a given
677 * distance to the start- or endpoint to the given coordinate for this entity.
679 * @param distance Distance to endpoint.
680 * @param startp true = measured from Startpoint, false = measured from Endpoint
682 * @return The point with the given distance to the start- or endpoint.
684 /*virtual*/ Vector Entity::getNearestDist(double /*distance*/, bool /*startp*/)
686 return Vector(false);
690 * Must be overwritten to get the nearest reference point for this entity.
692 * @param coord Coordinate (typically a mouse coordinate)
693 * @param dist Pointer to a value which will contain the measured
694 * distance between 'coord' and the closest point. The passed
695 * pointer can also be NULL in which case the distance will be
698 * @return The closest point with the given distance to the endpoint.
700 /*virtual*/ Vector Entity::getNearestRef(const Vector & coord, double * dist/*= NULL*/)
702 VectorSolutions s = getRefPoints();
704 return s.getClosest(coord, dist);
708 * Gets the nearest reference point of this entity if it is selected.
709 * Containers re-implement this method to return the nearest reference
710 * point of a selected sub entity.
712 * @param coord Coordinate (typically a mouse coordinate)
713 * @param dist Pointer to a value which will contain the measured
714 * distance between 'coord' and the closest point. The passed
715 * pointer can also be NULL in which case the distance will be
718 * @return The closest point with the given distance to the endpoint.
720 /*virtual*/ Vector Entity::getNearestSelectedRef(const Vector & coord, double * dist/*= NULL*/)
723 return getNearestRef(coord, dist);
725 return Vector(false);
729 * Acts like scale(Vector) but with equal factors.
730 * Equal to scale(center, Vector(factor, factor)).
732 /*virtual*/ void Entity::scale(Vector center, double factor)
734 scale(center, Vector(factor, factor));
738 * Implementations must drag the reference point(s) of all
739 * (sub-)entities that are very close to ref by offset.
741 /*virtual*/ void Entity::moveRef(const Vector &/*ref*/, const Vector &/*offset*/)
747 * Implementations must drag the reference point(s) of selected
748 * (sub-)entities that are very close to ref by offset.
750 /*virtual*/ void Entity::moveSelectedRef(const Vector &/*ref*/, const Vector &/*offset*/)
756 * Returns a pointer to the layer this entity is on or NULL.
758 * @para resolve true: if the layer is ByBlock, the layer of the
759 * block this entity is in is returned.
760 * false: the layer of the entity is returned.
762 * @return pointer to the layer this entity is on. If the layer
763 * is set to NULL the layer of the next parent that is not on
764 * layer NULL is returned. If all parents are on layer NULL, NULL
767 Layer * Entity::getLayer(bool resolve) const
771 // we have no layer but a parent that might have one.
772 // return parent's layer instead:
773 if (layer == NULL /*|| layer->getName()=="ByBlock"*/)
776 return parent->getLayer(true);
782 // return our layer. might still be NULL:
787 * Sets the layer of this entity to the layer with the given name
789 void Entity::setLayer(const QString & name)
791 Drawing * graphic = getGraphic();
794 layer = graphic->findLayer(name);
800 * Sets the layer of this entity to the layer given.
802 void Entity::setLayer(Layer * l)
808 * Sets the layer of this entity to the current layer of
809 * the graphic this entity is in. If this entity (and none
810 * of its parents) are in a graphic the layer is set to NULL.
812 void Entity::setLayerToActive()
814 Drawing * graphic = getGraphic();
817 layer = graphic->getActiveLayer();
823 * Gets the pen needed to draw this entity.
824 * The attributes can also come from the layer this entity is on
825 * if the flags are set accordingly.
827 * @param resolve true: Resolve the pen to a drawable pen (e.g. the pen
828 * from the layer or parent..)
829 * false: Don't resolve and return a pen or ByLayer, ByBlock, ...
831 * @return Pen for this entity.
833 Pen Entity::getPen(bool resolve) const
840 Layer * l = getLayer(true);
842 // use parental attributes (e.g. vertex of a polyline, block
843 // entities when they are drawn in block documents):
844 if (!p.isValid() || p.getColor().isByBlock())
847 p = parent->getPen();
849 // use layer attributes:
852 // layer is "ByBlock":
853 /*if (layer->getName()=="ByBlock" && getBlockOrInsert()!=NULL) {
854 p = getBlockOrInsert()->getPen();
857 // use layer's color:
858 if (p.getColor().isByLayer())
859 p.setColor(l->getPen().getColor());
861 // use layer's width:
862 if (p.getWidth() == RS2::WidthByLayer)
863 p.setWidth(l->getPen().getWidth());
865 // use layer's linetype:
866 if (p.getLineType() == RS2::LineByLayer)
867 p.setLineType(l->getPen().getLineType());
876 * Sets the explicit pen for this entity or a pen with special
877 * attributes such as BY_LAYER, ..
879 void Entity::setPen(const Pen & pen)
885 * Sets the pen of this entity to the current pen of
886 * the graphic this entity is in. If this entity (and none
887 * of its parents) are in a graphic the pen is not changed.
889 void Entity::setPenToActive()
891 Document * doc = getDocument();
894 pen = doc->getActivePen();
897 //DEBUG->print(Debug::D_WARNING, "Entity::setPenToActive(): "
898 // "No document / active pen linked to this entity.");
906 * Implementations must stretch the given range of the entity
907 * by the given offset. This default implementation moves the
908 * whole entity if it is completely inside the given range.
910 void Entity::stretch(Vector firstCorner, Vector secondCorner, Vector offset)
912 //e->calculateBorders();
913 if (getMin().isInWindow(firstCorner, secondCorner)
914 && getMax().isInWindow(firstCorner, secondCorner))
919 * @return Factor for scaling the line styles considering the current
920 * paper scaling and the fact that styles are stored in Millimeter.
922 double Entity::getStyleFactor(GraphicView * view)
924 double styleFactor = 1.0;
928 if (view->isPrinting() == false && view->isDraftMode())
929 styleFactor = 1.0 / view->getFactor().x;
932 //styleFactor = getStyleFactor();
933 // the factor caused by the unit:
934 RS2::Unit unit = RS2::None;
935 Drawing * g = getGraphic();
940 //double scale = g->getPaperScale();
941 styleFactor = Units::convert(1.0, RS2::Millimeter, unit);
945 // the factor caused by the line width:
946 if (((int)getPen(true).getWidth()) > 0)
947 styleFactor *= ((double)getPen(true).getWidth() / 100.0);
948 else if (((int)getPen(true).getWidth()) == 0)
952 if (view->isPrinting() || view->isPrintPreview() || view->isDraftMode() == false)
954 Drawing * graphic = getGraphic();
956 if (graphic != NULL && graphic->getPaperScale() > 1.0e-6)
957 styleFactor /= graphic->getPaperScale();
961 //DEBUG->print("stylefactor: %f", styleFactor);
962 //DEBUG->print("viewfactor: %f", view->getFactor().x);
964 if (styleFactor * view->getFactor().x < 0.2)
971 * @return User defined variable connected to this entity.
973 QString * Entity::getUserDefVar(QString key)
975 // return (this->varList.find(key));
976 return (this->varList.value(key));
980 * Add a user defined variable to this entity.
982 void Entity::setUserDefVar(QString key, QString val)
984 varList.insert(key, new QString(val));
988 * Deletes the given user defined variable.
990 void Entity::delUserDefVar(QString key)
996 * @return A list of all keys connected to this entity.
998 QStringList Entity::getAllKeys()
1001 // Q3DictIterator<QString> it(varList);
1002 QHashIterator<QString, QString *> it(varList);
1004 // for(; it.current(); ++it)
1005 // keys.append(it.currentKey());
1006 while (it.hasNext())
1009 keys.append(it.key());
1016 * Dumps the elements data to stdout.
1018 std::ostream & operator<<(std::ostream & os, Entity & e)
1020 //os << "Warning: Virtual entity!\n";
1023 os << " {Entity id: " << e.id;
1025 if (e.parent != NULL)
1026 os << " | parent id: " << e.parent->getId() << "\n";
1028 os << " | no parent\n";
1030 os << " flags: " << (e.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1031 os << (e.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1032 os << (e.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1035 if (e.layer == NULL)
1036 os << " layer: NULL ";
1038 os << " layer: " << e.layer->getName().toLatin1().data() << " "
1039 << " layer address: " << (int)(e.layer) << " ";
1041 os << e.pen << "\n";
1043 os << "variable list:\n";
1044 // Q3DictIterator<QString> it(e.varList); // See QDictIterator
1045 QHashIterator<QString, QString *> it(e.varList);
1048 for( ; it.current(); ++it )
1050 #warning "Removed output (Qt3 style iterator)... !!! FIX !!!"
1051 // os << it.currentKey() << ": " << *it.current() << ", ";
1054 while (it.hasNext())
1057 os << (it.key()).toAscii().data() << ": " << (*it.value()).toAscii().data() << ", ";
1061 // There should be a better way than this...
1064 case RS2::EntityPoint:
1068 case RS2::EntityLine:
1072 case RS2::EntityPolyline:
1073 os << (Polyline &)e;
1076 case RS2::EntityArc:
1080 case RS2::EntityCircle:
1084 case RS2::EntityEllipse:
1088 case RS2::EntityInsert:
1092 case RS2::EntityText:
1097 os << "Unknown Entity";