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/21/2010 Added this text. :-)
15 // JLH 06/02/2010 Changed all references of this class from RS_Graphic to
16 // Drawing, as that makes it more clear that this is what it
17 // is (a CAD drawing, not a bitmap).
24 #include "mathextra.h"
29 * Default constructor.
31 Drawing::Drawing(EntityContainer * parent): Document(parent), layerList(),
37 settings.beginGroup("Defaults");
38 setUnit(Units::stringToUnit(settings.value("Unit", "None").toString()));
41 RS2::Unit unit = getUnit();
43 if (unit == RS2::Inch)
45 addVariable("$DIMASZ", 0.1, 40);
46 addVariable("$DIMEXE", 0.05, 40);
47 addVariable("$DIMEXO", 0.025, 40);
48 addVariable("$DIMGAP", 0.025, 40);
49 addVariable("$DIMTXT", 0.1, 40);
53 addVariable("$DIMASZ", Units::convert(2.5, RS2::Millimeter, unit), 40);
54 addVariable("$DIMEXE", Units::convert(1.25, RS2::Millimeter, unit), 40);
55 addVariable("$DIMEXO", Units::convert(0.625, RS2::Millimeter, unit), 40);
56 addVariable("$DIMGAP", Units::convert(0.625, RS2::Millimeter, unit), 40);
57 addVariable("$DIMTXT", Units::convert(2.5, RS2::Millimeter, unit), 40);
70 /** @return RS2::EntityDrawing */
71 /*virtual*/ RS2::EntityType Drawing::rtti() const
73 return RS2::EntityDrawing;
77 * Counts the entities on the given layer.
79 unsigned long int Drawing::countLayerEntities(Layer * layer)
85 for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
87 if (t->getLayer() != NULL && t->getLayer()->getName() == layer->getName())
97 /*virtual*/ LayerList * Drawing::getLayerList()
102 /*virtual*/ BlockList * Drawing::getBlockList()
108 * Clears all layers, blocks and entities of this graphic.
109 * A default layer (0) is created.
111 void Drawing::newDoc()
113 DEBUG->print("Drawing::newDoc");
118 addLayer(new Layer("0"));
123 * Saves this graphic with the current filename and settings.
129 DEBUG->print("Drawing::save");
130 DEBUG->print(" file: %s", filename.toLatin1().data());
131 DEBUG->print(" format: %d", (int)formatType);
132 DEBUG->print(" export...");
133 ret = FILEIO->fileExport(*this, filename, formatType);
138 layerList.setModified(false);
139 blockList.setModified(false);
142 DEBUG->print("Drawing::save ok");
148 * Saves this graphic with the given filename and current settings.
150 bool Drawing::saveAs(const QString & filename, RS2::FormatType type)
152 DEBUG->print("Drawing::saveAs");
154 this->filename = filename;
155 this->formatType = type;
161 * Loads the given file into this graphic.
163 bool Drawing::open(const QString & filename, RS2::FormatType type)
165 DEBUG->print("Drawing::open(%s)", filename.toLatin1().data());
167 this->filename = filename;
171 ret = FILEIO->fileImport(*this, filename, type);
173 layerList.setModified(false);
174 blockList.setModified(false);
176 //cout << *((Drawing*)graphic);
177 //calculateBorders();
178 DEBUG->print("Drawing::open(%s): OK", filename.toLatin1().data());
183 // Wrappers for Layer functions:
184 void Drawing::clearLayers()
189 uint Drawing::countLayers() const
191 return layerList.count();
194 Layer * Drawing::layerAt(uint i)
196 return layerList.at(i);
199 void Drawing::activateLayer(const QString & name)
201 layerList.activate(name);
204 void Drawing::activateLayer(Layer * layer)
206 layerList.activate(layer);
209 Layer * Drawing::getActiveLayer()
211 return layerList.getActive();
214 /*virtual*/ void Drawing::addLayer(Layer * layer)
216 layerList.add(layer);
220 * Removes the given layer and undoes all entities on it.
222 /*virtual*/ void Drawing::removeLayer(Layer * layer)
224 if (layer != NULL && layer->getName() != "0")
226 // remove all entities on that layer:
229 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
231 if (e->getLayer() && e->getLayer()->getName() == layer->getName())
233 e->setUndoState(true);
241 // remove all entities in blocks that are on that layer:
242 for(uint bi=0; bi<blockList.count(); bi++)
244 Block * blk = blockList.at(bi);
248 for(Entity * e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone))
250 if (e->getLayer() != NULL && e->getLayer()->getName() == layer->getName())
252 e->setUndoState(true);
260 layerList.remove(layer);
264 /*virtual*/ void Drawing::editLayer(Layer * layer, const Layer & source)
266 layerList.edit(layer, source);
269 Layer * Drawing::findLayer(const QString & name)
271 return layerList.find(name);
274 void Drawing::toggleLayer(const QString & name)
276 layerList.toggle(name);
279 void Drawing::toggleLayer(Layer * layer)
281 layerList.toggle(layer);
284 void Drawing::toggleLayerLock(Layer * layer)
286 layerList.toggleLock(layer);
289 void Drawing::freezeAllLayers(bool freeze)
291 layerList.freezeAll(freeze);
295 void Drawing::addLayerListListener(LayerListListener * listener)
297 layerList.addListener(listener);
300 void Drawing::removeLayerListListener(LayerListListener * listener)
302 layerList.removeListener(listener);
306 // Wrapper for block functions:
308 void Drawing::clearBlocks()
313 uint Drawing::countBlocks()
315 return blockList.count();
318 Block * Drawing::blockAt(uint i)
320 return blockList.at(i);
323 void Drawing::activateBlock(const QString & name)
325 blockList.activate(name);
328 void Drawing::activateBlock(Block * block)
330 blockList.activate(block);
333 Block * Drawing::getActiveBlock()
335 return blockList.getActive();
338 /*virtual*/ bool Drawing::addBlock(Block * block, bool notify/*= true*/)
340 return blockList.add(block, notify);
343 /*virtual*/ void Drawing::addBlockNotification()
345 blockList.addNotification();
348 /*virtual*/ void Drawing::removeBlock(Block * block)
350 blockList.remove(block);
353 Block * Drawing::findBlock(const QString & name)
355 return blockList.find(name);
358 QString Drawing::newBlockName()
360 return blockList.newName();
363 void Drawing::toggleBlock(const QString & name)
365 blockList.toggle(name);
368 void Drawing::toggleBlock(Block * block)
370 blockList.toggle(block);
373 void Drawing::freezeAllBlocks(bool freeze)
375 blockList.freezeAll(freeze);
379 void Drawing::addBlockListListener(BlockListListener * listener)
381 blockList.addListener(listener);
384 void Drawing::removeBlockListListener(BlockListListener * listener)
386 blockList.removeListener(listener);
390 // Wrappers for variable functions:
391 void Drawing::clearVariables()
393 variableDict.clear();
396 int Drawing::countVariables()
398 return variableDict.count();
401 void Drawing::addVariable(const QString & key, const Vector & value, int code)
403 variableDict.add(key, value, code);
406 void Drawing::addVariable(const QString & key, const QString & value, int code)
408 variableDict.add(key, value, code);
411 void Drawing::addVariable(const QString & key, int value, int code)
413 variableDict.add(key, value, code);
416 void Drawing::addVariable(const QString & key, double value, int code)
418 variableDict.add(key, value, code);
421 Vector Drawing::getVariableVector(const QString & key, const Vector & def)
423 return variableDict.getVector(key, def);
426 QString Drawing::getVariableString(const QString & key, const QString & def)
428 return variableDict.getString(key, def);
431 int Drawing::getVariableInt(const QString & key, int def)
433 return variableDict.getInt(key, def);
436 double Drawing::getVariableDouble(const QString & key, double def)
438 return variableDict.getDouble(key, def);
441 void Drawing::removeVariable(const QString & key)
443 variableDict.remove(key);
446 //Q3Dict<Variable> & getVariableDict()
447 QMultiHash<QString, Variable *> & Drawing::getVariableDict()
449 return variableDict.getVariableDict();
453 * @return true if the grid is switched on (visible).
455 bool Drawing::isGridOn()
457 int on = getVariableInt("$GRIDMODE", 1);
463 * Enables / disables the grid.
465 void Drawing::setGridOn(bool on)
467 addVariable("$GRIDMODE", (int)on, 70);
471 * Sets the unit of this graphic to 'u'
473 void Drawing::setUnit(RS2::Unit u)
475 setPaperSize(Units::convert(getPaperSize(), getUnit(), u));
476 addVariable("$INSUNITS", (int)u, 70);
481 * Gets the unit of this graphic
483 RS2::Unit Drawing::getUnit()
485 return (RS2::Unit)getVariableInt("$INSUNITS", 0);
490 * @return The linear format type for this document.
491 * This is determined by the variable "$LUNITS".
493 RS2::LinearFormat Drawing::getLinearFormat()
495 int lunits = getVariableInt("$LUNITS", 2);
505 return RS2::Scientific;
509 return RS2::Engineering;
513 return RS2::Architectural;
517 return RS2::Fractional;
525 * @return The linear precision for this document.
526 * This is determined by the variable "$LUPREC".
528 int Drawing::getLinearPrecision()
530 return getVariableInt("$LUPREC", 4);
534 * @return The angle format type for this document.
535 * This is determined by the variable "$AUNITS".
537 RS2::AngleFormat Drawing::getAngleFormat()
539 int aunits = getVariableInt("$AUNITS", 0);
545 return RS2::DegreesDecimal;
549 return RS2::DegreesMinutesSeconds;
553 return RS2::Gradians;
561 return RS2::Surveyors;
565 return RS2::DegreesDecimal;
569 * @return The linear precision for this document.
570 * This is determined by the variable "$LUPREC".
572 int Drawing::getAnglePrecision()
574 return getVariableInt("$AUPREC", 4);
578 * @return The insertion point of the drawing into the paper space.
579 * This is the distance from the lower left paper edge to the zero
580 * point of the drawing. DXF: $PINSBASE.
582 Vector Drawing::getPaperInsertionBase()
584 return getVariableVector("$PINSBASE", Vector(0.0,0.0));
588 * Sets the PINSBASE variable.
590 void Drawing::setPaperInsertionBase(const Vector & p)
592 addVariable("$PINSBASE", p, 10);
596 * @return Paper size in graphic units.
598 Vector Drawing::getPaperSize()
600 Vector def = Units::convert(Vector(210.0, 297.0), RS2::Millimeter, getUnit());
601 Vector v1 = getVariableVector("$PLIMMIN", Vector(0.0, 0.0));
602 Vector v2 = getVariableVector("$PLIMMAX", def);
608 * Sets a new paper size.
610 void Drawing::setPaperSize(const Vector & s)
612 addVariable("$PLIMMIN", Vector(0.0, 0.0), 10);
613 addVariable("$PLIMMAX", s, 10);
617 * @return Paper format.
618 * This is determined by the variables "$PLIMMIN" and "$PLIMMAX".
620 * @param landscape will be set to true for landscape and false for portrait if not NULL.
622 RS2::PaperFormat Drawing::getPaperFormat(bool * landscape)
624 Vector size = Units::convert(getPaperSize(), getUnit(), RS2::Millimeter);
626 if (landscape != NULL)
627 *landscape = (size.x > size.y);
629 return Units::paperSizeToFormat(size);
633 * Sets the paper format to the given format.
635 void Drawing::setPaperFormat(RS2::PaperFormat f, bool landscape)
637 Vector size = Units::paperFormatToSize(f);
646 if (f != RS2::Custom)
647 setPaperSize(Units::convert(size, RS2::Millimeter, getUnit()));
651 * @return Paper space scaling (DXF: $PSVPSCALE).
653 double Drawing::getPaperScale()
657 ret = getVariableDouble("$PSVPSCALE", 1.0);
666 * Sets a new scale factor for the paper space.
668 void Drawing::setPaperScale(double s)
670 addVariable("$PSVPSCALE", s, 40);
674 * Centers drawing on page. Affects DXF variable $PINSBASE.
676 void Drawing::centerToPage()
678 Vector size = getPaperSize();
679 double scale = getPaperScale();
680 Vector pinsbase = (size - getSize() * scale) / 2.0 - getMin() * scale;
681 setPaperInsertionBase(pinsbase);
685 * Fits drawing on page. Affects DXF variable $PINSBASE.
687 void Drawing::fitToPage()
689 double border = Units::convert(25.0, RS2::Millimeter, getUnit());
690 Vector ps = getPaperSize() - Vector(border, border);
691 Vector s = getSize();
692 double fx = RS_MAXDOUBLE;
693 double fy = RS_MAXDOUBLE;
694 //double factor = 1.0;
696 //ps = Units::convert(ps, getUnit(), RS2::Millimeter);
698 if (fabs(s.x) > 1.0e-6)
701 if (fabs(s.y) > 1.0e-6)
704 setPaperScale(std::min(fx, fy));
709 * @retval true The document has been modified since it was last saved.
710 * @retval false The document has not been modified since it was last saved.
712 /*virtual*/ bool Drawing::isModified() const
714 return modified || layerList.isModified() || blockList.isModified();
718 * Sets the documents modified status to 'm'.
720 /*virtual*/ void Drawing::setModified(bool m)
723 layerList.setModified(m);
724 blockList.setModified(m);
728 RS_CamData & Drawing::getCamData()
733 void Drawing::setCamData(const RS_CamData & d)
740 * Dumps the entities to stdout.
742 std::ostream & operator<<(std::ostream & os, Drawing & g)
744 os << "--- Drawing: \n";
745 os << "---" << *g.getLayerList() << "\n";
746 os << "---" << *g.getBlockList() << "\n";
747 os << "---" << (Undo &)g << "\n";
748 os << "---" << (EntityContainer &)g << "\n";