diff --git a/src/Mod/TechDraw/App/CMakeLists.txt b/src/Mod/TechDraw/App/CMakeLists.txt index ca5088c48c..daab98cbdb 100644 --- a/src/Mod/TechDraw/App/CMakeLists.txt +++ b/src/Mod/TechDraw/App/CMakeLists.txt @@ -18,11 +18,22 @@ include_directories( ${QT_QTCORE_INCLUDE_DIR} ) +set(TechDrawLIBS + Measure + Part + Spreadsheet + Import +) + if(BUILD_QT5) include_directories( ${Qt5XmlPatterns_INCLUDE_DIRS} + ${Qt5Concurrent_INCLUDE_DIRS} ) set(QtXmlPatternsLib ${Qt5XmlPatterns_LIBRARIES}) + list(APPEND TechDrawLIBS + ${Qt5Concurrent_LIBRARIES} + ) else(BUILD_QT5) include_directories( ${QT_QTXMLPATTERNS_INCLUDE_DIR} @@ -32,13 +43,6 @@ endif(BUILD_QT5) link_directories(${OCC_LIBRARY_DIR}) -set(TechDrawLIBS - Measure - Part - Spreadsheet - Import -) - generate_from_xml(DrawPagePy) generate_from_xml(DrawViewPy) generate_from_xml(DrawViewPartPy) diff --git a/src/Mod/TechDraw/App/DrawGeomHatch.cpp b/src/Mod/TechDraw/App/DrawGeomHatch.cpp index 37aa3965e5..2fca2d8001 100644 --- a/src/Mod/TechDraw/App/DrawGeomHatch.cpp +++ b/src/Mod/TechDraw/App/DrawGeomHatch.cpp @@ -176,15 +176,29 @@ void DrawGeomHatch::makeLineSets() // Base::Console().Message("DGH::makeLineSets()\n"); if ((!PatIncluded.isEmpty()) && (!NamePattern.isEmpty())) { - std::vector specs = getDecodedSpecsFromFile(); m_lineSets.clear(); + m_lineSets = makeLineSets(PatIncluded.getValue(), + NamePattern.getValue()); + } +} + +/*static*/ +std::vector DrawGeomHatch::makeLineSets(std::string fileSpec, std::string myPattern) +{ + std::vector lineSets; + if ((!fileSpec.empty()) && + (!myPattern.empty())) { + std::vector specs = + DrawGeomHatch::getDecodedSpecsFromFile(fileSpec, + myPattern); for (auto& hl: specs) { - //hl.dump("hl from file"); + //hl.dump("hl from section"); LineSet ls; ls.setPATLineSpec(hl); - m_lineSets.push_back(ls); + lineSets.push_back(ls); } } + return lineSets; } DrawViewPart* DrawGeomHatch::getSourceView() const diff --git a/src/Mod/TechDraw/App/DrawGeomHatch.h b/src/Mod/TechDraw/App/DrawGeomHatch.h index c74cd1c108..d29a01173d 100644 --- a/src/Mod/TechDraw/App/DrawGeomHatch.h +++ b/src/Mod/TechDraw/App/DrawGeomHatch.h @@ -93,7 +93,7 @@ public: static std::string prefGeomHatchFile(void); static std::string prefGeomHatchName(); static App::Color prefGeomHatchColor(); - + static std::vector makeLineSets(std::string fileSpec, std::string myPattern); protected: virtual void onDocumentRestored() override; diff --git a/src/Mod/TechDraw/App/DrawLeaderLine.cpp b/src/Mod/TechDraw/App/DrawLeaderLine.cpp index 96c7f1be0d..4cc2f7b0d6 100644 --- a/src/Mod/TechDraw/App/DrawLeaderLine.cpp +++ b/src/Mod/TechDraw/App/DrawLeaderLine.cpp @@ -142,7 +142,8 @@ App::DocumentObjectExecReturn *DrawLeaderLine::execute() if (!keepUpdated()) { return App::DocumentObject::StdReturn; } - adjustLastSegment(); + adjustLastSegment(); + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawPage.cpp b/src/Mod/TechDraw/App/DrawPage.cpp index bd6af54c75..b09f7d5092 100644 --- a/src/Mod/TechDraw/App/DrawPage.cpp +++ b/src/Mod/TechDraw/App/DrawPage.cpp @@ -356,8 +356,11 @@ void DrawPage::updateAllViews() if (part) { continue; } - if (v) { - v->recomputeFeature(); + + TechDraw::DrawView* view = dynamic_cast(v); + if (view) { + view->overrideKeepUpdated(true); + view->recomputeFeature(); } } } diff --git a/src/Mod/TechDraw/App/DrawProjGroup.cpp b/src/Mod/TechDraw/App/DrawProjGroup.cpp index e1fa045cd1..f71107aed4 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroup.cpp @@ -62,8 +62,7 @@ const char* DrawProjGroup::ProjectionTypeEnums[] = {"First Angle", PROPERTY_SOURCE(TechDraw::DrawProjGroup, TechDraw::DrawViewCollection) -DrawProjGroup::DrawProjGroup() : - m_lockScale(false) +DrawProjGroup::DrawProjGroup() { static const char *group = "Base"; static const char *agroup = "Distribute"; @@ -115,50 +114,62 @@ void DrawProjGroup::onChanged(const App::Property* prop) { //TODO: For some reason, when the projection type is changed, the isometric views show change appropriately, but the orthographic ones don't... Or vice-versa. WF: why would you change from 1st to 3rd in mid drawing? //if group hasn't been added to page yet, can't scale or distribute projItems + if (isRestoring() || !getPage()) { + return TechDraw::DrawViewCollection::onChanged(prop); + } + TechDraw::DrawPage *page = getPage(); - if (!isRestoring() && page) { - if (prop == &Scale) { - if (!m_lockScale) { + + if (prop == &Scale) { + updateChildrenScale(); + recomputeChildren(); + return; + } + + if (prop == &ProjectionType) { + updateChildrenEnforce(); + return; + } + + if ( (prop == &Source) || + (prop == &XSource) ) { + updateChildrenSource(); + return; + } + + if ((prop == &spacingX) || (prop == &spacingY)) { + updateChildrenEnforce(); + return; + } + + if (prop == &LockPosition) { + updateChildrenLock(); + return; + } + + if (prop == &ScaleType) { + if (ScaleType.isValue("Automatic")) { + //Nothing in particular + } else if (ScaleType.isValue("Page")) { + double newScale = page->Scale.getValue(); + if(std::abs(getScale() - newScale) > FLT_EPSILON) { + Scale.setValue(newScale); updateChildrenScale(); - updateChildrenEnforce(); } + } else { + //ScaleType = Custom } + //DrawView will sort out Scale hidden/readonly/etc + TechDraw::DrawViewCollection::onChanged(prop); + } - if (prop == &ProjectionType) { - updateChildrenEnforce(); - } - - if ( (prop == &Source) || - (prop == &XSource) ) { - updateChildrenSource(); - } - - if ((prop == &spacingX) || (prop == &spacingY)) { - updateChildrenEnforce(); - } - - if (prop == &LockPosition) { - updateChildrenLock(); - } - - if (prop == &ScaleType) { - if (ScaleType.isValue("Automatic")) { - //Nothing in particular - } else if (ScaleType.isValue("Page")) { - double newScale = page->Scale.getValue(); - if(std::abs(getScale() - newScale) > FLT_EPSILON) { - Scale.setValue(newScale); - } - } - updateChildrenScale(); - } - if (prop == &Rotation) { - if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) { - Rotation.setValue(0.0); - purgeTouched(); - Base::Console().Log("DPG: Projection Groups do not rotate. Change ignored.\n"); - } + if (prop == &Rotation) { + if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) { + Rotation.setValue(0.0); + purgeTouched(); + Base::Console().Log("DPG: Projection Groups do not rotate. Change ignored.\n"); } + return; } TechDraw::DrawViewCollection::onChanged(prop); @@ -166,7 +177,8 @@ void DrawProjGroup::onChanged(const App::Property* prop) App::DocumentObjectExecReturn *DrawProjGroup::execute() { -// Base::Console().Message("DPG::execute() - %s\n", getNameInDocument()); +// Base::Console().Message("DPG::execute() - %s - waitingForChildren: %d\n", +// getNameInDocument(), waitingForChildren()); if (!keepUpdated()) return App::DocumentObject::StdReturn; @@ -178,15 +190,24 @@ App::DocumentObjectExecReturn *DrawProjGroup::execute() //no anchor yet. nothing to do. return DrawViewCollection::execute(); - if (ScaleType.isValue("Automatic") && !checkFit()) { - m_lockScale = true; - Scale.setValue(autoScale()); - Scale.purgeTouched(); - updateChildrenScale(); - m_lockScale = false; + if (waitingForChildren()) { + return DrawViewCollection::execute(); } - autoPositionChildren(); + if (ScaleType.isValue("Automatic") && !checkFit()) { + if (!DrawUtil::fpCompare(getScale(), autoScale(), 0.00001)) { + Scale.setValue(autoScale()); + //don't bother repositioning children since they will be + //recomputed at new scale + overrideKeepUpdated(false); + return DrawViewCollection::execute(); + } + } + + if (AutoDistribute.getValue()) { + autoPositionChildren(); + } + overrideKeepUpdated(false); return DrawViewCollection::execute(); } @@ -211,37 +232,29 @@ short DrawProjGroup::mustExecute() const return TechDraw::DrawViewCollection::mustExecute(); } -Base::BoundBox3d DrawProjGroup::getBoundingBox() const +void DrawProjGroup::reportReady() { - Base::BoundBox3d bbox; - - std::vector views = Views.getValues(); - TechDraw::DrawProjGroupItem *anchorView = dynamic_cast(Anchor.getValue()); - if (!anchorView) { - //if an element in Views is not a DPGI, something really bad has happened somewhere - Base::Console().Log("PROBLEM - DPG::getBoundingBox - non DPGI entry in Views! %s\n", - getNameInDocument()); - throw Base::TypeError("Error: projection in DPG list is not a DPGI!"); +// Base::Console().Message("DPG::reportReady - waitingForChildren: %d\n", waitingForChildren()); + if (waitingForChildren()) { + //not ready yet + return; } - for (std::vector::const_iterator it = views.begin(); it != views.end(); ++it) { - if ((*it)->getTypeId().isDerivedFrom(DrawViewPart::getClassTypeId())) { - DrawViewPart *part = static_cast(*it); - Base::BoundBox3d bb = part->getBoundingBox(); + //all the secondary views are ready so we can now figure out alignment + if (AutoDistribute.getValue()) { + recomputeFeature(); + } +} - bb.ScaleX(1. / part->getScale()); - bb.ScaleY(1. / part->getScale()); - bb.ScaleZ(1. / part->getScale()); - - // X and Y of dependent views are relative to the anchorView - if (part != anchorView) { - bb.MoveX(part->X.getValue()); - bb.MoveY(part->Y.getValue()); - } - - bbox.Add(bb); +bool DrawProjGroup::waitingForChildren() const +{ + for(const auto v : Views.getValues()) { + DrawProjGroupItem* dpgi = static_cast(v); + if (dpgi->waitingForHlr() || //dpgi is still thinking + dpgi->isTouched()) { //dpgi needs to execute + return true; } } - return bbox; + return false; } TechDraw::DrawPage * DrawProjGroup::getPage() const @@ -249,84 +262,92 @@ TechDraw::DrawPage * DrawProjGroup::getPage() const return findParentPage(); } -// obs? replaced by autoscale? -// Function provided by Joe Dowsett, 2014 -double DrawProjGroup::calculateAutomaticScale() const +//does the unscaled DPG fit on the page? +bool DrawProjGroup::checkFit() const { - TechDraw::DrawPage *page = getPage(); +// Base::Console().Message("DPG::checkFit() - %s\n", getNameInDocument()); + if (waitingForChildren()) { + //assume everything fits since we don't know what size the chilren are + return true; + } + auto page = findParentPage(); if (!page) throw Base::RuntimeError("No page is assigned to this feature"); - - DrawProjGroupItem *viewPtrs[10]; - - arrangeViewPointers(viewPtrs); - double width, height; - minimumBbViews(viewPtrs, width, height); //get SCALED boxes! - // if Page.keepUpdated is false, and DrawViews have never been executed, - // bb's will be 0x0 and this routine will return 0!!! - // if we return 1.0, AutoScale will sort itself out once bb's are non-zero. - double bbFudge = 1.2; - width *= bbFudge; - height *= bbFudge; - - // C++ Standard says casting bool to int gives 0 or 1 - int numVertSpaces = (viewPtrs[0] || viewPtrs[3] || viewPtrs[7]) + - (viewPtrs[2] || viewPtrs[5] || viewPtrs[9]) + - (viewPtrs[6] != nullptr); - int numHorizSpaces = (viewPtrs[0] || viewPtrs[1] || viewPtrs[2]) + - (viewPtrs[7] || viewPtrs[8] || viewPtrs[9]); - - double availableX = page->getPageWidth(); - double availableY = page->getPageHeight(); - double xWhite = spacingX.getValue() * (numVertSpaces + 1); - double yWhite = spacingY.getValue() * (numHorizSpaces + 1); - width += xWhite; - height += yWhite; - double scale_x = availableX / width; - double scale_y = availableY / height; - - double scaleFudge = 0.80; - float working_scale = scaleFudge * std::min(scale_x, scale_y); - double result = DrawUtil::sensibleScale(working_scale); - if (!(result > 0.0)) { - Base::Console().Log("DPG - %s - bad scale found (%.3f) using 1.0\n",getNameInDocument(),result); - result = 1.0; - } - - return result; + return checkFit(page); } -//returns the (scaled) bounding rectangle of all the views. -QRectF DrawProjGroup::getRect() const //this is current rect, not potential rect +bool DrawProjGroup::checkFit(DrawPage* page) const +{ +// Base::Console().Message("DPG::checkFit(page) - %s\n", getNameInDocument()); + if (waitingForChildren()) { + return true; + } + + QRectF bigBox = getRect(false); + if ( (bigBox.width() <= page->getPageWidth()) && + (bigBox.height() <= page->getPageHeight()) ) { + return true; + } + return false; +} + +//calculate a scale that fits all views on page +double DrawProjGroup::autoScale() const +{ +// Base::Console().Message("DPG::autoScale() - %s\n", getNameInDocument()); + auto page = findParentPage(); + if (!page) { + throw Base::RuntimeError("No page is assigned to this feature"); + } + return autoScale(page->getPageWidth(), page->getPageHeight()); +} + +double DrawProjGroup::autoScale(double w, double h) const +{ +// Base::Console().Message("DPG::autoScale(%.3f, %.3f) - %s\n", w, h, getNameInDocument()); + //get the space used by views + white space at 1:1 scale + QRectF bigBox = getRect(false); //unscaled box + + double xScale = w / bigBox.width(); // > 1 page bigger than figure + double yScale = h / bigBox.height(); // < 1 page is smaller than figure + + double newScale = std::min(xScale,yScale); + return DrawUtil::sensibleScale(newScale); +} + +//returns the bounding rectangle of all the views in the current scale +QRectF DrawProjGroup::getRect() const +{ + return getRect(true); +} + +QRectF DrawProjGroup::getRect(bool scaled) const { // Base::Console().Message("DPG::getRect - views: %d\n", Views.getValues().size()); DrawProjGroupItem *viewPtrs[10]; arrangeViewPointers(viewPtrs); - double width, height; - minimumBbViews(viewPtrs, width, height); //this is scaled! - double xSpace = spacingX.getValue() * 3.0 * std::max(1.0, getScale()); - double ySpace = spacingY.getValue() * 2.0 * std::max(1.0, getScale()); - double rectW = 0.0; - double rectH = 0.0; - if ( !(DrawUtil::fpCompare(width, 0.0) && - DrawUtil::fpCompare(height, 0.0)) ) { - rectW = width + xSpace; - rectH = height + ySpace; - } - double fudge = 1.3; //make rect a little big to make sure it fits + double totalWidth, totalHeight; + getViewArea(viewPtrs, totalWidth, totalHeight, scaled); + double xSpace = spacingX.getValue() * 3.0; + double ySpace = spacingY.getValue() * 2.0; + double rectW = totalWidth + xSpace; + double rectH = totalHeight + ySpace; + double fudge = 1.2; //make rect a little big to make sure it fits rectW *= fudge; rectH *= fudge; + return QRectF(0,0,rectW,rectH); } -//find area consumed by Views only in current scale -void DrawProjGroup::minimumBbViews(DrawProjGroupItem *viewPtrs[10], - double &width, double &height) const +//find area consumed by Views only - scaled or unscaled +void DrawProjGroup::getViewArea(DrawProjGroupItem *viewPtrs[10], + double &width, double &height, + bool scaled) const { - // Get bounding boxes in object scale + // Get the child view bounding boxes Base::BoundBox3d bboxes[10]; - makeViewBbs(viewPtrs, bboxes, true); //true => scaled - + makeViewBbs(viewPtrs, bboxes, scaled); + //TODO: note that TLF/TRF/BLF,BRF extend a bit farther than a strict row/col arrangement would suggest. //get widest view in each row/column double col0w = std::max(std::max(bboxes[0].LengthX(), bboxes[3].LengthX()), bboxes[7].LengthX()), @@ -910,16 +931,16 @@ void DrawProjGroup::arrangeViewPointers(DrawProjGroupItem *viewPtrs[10]) const void DrawProjGroup::makeViewBbs(DrawProjGroupItem *viewPtrs[10], Base::BoundBox3d bboxes[10], - bool documentScale) const + bool scaled) const { Base::BoundBox3d empty(Base::Vector3d(0.0, 0.0, 0.0), 0.0); for (int i = 0; i < 10; ++i) { bboxes[i] = empty; if (viewPtrs[i]) { bboxes[i] = viewPtrs[i]->getBoundingBox(); -// bboxes[i] = viewPtrs[i]->getBoundingBox(viewPtrs[i]->getProjectionCS(Base::Vector3d(0.0, 0.0, 0.0))); - if (!documentScale) { + if (!scaled) { double scale = 1.0 / viewPtrs[i]->getScale(); //convert bbx to 1:1 scale +// double scale = 1.0 / viewPtrs[i]->getLastScale(); //convert bbx to 1:1 scale bboxes[i].ScaleX(scale); bboxes[i].ScaleY(scale); bboxes[i].ScaleZ(scale); @@ -930,7 +951,7 @@ void DrawProjGroup::makeViewBbs(DrawProjGroupItem *viewPtrs[10], void DrawProjGroup::recomputeChildren() { -// Base::Console().Message("DPG::recomputeChildren()\n"); +// Base::Console().Message("DPG::recomputeChildren() - waiting: %d\n", waitingForChildren()); for( const auto it : Views.getValues() ) { auto view( dynamic_cast(it) ); if (!view) { @@ -943,14 +964,15 @@ void DrawProjGroup::recomputeChildren() void DrawProjGroup::autoPositionChildren() { -// Base::Console().Message("DPG::autoPositionChildren() - %s\n", getNameInDocument()); +// Base::Console().Message("DPG::autoPositionChildren() - %s - waiting: %d\n", +// getNameInDocument(), waitingForChildren()); for( const auto it : Views.getValues() ) { auto view( dynamic_cast(it) ); if (!view) { + //if an element in Views is not a DPGI, something really bad has happened somewhere throw Base::TypeError("Error: projection in DPG list is not a DPGI!"); } else { view->autoPosition(); - view->requestPaint(); } } } @@ -960,16 +982,16 @@ void DrawProjGroup::autoPositionChildren() */ void DrawProjGroup::updateChildrenScale() { -// Base::Console().Message("DPG::updateChildrenScale\n"); +// Base::Console().Message("DPG::updateChildrenScale() - waiting: %d\n", waitingForChildren()); for( const auto it : Views.getValues() ) { auto view( dynamic_cast(it) ); if (!view) { //if an element in Views is not a DPGI, something really bad has happened somewhere - Base::Console().Log("PROBLEM - DPG::updateChildrenScale - non DPGI entry in Views! %s\n", - getNameInDocument()); throw Base::TypeError("Error: projection in DPG list is not a DPGI!"); } else { view->Scale.setValue(getScale()); + view->Scale.purgeTouched(); + view->purgeTouched(); } } } @@ -1016,22 +1038,7 @@ void DrawProjGroup::updateChildrenLock() } } -void DrawProjGroup::updateViews() { - // this is intended to update the views in general, e.g. when the spacing changed - for (const auto it : Views.getValues()) { - auto view(dynamic_cast(it)); - if (!view) { - //if an element in Views is not a DPGI, something really bad has happened somewhere - Base::Console().Log("PROBLEM - DPG::updateViews - non DPGI entry in Views! %s\n", - getNameInDocument()); - throw Base::TypeError("Error: projection in DPG list is not a DPGI!"); - } - else // the views are OK - view->recomputeFeature(); - } -} - -void DrawProjGroup::updateChildrenEnforce() +void DrawProjGroup::updateChildrenEnforce(void) { for( const auto it : Views.getValues() ) { auto view( dynamic_cast(it) ); diff --git a/src/Mod/TechDraw/App/DrawProjGroup.h b/src/Mod/TechDraw/App/DrawProjGroup.h index 5ebe856f39..585117a225 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.h +++ b/src/Mod/TechDraw/App/DrawProjGroup.h @@ -22,8 +22,8 @@ #ifndef _TECHDRAW_FEATUREVIEWGROUP_H_ #define _TECHDRAW_FEATUREVIEWGROUP_H_ - -#include + +#include #include # include @@ -51,7 +51,7 @@ class DrawProjGroupItem; class TechDrawExport DrawProjGroup : public TechDraw::DrawViewCollection { PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawProjGroup); - Q_OBJECT + Q_OBJECT public: /// Constructor @@ -72,9 +72,11 @@ public: App::PropertyLink Anchor; /// Anchor Element to align views to - Base::BoundBox3d getBoundingBox() const; - double calculateAutomaticScale() const; - QRectF getRect() const override; + double autoScale() const override; + double autoScale(double w, double h) const override; + QRectF getRect() const override; //always scaled + QRectF getRect(bool scaled) const; //scaled or unscaled + /// Check if container has a view of a specific type bool hasProjection(const char *viewProjType) const; @@ -137,7 +139,13 @@ public: void updateChildrenEnforce(); std::vector getAllSources() const; + bool checkFit() const override; + bool checkFit(DrawPage* p) const override; + bool waitingForChildren() const; + void reportReady(); + + void dumpTouchedProps(); protected: void onChanged(const App::Property* prop) override; @@ -158,30 +166,29 @@ protected: */ void makeViewBbs(DrawProjGroupItem *viewPtrs[10], Base::BoundBox3d bboxes[10], - bool documentScale = true) const; + bool scaled = true) const; /// Helper for calculateAutomaticScale /*! * Returns a width and height in object-space scale, for the enabled views * without accounting for their actual X and Y positions or borders. */ - void minimumBbViews(DrawProjGroupItem *viewPtrs[10], - double &width, double &height) const; + void getViewArea(DrawProjGroupItem *viewPtrs[10], + double &width, double &height, + bool scaled = true) const; /// Returns pointer to our page, or NULL if it couldn't be located TechDraw::DrawPage * getPage() const; void updateChildrenSource(); void updateChildrenLock(); - void updateViews(); + int getViewIndex(const char *viewTypeCStr) const; int getDefProjConv() const; Base::Vector3d dir2vec(gp_Dir d); gp_Dir vec2dir(Base::Vector3d v); void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override; - - bool m_lockScale; }; } //namespace TechDraw diff --git a/src/Mod/TechDraw/App/DrawProjGroupItem.cpp b/src/Mod/TechDraw/App/DrawProjGroupItem.cpp index 3ad3b7f161..b13c320e55 100644 --- a/src/Mod/TechDraw/App/DrawProjGroupItem.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroupItem.cpp @@ -81,18 +81,7 @@ DrawProjGroupItem::~DrawProjGroupItem() short DrawProjGroupItem::mustExecute() const { - short result = 0; - if (!isRestoring()) { - result = (Direction.isTouched() || - XDirection.isTouched() || - Source.isTouched() || - XSource.isTouched() || - Scale.isTouched()); - } - - if (result) { - return result; - } + //there is nothing unique about dpgi vs dvp return TechDraw::DrawViewPart::mustExecute(); } @@ -158,22 +147,19 @@ App::DocumentObjectExecReturn *DrawProjGroupItem::execute(void) return new App::DocumentObjectExecReturn("DPGI: Direction and XDirection are parallel"); } - App::DocumentObjectExecReturn* ret = DrawViewPart::execute(); - //autoPosition needs to run after the geometry has been created - autoPosition(); - return ret; + return DrawViewPart::execute(); } void DrawProjGroupItem::postHlrTasks(void) { // Base::Console().Message("DPGI::postHlrTasks() - %s\n", getNameInDocument()); - //DPGI has no geometry until HLR has finished, and the DPG can not properly - //AutoDistibute until all its items have geometry. autoPositionChildren is - //relatively cheap so we can do it after every geometry update - if (getPGroup() && getPGroup()->AutoDistribute.getValue()) { - getPGroup()->autoPositionChildren(); - } DrawViewPart::postHlrTasks(); + + //DPGI has no geometry until HLR has finished, and the DPG can not properly + //AutoDistibute until all its items have geometry. + autoPosition(); + + getPGroup()->reportReady(); //tell the parent DPG we are ready } void DrawProjGroupItem::autoPosition() @@ -184,11 +170,12 @@ void DrawProjGroupItem::autoPosition() } Base::Vector3d newPos; if (getPGroup() && getPGroup()->AutoDistribute.getValue()) { - newPos = getPGroup()->getXYPosition(Type.getValueAsString()); - X.setValue(newPos.x); - Y.setValue(newPos.y); - requestPaint(); - purgeTouched(); //prevents "still touched after recompute" message + newPos = getPGroup()->getXYPosition(Type.getValueAsString()); + X.setValue(newPos.x); + Y.setValue(newPos.y); + requestPaint(); + purgeTouched(); //prevents "still touched after recompute" message + getPGroup()->purgeTouched(); //changing dpgi x,y marks parent dpg as touched } } diff --git a/src/Mod/TechDraw/App/DrawRichAnno.cpp b/src/Mod/TechDraw/App/DrawRichAnno.cpp index 84a242e390..a7c872d031 100644 --- a/src/Mod/TechDraw/App/DrawRichAnno.cpp +++ b/src/Mod/TechDraw/App/DrawRichAnno.cpp @@ -94,7 +94,8 @@ App::DocumentObjectExecReturn *DrawRichAnno::execute() // Base::Console().Message("DRA::execute() - @ (%.3f, %.3f)\n", X.getValue(), Y.getValue()); if (!keepUpdated()) { return App::DocumentObject::StdReturn; - } + } + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawView.cpp b/src/Mod/TechDraw/App/DrawView.cpp index d7a3ea3f79..438d29c3a4 100644 --- a/src/Mod/TechDraw/App/DrawView.cpp +++ b/src/Mod/TechDraw/App/DrawView.cpp @@ -74,7 +74,8 @@ PROPERTY_SOURCE(TechDraw::DrawView, App::DocumentObject) DrawView::DrawView(): autoPos(true), - mouseMove(false) + mouseMove(false), + m_overrideKeepUpdated(false) { static const char *group = "Base"; ADD_PROPERTY_TYPE(X, (0.0), group, (App::PropertyType)(App::Prop_Output), "X position"); @@ -380,6 +381,7 @@ double DrawView::autoScale(double pw, double ph) const bool DrawView::checkFit() const { +// Base::Console().Message("DV::checkFit() - %s\n", getNameInDocument()); auto page = findParentPage(); return checkFit(page); } @@ -387,6 +389,7 @@ bool DrawView::checkFit() const //!check if View is too big for page bool DrawView::checkFit(TechDraw::DrawPage* p) const { +// Base::Console().Message("DV::checkFit(page) - %s\n", getNameInDocument()); bool result = true; double fudge = 1.1; @@ -534,13 +537,14 @@ void DrawView::handleChangedPropertyType( bool DrawView::keepUpdated() { // Base::Console().Message("DV::keepUpdated() - %s\n", getNameInDocument()); - bool result = false; - + if (overrideKeepUpdated()) { + return true; + } TechDraw::DrawPage *page = findParentPage(); if(page) { - result = page->canUpdate() || page->forceRedraw(); + return (page->canUpdate() || page->forceRedraw()); } - return result; + return false; } void DrawView::setScaleAttribute() diff --git a/src/Mod/TechDraw/App/DrawView.h b/src/Mod/TechDraw/App/DrawView.h index 5921c7477e..8353fe473f 100644 --- a/src/Mod/TechDraw/App/DrawView.h +++ b/src/Mod/TechDraw/App/DrawView.h @@ -112,6 +112,9 @@ public: void setScaleAttribute(); + void overrideKeepUpdated(bool s) { m_overrideKeepUpdated = s; } + bool overrideKeepUpdated(void) { return m_overrideKeepUpdated; } + protected: void onChanged(const App::Property* prop) override; virtual void validateScale(); @@ -125,6 +128,8 @@ protected: private: static const char* ScaleTypeEnums[]; static App::PropertyFloatConstraint::Constraints scaleRange; + + bool m_overrideKeepUpdated; }; typedef App::FeaturePythonT DrawViewPython; diff --git a/src/Mod/TechDraw/App/DrawViewArch.cpp b/src/Mod/TechDraw/App/DrawViewArch.cpp index 99b5abb9ec..ac7347ee5f 100644 --- a/src/Mod/TechDraw/App/DrawViewArch.cpp +++ b/src/Mod/TechDraw/App/DrawViewArch.cpp @@ -140,7 +140,7 @@ App::DocumentObjectExecReturn *DrawViewArch::execute() Base::Interpreter().runStringArg("App.activeDocument().%s.Symbol = '%s' + svgBody + '%s'", FeatName.c_str(),svgHead.c_str(),svgTail.c_str()); } -// requestPaint(); + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawViewClip.cpp b/src/Mod/TechDraw/App/DrawViewClip.cpp index 2dd37225ee..3a25ef9393 100644 --- a/src/Mod/TechDraw/App/DrawViewClip.cpp +++ b/src/Mod/TechDraw/App/DrawViewClip.cpp @@ -119,6 +119,7 @@ App::DocumentObjectExecReturn *DrawViewClip::execute() } requestPaint(); + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawViewCollection.cpp b/src/Mod/TechDraw/App/DrawViewCollection.cpp index 5a41db3728..f32b2a00da 100644 --- a/src/Mod/TechDraw/App/DrawViewCollection.cpp +++ b/src/Mod/TechDraw/App/DrawViewCollection.cpp @@ -77,6 +77,7 @@ App::DocumentObjectExecReturn *DrawViewCollection::execute() lockChildren(); + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawViewDetail.cpp b/src/Mod/TechDraw/App/DrawViewDetail.cpp index f515d5ab7b..af472ae57c 100644 --- a/src/Mod/TechDraw/App/DrawViewDetail.cpp +++ b/src/Mod/TechDraw/App/DrawViewDetail.cpp @@ -24,35 +24,21 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include - #include -#include #include -#include #include #include #include -#include -#include #include #include #include -#include #include #include -#include -#include #include -#include #include #include #include -#include -#include -#include #include -#include #include #include #include @@ -61,42 +47,38 @@ #include #include #include - #endif #include +#include #include #include -#include "QtConcurrent/qtconcurrentrun.h" +#include #include #include #include #include -#include #include +#include #include #include #include -#include "Preferences.h" -#include "Geometry.h" -#include "GeometryObject.h" -#include "Cosmetic.h" -#include "EdgeWalker.h" -#include "DrawProjectSplit.h" -#include "DrawProjGroupItem.h" #include "DrawPage.h" #include "DrawUtil.h" -#include "DrawViewDetail.h" #include "DrawViewSection.h" +#include "Geometry.h" +#include "GeometryObject.h" +#include "Preferences.h" + +#include "DrawViewDetail.h" using namespace TechDraw; using namespace std; - //=========================================================================== // DrawViewDetail //=========================================================================== @@ -104,7 +86,9 @@ using namespace std; PROPERTY_SOURCE(TechDraw::DrawViewDetail, TechDraw::DrawViewPart) DrawViewDetail::DrawViewDetail() : - m_waitingForDetail(false) + m_waitingForDetail(false), + m_saveDvp(nullptr), + m_saveDvs(nullptr) { static const char *dgroup = "Detail"; @@ -129,66 +113,71 @@ DrawViewDetail::~DrawViewDetail() short DrawViewDetail::mustExecute() const { - if (!isRestoring()) { - if ( - AnchorPoint.isTouched() || - Radius.isTouched() || - BaseView.isTouched() || - Reference.isTouched() - ) { - return true; - } + if (isRestoring()) { + TechDraw::DrawView::mustExecute(); } + + if (AnchorPoint.isTouched() || + Radius.isTouched() || + BaseView.isTouched() || + Reference.isTouched()) { + return 1; + } + return TechDraw::DrawView::mustExecute(); } void DrawViewDetail::onChanged(const App::Property* prop) { - if (!isRestoring()) { - if (prop == &Reference) { - std::string lblText = "Detail " + - std::string(Reference.getValue()); - Label.setValue(lblText); - } - if ((prop == &Reference) || - (prop == &Radius) || - (prop == &BaseView)) { - requestPaint(); - } - if (prop == &AnchorPoint) { - // to see AnchorPoint changes repainting is not enough, we must recompute - recomputeFeature(true); - } - if (prop == &ScaleType) { - auto page = findParentPage(); - // if ScaleType is "Page", the user cannot change it - if (ScaleType.isValue("Page")) { - Scale.setStatus(App::Property::ReadOnly, true); - // apply the page-wide Scale - if (page) { - if (std::abs(page->Scale.getValue() - getScale()) > FLT_EPSILON) { - Scale.setValue(page->Scale.getValue()); - Scale.purgeTouched(); - } + if (isRestoring()) { + DrawView::onChanged(prop); + return; + } + + if (prop == &Reference) { + std::string lblText = "Detail " + + std::string(Reference.getValue()); + Label.setValue(lblText); + } + if ((prop == &Reference) || + (prop == &Radius) || + (prop == &BaseView)) { + requestPaint(); + } + if (prop == &AnchorPoint) { + // to see AnchorPoint changes repainting is not enough, we must recompute + recomputeFeature(true); + } + if (prop == &ScaleType) { + auto page = findParentPage(); + // if ScaleType is "Page", the user cannot change it + if (ScaleType.isValue("Page")) { + Scale.setStatus(App::Property::ReadOnly, true); + // apply the page-wide Scale + if (page) { + if (std::abs(page->Scale.getValue() - getScale()) > FLT_EPSILON) { + Scale.setValue(page->Scale.getValue()); + Scale.purgeTouched(); } } - else if (ScaleType.isValue("Custom")) { - // allow the change Scale - Scale.setStatus(App::Property::ReadOnly, false); - } - else if (ScaleType.isValue("Automatic")) { - Scale.setStatus(App::Property::ReadOnly, true); - // apply a Scale - if (!checkFit(page)) { - double newScale = autoScale(page->getPageWidth(), page->getPageHeight()); - if (std::abs(newScale - getScale()) > FLT_EPSILON) { //stops onChanged/execute loop - Scale.setValue(newScale); - Scale.purgeTouched(); - } + } + else if (ScaleType.isValue("Custom")) { + // allow Scale changes + Scale.setStatus(App::Property::ReadOnly, false); + } + else if (ScaleType.isValue("Automatic")) { + Scale.setStatus(App::Property::ReadOnly, true); + // apply an automatic Scale + if (!checkFit(page)) { + double newScale = autoScale(page->getPageWidth(), page->getPageHeight()); + if (std::abs(newScale - getScale()) > FLT_EPSILON) { //stops onChanged/execute loop + Scale.setValue(newScale); + Scale.purgeTouched(); } } } } + DrawView::onChanged(prop); } @@ -196,19 +185,16 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute() { // Base::Console().Message("DVD::execute() - %s\n", getNameInDocument()); if (!keepUpdated()) { - return App::DocumentObject::StdReturn; + return DrawView::execute(); } App::DocumentObject* baseObj = BaseView.getValue(); if (!baseObj) { - Base::Console().Log("DVD::execute - No BaseView(s) linked. - %s\n", - getNameInDocument()); return DrawView::execute(); } if (!baseObj->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { - Base::Console().Log("DVD::execute - %s - BaseView object is not a DrawViewPart object\n", - getNameInDocument()); + //this can only happen via scripting? return DrawView::execute(); } @@ -224,8 +210,6 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute() } if (shape.IsNull()) { - Base::Console().Log("DVD::execute - %s - Source shape is Null\n", - getNameInDocument()); return DrawView::execute(); } @@ -241,18 +225,7 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute() detailExec(shape, dvp, dvs); addShapes2d(); - //second pass if required - if (ScaleType.isValue("Automatic") && !checkFit()) { - double newScale = autoScale(); - Scale.setValue(newScale); - Scale.purgeTouched(); - if (geometryObject) { - delete geometryObject; - geometryObject = nullptr; - detailExec(shape, dvp, dvs); - } - } - dvp->requestPaint(); //to refresh detail highlight! + dvp->requestPaint(); //to refresh detail highlight in base view return DrawView::execute(); } @@ -262,93 +235,91 @@ void DrawViewDetail::detailExec(TopoDS_Shape& shape, DrawViewPart* dvp, DrawViewSection* dvs) { - if (waitingForResult()) { + if (waitingForHlr() || + waitingForDetail()) { // Base::Console().Message("DVD::detailExec - waiting for result\n"); return; } - if (waitingForDetail()) { - return; - } QObject::connect(&m_detailWatcher, SIGNAL(finished()), this, SLOT(onMakeDetailFinished())); m_detailFuture = QtConcurrent::run(this, &DrawViewDetail::makeDetailShape, shape, dvp, dvs); m_detailWatcher.setFuture(m_detailFuture); + waitingForDetail(true); } //this runs in a separate thread since it can sometimes take a long time +//make a common of the input shape and a cylinder (or prism depending on +//the matting style) void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, DrawViewPart* dvp, DrawViewSection* dvs) { - waitingForDetail(true); showProgressMessage(getNameInDocument(), "is making detail shape"); -// auto start = chrono::high_resolution_clock::now(); - - Base::Vector3d anchor = AnchorPoint.getValue(); //this is a 2D point (in unrotated coords) Base::Vector3d dirDetail = dvp->Direction.getValue(); - double radius = getFudgeRadius(); int solidCount = DrawUtil::countSubShapes(shape, TopAbs_SOLID); int shellCount = DrawUtil::countSubShapes(shape, TopAbs_SHELL); + //make a copy of the input shape so we don't inadvertently change it BRepBuilderAPI_Copy BuilderCopy(shape); - TopoDS_Shape myShape = BuilderCopy.Shape(); + TopoDS_Shape copyShape = BuilderCopy.Shape(); + m_saveShape = copyShape; + m_saveDvp = dvp; + m_saveDvs = dvs; - gp_Pnt gpCenter = TechDraw::findCentroid(myShape, + gp_Pnt gpCenter = TechDraw::findCentroid(copyShape, dirDetail); Base::Vector3d shapeCenter = Base::Vector3d(gpCenter.X(),gpCenter.Y(),gpCenter.Z()); m_saveCentroid = shapeCenter; //centroid of original shape - if (dvs) { + if (!dvs) { //section cutShape should already be on origin - } else { - myShape = TechDraw::moveShape(myShape, //centre shape on origin + copyShape = TechDraw::moveShape(copyShape, //centre shape on origin -shapeCenter); } shapeCenter = Base::Vector3d(0.0, 0.0, 0.0); - m_viewAxis = dvp->getProjectionCS(shapeCenter); - anchor = Base::Vector3d(anchor.x,anchor.y, 0.0); //anchor coord in projection CS - Base::Vector3d anchorOffset3d = DrawUtil::toR3(m_viewAxis, anchor); //actual anchor coords in R3 + m_viewAxis = dvp->getProjectionCS(shapeCenter); //save the CS for later + Base::Vector3d anchor = AnchorPoint.getValue(); //this is a 2D point in unrotated base view coords + anchor = DrawUtil::toR3(m_viewAxis, anchor); //actual anchor coords in R3 Bnd_Box bbxSource; bbxSource.SetGap(0.0); - BRepBndLib::AddOptimal(myShape, bbxSource); + BRepBndLib::AddOptimal(copyShape, bbxSource); double diag = sqrt(bbxSource.SquareExtent()); - Base::Vector3d toolPlaneOrigin = anchorOffset3d + dirDetail * diag * -1.0; //center tool about anchor + Base::Vector3d toolPlaneOrigin = anchor + dirDetail * diag * -1.0; //center tool about anchor double extrudeLength = 2.0 * toolPlaneOrigin.Length(); gp_Pnt gpnt(toolPlaneOrigin.x,toolPlaneOrigin.y,toolPlaneOrigin.z); gp_Dir gdir(dirDetail.x,dirDetail.y,dirDetail.z); - double hideToolRadius = radius * 1.0; - TopoDS_Face aProjFace; + TopoDS_Face extrusionFace; Base::Vector3d extrudeVec = dirDetail * extrudeLength; - gp_Vec extrudeDir(extrudeVec.x,extrudeVec.y,extrudeVec.z); + gp_Vec extrudeDir(extrudeVec.x, extrudeVec.y, extrudeVec.z); TopoDS_Shape tool; if (Preferences::mattingStyle()) { //square mat gp_Pln gpln(gpnt,gdir); - BRepBuilderAPI_MakeFace mkFace(gpln, -hideToolRadius,hideToolRadius,-hideToolRadius,hideToolRadius); - aProjFace = mkFace.Face(); - if(aProjFace.IsNull()) { - Base::Console().Warning("DVD::detailExec - %s - failed to create tool base face\n", getNameInDocument()); + BRepBuilderAPI_MakeFace mkFace(gpln, -radius, radius, -radius, radius); + extrusionFace = mkFace.Face(); + if(extrusionFace.IsNull()) { + Base::Console().Warning("DVD::makeDetailShape - %s - failed to create tool base face\n", getNameInDocument()); return; } - tool = BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape(); + tool = BRepPrimAPI_MakePrism(extrusionFace, extrudeDir, false, true).Shape(); if(tool.IsNull()) { - Base::Console().Warning("DVD::detailExec - %s - failed to create tool (prism)\n", getNameInDocument()); + Base::Console().Warning("DVD::makeDetailShape - %s - failed to create tool (prism)\n", getNameInDocument()); return; } } else { //circular mat gp_Ax2 cs(gpnt, gdir); - BRepPrimAPI_MakeCylinder mkTool(cs, hideToolRadius, extrudeLength); + BRepPrimAPI_MakeCylinder mkTool(cs, radius, extrudeLength); tool = mkTool.Shape(); if(tool.IsNull()) { Base::Console().Warning("DVD::detailExec - %s - failed to create tool (cylinder)\n", getNameInDocument()); @@ -356,29 +327,29 @@ void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, } } + //for each solid and shell in the input shape, make a common with the tool and + //add the result to a compound. This avoids issues with some geometry errors in the + //input shape. BRep_Builder builder; TopoDS_Compound pieces; builder.MakeCompound(pieces); if (solidCount > 0) { - TopExp_Explorer expl(myShape, TopAbs_SOLID); + TopExp_Explorer expl(copyShape, TopAbs_SOLID); for (; expl.More(); expl.Next()) { const TopoDS_Solid& s = TopoDS::Solid(expl.Current()); BRepAlgoAPI_Common mkCommon(s,tool); if (!mkCommon.IsDone()) { - // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (1)\n", getNameInDocument()); continue; } if (mkCommon.Shape().IsNull()) { - // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (2)\n", getNameInDocument()); continue; } //this might be overkill for piecewise algo //Did we get at least 1 solid? TopExp_Explorer xp; xp.Init(mkCommon.Shape(),TopAbs_SOLID); - if (!(xp.More() == Standard_True)) { - // Base::Console().Warning("DVD::execute - mkCommon.Shape is not a solid!\n"); + if ((xp.More() != Standard_True)) { continue; } builder.Add(pieces, mkCommon.Shape()); @@ -386,25 +357,22 @@ void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, } if (shellCount > 0) { - TopExp_Explorer expl(myShape, TopAbs_SHELL); + TopExp_Explorer expl(copyShape, TopAbs_SHELL); for (; expl.More(); expl.Next()) { const TopoDS_Shell& s = TopoDS::Shell(expl.Current()); BRepAlgoAPI_Common mkCommon(s,tool); if (!mkCommon.IsDone()) { - // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (1)\n", getNameInDocument()); continue; } if (mkCommon.Shape().IsNull()) { - // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (2)\n", getNameInDocument()); continue; } //this might be overkill for piecewise algo //Did we get at least 1 shell? TopExp_Explorer xp; xp.Init(mkCommon.Shape(),TopAbs_SHELL); - if (!(xp.More() == Standard_True)) { - // Base::Console().Warning("DVD::execute - mkCommon.Shape is not a shell!\n"); + if ((xp.More() != Standard_True)) { continue; } builder.Add(pieces, mkCommon.Shape()); @@ -413,17 +381,10 @@ void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, if (debugDetail()) { BRepTools::Write(tool, "DVDTool.brep"); //debug - BRepTools::Write(myShape, "DVDCopy.brep"); //debug + BRepTools::Write(copyShape, "DVDCopy.brep"); //debug BRepTools::Write(pieces, "DVDCommon.brep"); //debug } -//for debugging show compound instead of common -// BRep_Builder builder; -// TopoDS_Compound Comp; -// builder.MakeCompound(Comp); -// builder.Add(Comp, tool); -// builder.Add(Comp, myShape); - gp_Pnt inputCenter; try { //centroid of result @@ -438,7 +399,7 @@ void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, (shellCount > 0)) { //align shape with detail anchor TopoDS_Shape centeredShape = TechDraw::moveShape(pieces, - anchorOffset3d * -1.0); + anchor * -1.0); m_scaledShape = TechDraw::scaleShape(centeredShape, getScale()); if (debugDetail()) { @@ -446,9 +407,9 @@ void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, } } else { //no solids, no shells, do what you can with edges - TopoDS_Shape projectedEdges = projectEdgesOntoFace(myShape, aProjFace, gdir); + TopoDS_Shape projectedEdges = projectEdgesOntoFace(copyShape, extrusionFace, gdir); TopoDS_Shape centeredShape = TechDraw::moveShape(projectedEdges, - anchorOffset3d * -1.0); + anchor * -1.0); if (debugDetail()) { BRepTools::Write(projectedEdges, "DVDProjectedEdges.brep"); //debug BRepTools::Write(centeredShape, "DVDCenteredShape.brep"); //debug @@ -472,10 +433,6 @@ void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, return; } -// auto end = chrono::high_resolution_clock::now(); -// auto diff = end - start; -// double diffOut = chrono::duration (diff).count(); -// Base::Console().Message("DVD::makeDetailShape - %s spent: %.3f millisecs making detail shape\n", getNameInDocument(), diffOut); showProgressMessage(getNameInDocument(), "has finished making detail shape"); } @@ -485,6 +442,19 @@ void DrawViewDetail::postHlrTasks(void) geometryObject->pruneVertexGeom(Base::Vector3d(0.0,0.0,0.0), Radius.getValue() * getScale()); //remove vertices beyond clipradius DrawViewPart::postHlrTasks(); + + //second pass if required + if (ScaleType.isValue("Automatic") && !checkFit()) { + double newScale = autoScale(); + Scale.setValue(newScale); + Scale.purgeTouched(); + if (geometryObject) { + delete geometryObject; + geometryObject = nullptr; + detailExec(m_saveShape, m_saveDvp, m_saveDvs); + } + } + overrideKeepUpdated(false); } //continue processing after makeDetailShape thread is finished @@ -497,6 +467,15 @@ void DrawViewDetail::onMakeDetailFinished(void) geometryObject = buildGeometryObject(m_scaledShape, m_viewAxis); } + +bool DrawViewDetail::waitingForResult() const +{ + if (DrawViewPart::waitingForResult() || + waitingForDetail()) { + return true; + } + return false; +} TopoDS_Shape DrawViewDetail::projectEdgesOntoFace(TopoDS_Shape &edgeShape, TopoDS_Face &projFace, gp_Dir& projDir) diff --git a/src/Mod/TechDraw/App/DrawViewDetail.h b/src/Mod/TechDraw/App/DrawViewDetail.h index c69d80755a..05d5a089ff 100644 --- a/src/Mod/TechDraw/App/DrawViewDetail.h +++ b/src/Mod/TechDraw/App/DrawViewDetail.h @@ -81,7 +81,8 @@ public: DrawViewSection* dvs); void postHlrTasks(void) override; void waitingForDetail(bool s) { m_waitingForDetail = s; } - bool waitingForDetail(void) { return m_waitingForDetail; } + bool waitingForDetail(void) const { return m_waitingForDetail; } + bool waitingForResult() const override; double getFudgeRadius(void); TopoDS_Shape projectEdgesOntoFace(TopoDS_Shape& edgeShape, @@ -104,6 +105,9 @@ protected: QFutureWatcher m_detailWatcher; QFuture m_detailFuture; bool m_waitingForDetail; + + DrawViewPart* m_saveDvp; + DrawViewSection* m_saveDvs; }; typedef App::FeaturePythonT DrawViewDetailPython; diff --git a/src/Mod/TechDraw/App/DrawViewDimExtent.cpp b/src/Mod/TechDraw/App/DrawViewDimExtent.cpp index adc05b7f22..e8c3c1967a 100644 --- a/src/Mod/TechDraw/App/DrawViewDimExtent.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimExtent.cpp @@ -133,7 +133,7 @@ App::DocumentObjectExecReturn *DrawViewDimExtent::execute(void) TechDraw::VertexPtr v0 = dvp->getProjVertexByCosTag(cTags[0]); TechDraw::VertexPtr v1 = dvp->getProjVertexByCosTag(cTags[1]); - if (!v0 || v1) + if (!v0 || !v1) return DrawViewDimension::execute(); double length00 = (v0->pnt - refMin).Length(); @@ -156,6 +156,7 @@ App::DocumentObjectExecReturn *DrawViewDimExtent::execute(void) cvTemp->permaPoint = refMax / scale; } + overrideKeepUpdated(false); return DrawViewDimension::execute(); } diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index 1b6c16257d..c309cfa90f 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -736,7 +736,7 @@ App::DocumentObjectExecReturn *DrawViewDimension::execute() m_hasGeometry = true; } - //TODO: if MeasureType = Projected and the Projected shape changes, the Dimension may become invalid (see tilted Cube example) + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawViewDraft.cpp b/src/Mod/TechDraw/App/DrawViewDraft.cpp index 4a391cc32b..ac4ffe4c91 100644 --- a/src/Mod/TechDraw/App/DrawViewDraft.cpp +++ b/src/Mod/TechDraw/App/DrawViewDraft.cpp @@ -126,7 +126,8 @@ App::DocumentObjectExecReturn *DrawViewDraft::execute() Base::Interpreter().runStringArg("App.activeDocument().%s.Symbol = '%s' + svgBody + '%s'", FeatName.c_str(),svgHead.c_str(),svgTail.c_str()); } -// requestPaint(); + + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawViewImage.cpp b/src/Mod/TechDraw/App/DrawViewImage.cpp index 92a314ef9a..b62cac2501 100644 --- a/src/Mod/TechDraw/App/DrawViewImage.cpp +++ b/src/Mod/TechDraw/App/DrawViewImage.cpp @@ -111,7 +111,7 @@ QRectF DrawViewImage::getRect() const void DrawViewImage::replaceImageIncluded(std::string newFileName) { - Base::Console().Message("DVI::replaceImageIncluded(%s)\n", newFileName.c_str()); +// Base::Console().Message("DVI::replaceImageIncluded(%s)\n", newFileName.c_str()); if (ImageIncluded.isEmpty()) { setupImageIncluded(); } else { @@ -123,7 +123,7 @@ void DrawViewImage::replaceImageIncluded(std::string newFileName) void DrawViewImage::setupImageIncluded() { - Base::Console().Message("DVI::setupImageIncluded()\n"); +// Base::Console().Message("DVI::setupImageIncluded()\n"); App::Document* doc = getDocument(); std::string dir = doc->TransientDir.getValue(); std::string special = getNameInDocument(); diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index 09a3f5c9d5..02761ed1fb 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -26,60 +26,36 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include - -#include "QtConcurrent/qtconcurrentrun.h" - #include -#include -#include +#include #include #include #include #include #include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include #include #include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include #include #include -#include #include #include #include #include -#include - -#include - #endif #include #include #include +#include + +#include #include #include @@ -90,11 +66,11 @@ #include #include #include -#include -#include -#include -#include "Preferences.h" +#include +#include +#include + #include "Cosmetic.h" #include "DrawGeomHatch.h" #include "DrawHatch.h" @@ -104,15 +80,16 @@ #include "DrawViewBalloon.h" #include "DrawViewDetail.h" #include "DrawViewDimension.h" -#include "LandmarkDimension.h" -#include "DrawViewPart.h" #include "DrawViewSection.h" #include "EdgeWalker.h" #include "Geometry.h" #include "GeometryObject.h" +#include "LandmarkDimension.h" #include "LineGroup.h" +#include "Preferences.h" #include "ShapeExtractor.h" +#include "DrawViewPart.h" #include // generated from DrawViewPartPy.xml using namespace TechDraw; @@ -160,10 +137,9 @@ DrawViewPart::DrawViewPart(void) : "Perspective(true) or Orthographic(false) projection"); ADD_PROPERTY_TYPE(Focus,(defDist),group,App::Prop_None,"Perspective view focus distance"); - //properties that control HLR algoaffect Appearance + //properties that control HLR algo bool coarseView = hGrp->GetBool("CoarseView", false); ADD_PROPERTY_TYPE(CoarseView, (coarseView), sgroup, App::Prop_None, "Coarse View on/off"); - //add property for visible outline? ADD_PROPERTY_TYPE(SmoothVisible ,(prefSmoothViz()),sgroup,App::Prop_None,"Show Visible Smooth lines"); ADD_PROPERTY_TYPE(SeamVisible ,(prefSeamViz()),sgroup,App::Prop_None,"Show Visible Seam lines"); ADD_PROPERTY_TYPE(IsoVisible ,(prefIsoViz()),sgroup,App::Prop_None,"Show Visible Iso u,v lines"); @@ -173,7 +149,6 @@ DrawViewPart::DrawViewPart(void) : ADD_PROPERTY_TYPE(IsoHidden ,(prefIsoHid()),sgroup,App::Prop_None,"Show Hidden Iso u,v lines"); ADD_PROPERTY_TYPE(IsoCount ,(prefIsoCount()),sgroup,App::Prop_None,"Number of iso parameters lines"); - geometryObject = nullptr; //initialize bbox to non-garbage bbox = Base::BoundBox3d(Base::Vector3d(0.0, 0.0, 0.0), 0.0); } @@ -193,55 +168,31 @@ std::vector DrawViewPart::getSourceShape2d() const return result; } - TopoDS_Shape DrawViewPart::getSourceShape() const { // Base::Console().Message("DVP::getSourceShape()\n"); - TopoDS_Shape result; const std::vector& links = getAllSources(); - if (links.empty()) { - bool isRestoring = getDocument()->testStatus(App::Document::Status::Restoring); - if (isRestoring) { - Base::Console().Warning("DVP::getSourceShape - No Sources (but document is restoring) - %s\n", - getNameInDocument()); - } else { - Base::Console().Error("Error: DVP::getSourceShape - No Source(s) linked. - %s\n", - getNameInDocument()); - } - } else { - result = ShapeExtractor::getShapes(links); + if (!links.empty()) { + return ShapeExtractor::getShapes(links); } - return result; + return TopoDS_Shape(); } TopoDS_Shape DrawViewPart::getSourceShapeFused() const { // Base::Console().Message("DVP::getSourceShapeFused()\n"); - TopoDS_Shape result; -// const std::vector& links = Source.getValues(); const std::vector& links = getAllSources(); - if (links.empty()) { - bool isRestoring = getDocument()->testStatus(App::Document::Status::Restoring); - if (isRestoring) { - Base::Console().Warning("DVP::getSourceShape - No Sources (but document is restoring) - %s\n", - getNameInDocument()); - } else { - Base::Console().Error("Error: DVP::getSourceShape - No Source(s) linked. - %s\n", - getNameInDocument()); - } - } else { - result = ShapeExtractor::getShapesFused(links); + if (!links.empty()) { + return ShapeExtractor::getShapesFused(links); } - return result; + return TopoDS_Shape(); } std::vector DrawViewPart::getAllSources() const { // Base::Console().Message("DVP::getAllSources()\n"); - const std::vector links = Source.getValues(); + std::vector links = Source.getValues(); std::vector xLinks = XSource.getValues(); -// std::vector xLinks; -// XSource.getLinks(xLinks); std::vector result = links; if (!xLinks.empty()) { @@ -250,6 +201,8 @@ std::vector DrawViewPart::getAllSources() const return result; } +//pick supported 2d shapes out of the Source properties and +//add them directly to the geometry without going through HLR void DrawViewPart::addShapes2d(void) { std::vector shapes = getSourceShape2d(); @@ -285,20 +238,13 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void) // Base::Console().Message("DVP::execute() - %s\n", getNameInDocument()); if (!keepUpdated()) { - return App::DocumentObject::StdReturn; + return DrawView::execute(); } - if (waitingForResult()) { + if (waitingForHlr()) { return DrawView::execute(); } - const std::vector& links = getAllSources(); - if (links.empty()) { - Base::Console().Log("DVP::execute - %s - No Source(s) linked.\n", - getNameInDocument()); - return DrawView::execute(); - } - TopoDS_Shape shape = getSourceShape(); if (shape.IsNull()) { Base::Console().Log("DVP::execute - %s - Source shape is Null.\n", @@ -306,58 +252,46 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void) return DrawView::execute(); } + //make sure the XDirection property is valid. Mostly for older models. if (!checkXDirection()) { - //block touch/onChanged stuff Base::Vector3d newX = getXDirection(); XDirection.setValue(newX); XDirection.purgeTouched(); //don't trigger updates! - //unblock } m_saveShape = shape; partExec(shape); - addShapes2d(); - - //second pass if required - if (ScaleType.isValue("Automatic")) { - if (!checkFit()) { - double newScale = autoScale(); - Scale.setValue(newScale); - Scale.purgeTouched(); - partExec(shape); - } - } return DrawView::execute(); } short DrawViewPart::mustExecute() const { - short result = 0; - if (!isRestoring()) { - result = (Direction.isTouched() || - Source.isTouched() || - XSource.isTouched() || - Perspective.isTouched() || - Focus.isTouched() || - Rotation.isTouched() || - SmoothVisible.isTouched() || - SeamVisible.isTouched() || - IsoVisible.isTouched() || - HardHidden.isTouched() || - SmoothHidden.isTouched() || - SeamHidden.isTouched() || - IsoHidden.isTouched() || - IsoCount.isTouched() || - CoarseView.isTouched() || - CosmeticVertexes.isTouched() || - CosmeticEdges.isTouched() || - CenterLines.isTouched()); + if (isRestoring()) { + return TechDraw::DrawView::mustExecute(); } - if (result) { - return result; + if (Direction.isTouched() || + Source.isTouched() || + XSource.isTouched() || + Perspective.isTouched() || + Focus.isTouched() || + Rotation.isTouched() || + SmoothVisible.isTouched() || + SeamVisible.isTouched() || + IsoVisible.isTouched() || + HardHidden.isTouched() || + SmoothHidden.isTouched() || + SeamHidden.isTouched() || + IsoHidden.isTouched() || + IsoCount.isTouched() || + CoarseView.isTouched() || + CosmeticVertexes.isTouched() || + CosmeticEdges.isTouched() || + CenterLines.isTouched()) { + return 1; } + return TechDraw::DrawView::mustExecute(); } @@ -377,8 +311,7 @@ void DrawViewPart::partExec(TopoDS_Shape& shape) { // Base::Console().Message("DVP::partExec()\n"); if (waitingForHlr()) { - //finish what we are already doing before starting over -// Base::Console().Message("DVP::partExec - %s - waiting for HLR\n", getNameInDocument()); + //finish what we are already doing before starting a new cycle return; } @@ -386,13 +319,18 @@ void DrawViewPart::partExec(TopoDS_Shape& shape) delete geometryObject; geometryObject = nullptr; } + geometryObject = makeGeometryForShape(shape); + if (CoarseView.getValue()){ + onHlrFinished(); //poly algo does not run in separate thread, so we need to invoke + //the post hlr processing manually + } } +//prepare the shape for HLR processing by centering, scaling and rotating it GeometryObject* DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape) { // Base::Console().Message("DVP::makeGeometryForShape()\n"); -// BRepTools::Write(shape, "DVPShape.brep"); //debug gp_Pnt inputCenter; Base::Vector3d stdOrg(0.0,0.0,0.0); gp_Ax2 viewAxis = getProjectionCS(stdOrg); @@ -420,11 +358,12 @@ GeometryObject* DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape) return go; } -//note: slightly different than routine with same name in DrawProjectSplit +//create a geometry object and trigger the HLR process in another thread TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, gp_Ax2& viewAxis) { // Base::Console().Message("DVP::buildGeometryObject() - %s\n", getNameInDocument()); showProgressMessage(getNameInDocument(), "is finding hidden lines"); + TechDraw::GeometryObject* go = new TechDraw::GeometryObject(getNameInDocument(), this); go->setIsoCount(IsoCount.getValue()); go->isPerspective(Perspective.getValue()); @@ -432,12 +371,12 @@ TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, go->usePolygonHLR(CoarseView.getValue()); if (CoarseView.getValue()){ + //the polygon approximation HLR process runs quickly, so doesn't need to be in a + //separate thread go->projectShapeWithPolygonAlgo(shape, viewAxis); - onHlrFinished(); //poly algo does not run in separate thread, so we need to invoke - //the post hlr processing manually } else { - //project shape runs in a separate thread since if can take a long time + //projectShape (the HLR process) runs in a separate thread since it can take a long time QObject::connect(&m_hlrWatcher, SIGNAL(finished()), this, SLOT(onHlrFinished())); m_hlrFuture = QtConcurrent::run(go, &GeometryObject::projectShape, shape, viewAxis); m_hlrWatcher.setFuture(m_hlrFuture); @@ -450,21 +389,23 @@ TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, void DrawViewPart::onHlrFinished(void) { // Base::Console().Message("DVP::onHlrFinished() - %s\n", getNameInDocument()); - //the last hlr task is to make a bbox of the results + //the last hlr related task is to make a bbox of the results bbox = geometryObject->calcBoundingBox(); waitingForHlr(false); QObject::disconnect(&m_hlrWatcher, SIGNAL(finished()), this, SLOT(onHlrFinished())); showProgressMessage(getNameInDocument(), "has finished finding hidden lines"); - postHlrTasks(); + postHlrTasks(); //application level tasks that depend on HLR/GO being complete - //start face finding in a separate thread + //start face finding in a separate thread. We don't find faces when using the polygon + //HLR method if (handleFaces() && !CoarseView.getValue() && !waitingForFaces()) { try { QObject::connect(&m_faceWatcher, SIGNAL(finished()), this, SLOT(onFacesFinished())); m_faceFuture = QtConcurrent::run(this, &DrawViewPart::extractFaces); m_faceWatcher.setFuture(m_faceFuture); + waitingForFaces(true); } catch (Standard_Failure& e) { waitingForFaces(false); @@ -483,6 +424,7 @@ void DrawViewPart::postHlrTasks(void) addCosmeticEdgesToGeom(); addCenterLinesToGeom(); addReferencesToGeom(); + addShapes2d(); //dimensions and balloons need to be recomputed here because their //references will be invalid until the geometry exists @@ -495,42 +437,49 @@ void DrawViewPart::postHlrTasks(void) b->recomputeFeature(); } + //second pass if required + if (ScaleType.isValue("Automatic")) { + if (!checkFit()) { + double newScale = autoScale(); + Scale.setValue(newScale); + Scale.purgeTouched(); + partExec(m_saveShape); + } + } + + overrideKeepUpdated(false); + requestPaint(); } -//! make faces from the existing edge geometry +//! make faces from the edge geometry void DrawViewPart::extractFaces() { // Base::Console().Message("DVP::extractFaces()\n"); - - if (!geometryObject) { + if (!geometryObject || + !this->hasGeometry()) { //no geometry yet so don't bother return; } - waitingForFaces(true); showProgressMessage(getNameInDocument(), "is extracting faces"); geometryObject->clearFaceGeom(); const std::vector& goEdges = geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue()); - std::vector::const_iterator itEdge = goEdges.begin(); //make a copy of the input edges so the loose tolerances of face finding are //not applied to the real edge geometry. See TopoDS_Shape::TShape(). std::vector copyEdges; - for (;itEdge != goEdges.end(); itEdge++) { - BRepBuilderAPI_Copy copier((*itEdge)->occEdge, true, true); + for (auto& tdEdge: goEdges) { + BRepBuilderAPI_Copy copier(tdEdge->occEdge, true, true); //copy occEdge with its geometry (TShape) and mesh info copyEdges.push_back(TopoDS::Edge(copier.Shape())); } - std::vector faceEdges; std::vector nonZero; for (auto& e:copyEdges) { //drop any zero edges (shouldn't be any by now!!!) if (!DrawUtil::isZeroEdge(e)) { nonZero.push_back(e); - } else { - Base::Console().Log("INFO - DVP::extractFaces for %s found ZeroEdge!\n",getNameInDocument()); } } @@ -539,18 +488,16 @@ void DrawViewPart::extractFaces() std::vector splits; std::vector::iterator itOuter = nonZero.begin(); int iOuter = 0; - for (; itOuter != nonZero.end(); ++itOuter, iOuter++) { //*** itOuter != nonZero.end() - 1 + for (; itOuter != nonZero.end(); ++itOuter, iOuter++) { TopoDS_Vertex v1 = TopExp::FirstVertex((*itOuter)); TopoDS_Vertex v2 = TopExp::LastVertex((*itOuter)); Bnd_Box sOuter; BRepBndLib::AddOptimal(*itOuter, sOuter); sOuter.SetGap(0.1); if (sOuter.IsVoid()) { - Base::Console().Log("DVP::Extract Faces - outer Bnd_Box is void for %s\n",getNameInDocument()); continue; } if (DrawUtil::isZeroEdge(*itOuter)) { - Base::Console().Log("DVP::extractFaces - outerEdge: %d is ZeroEdge\n",iOuter); //this is not finding ZeroEdges continue; //skip zero length edges. shouldn't happen ;) } int iInner = 0; @@ -567,14 +514,13 @@ void DrawViewPart::extractFaces() BRepBndLib::AddOptimal(*itInner, sInner); sInner.SetGap(0.1); if (sInner.IsVoid()) { - Base::Console().Log("INFO - DVP::Extract Faces - inner Bnd_Box is void for %s\n",getNameInDocument()); continue; } if (sOuter.IsOut(sInner)) { //bboxes of edges don't intersect, don't bother continue; } - double param = -1; + double param = -1; //parametric point on edge where the vertex touches if (DrawProjectSplit::isOnEdge((*itInner),v1,param,false)) { gp_Pnt pnt1 = BRep_Tool::Pnt(v1); splitPoint s1; @@ -594,17 +540,20 @@ void DrawViewPart::extractFaces() } //inner loop } //outer loop + //if edge A was touched at the same point by multiple edges B, we only want to split A once std::vector sorted = DrawProjectSplit::sortSplits(splits,true); auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual); //duplicates to back - sorted.erase(last, sorted.end()); //remove dupl splits + sorted.erase(last, sorted.end()); //remove duplicate splits + std::vector newEdges = DrawProjectSplit::splitEdges(nonZero,sorted); if (newEdges.empty()) { - Base::Console().Log("DVP::extractFaces - no newEdges\n"); + Base::Console().Log("DVP::extractFaces - no edges return by splitting process\n"); waitingForFaces(false); return; } + //try to remove any duplicated edges since they will confuse the edgeWalker newEdges = DrawProjectSplit::removeDuplicateEdges(newEdges); //find all the wires in the pile of faceEdges @@ -612,7 +561,7 @@ void DrawViewPart::extractFaces() ew.loadEdges(newEdges); bool success = ew.perform(); if (!success) { - Base::Console().Warning("DVP::extractFaces - %s -Can't make faces from projected edges\n", getNameInDocument()); + Base::Console().Warning("DVP::extractFaces - %s - Can't make faces from projected edges\n", getNameInDocument()); waitingForFaces(false); return; } @@ -620,23 +569,19 @@ void DrawViewPart::extractFaces() std::vector sortedWires = ew.sortStrip(fw,true); -// int idb = 0; std::vector::iterator itWire = sortedWires.begin(); for (; itWire != sortedWires.end(); itWire++) { //version 1: 1 wire/face - no voids in face -//debug -// std::stringstream ss; -// ss << "DVPSWire" << idb << ".brep"; -// std::string wireName = ss.str(); -// BRepTools::Write((*itWire), wireName.c_str()); //debug -//debug idb++; TechDraw::FacePtr f(std::make_shared()); const TopoDS_Wire& wire = (*itWire); TechDraw::Wire* w = new TechDraw::Wire(wire); f->wires.push_back(w); - geometryObject->addFaceGeom(f); + if (geometryObject) { + //it can happen that a new hlr cycle deletes geometryObject while we are + //extracting faces. if it does happen, a new cycle should fix it. + geometryObject->addFaceGeom(f); + } } - waitingForFaces(false); } //continue processing after extractFaces thread completes @@ -649,28 +594,30 @@ void DrawViewPart::onFacesFinished(void) requestPaint(); } +//retrieve all the face hatches associated with this dvp std::vector DrawViewPart::getHatches() const { std::vector result; std::vector children = getInList(); - for (std::vector::iterator it = children.begin(); it != children.end(); ++it) { - if ( ((*it)->getTypeId().isDerivedFrom(DrawHatch::getClassTypeId())) && - (!(*it)->isRemoving()) ) { - TechDraw::DrawHatch* hatch = dynamic_cast(*it); + for (auto& child: children) { + if ( (child->getTypeId().isDerivedFrom(DrawHatch::getClassTypeId())) && + (!child->isRemoving()) ) { + TechDraw::DrawHatch* hatch = dynamic_cast(child); result.push_back(hatch); } } return result; } +//retrieve all the geometric hatches associated with this dvp std::vector DrawViewPart::getGeomHatches() const { std::vector result; std::vector children = getInList(); - for (std::vector::iterator it = children.begin(); it != children.end(); ++it) { - if ( ((*it)->getTypeId().isDerivedFrom(DrawGeomHatch::getClassTypeId())) && - (!(*it)->isRemoving()) ) { - TechDraw::DrawGeomHatch* geom = dynamic_cast(*it); + for (auto& child: children) { + if ( (child->getTypeId().isDerivedFrom(DrawGeomHatch::getClassTypeId())) && + (!child->isRemoving()) ) { + TechDraw::DrawGeomHatch* geom = dynamic_cast(child); result.push_back(geom); } } @@ -678,6 +625,8 @@ std::vector DrawViewPart::getGeomHatches() const } //return *unique* list of Dimensions which reference this DVP +//if the dimension has two references to this dvp, it will appear twice in +//the inlist std::vector DrawViewPart::getDimensions() const { std::vector result; @@ -892,35 +841,31 @@ BaseGeomPtr DrawViewPart::projectEdge(const TopoDS_Edge& e) const bool DrawViewPart::waitingForResult() const { - bool result(false); - if (waitingForHlr()) { - result = true; + if (waitingForHlr() || + waitingForFaces()) { + return true; } -// if (waitingForFaces()) { -// result = true; -// } - return result; + return false; } bool DrawViewPart::hasGeometry(void) const { - bool result = false; if (!geometryObject) { - return result; + return false; } - if (waitingForResult()) { - return result; + if (waitingForHlr()) { + return false; } const std::vector &verts = getVertexGeometry(); const std::vector &edges = getEdgeGeometry(); if (verts.empty() && edges.empty() ) { - result = false; + return false; } else { - result = true; + return true; } - return result; + return false; } gp_Ax2 DrawViewPart::getProjectionCS(const Base::Vector3d pt) const diff --git a/src/Mod/TechDraw/App/DrawViewPart.h b/src/Mod/TechDraw/App/DrawViewPart.h index a4a50f0348..ded3ee5853 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.h +++ b/src/Mod/TechDraw/App/DrawViewPart.h @@ -209,7 +209,7 @@ public: void waitingForFaces(bool s) { m_waitingForFaces = s;} bool waitingForHlr() const { return m_waitingForHlr; } void waitingForHlr(bool s) { m_waitingForHlr = s; } - bool waitingForResult() const; + virtual bool waitingForResult() const; void progressValueChanged(int v); diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 07a5d062d3..b722e0d9a0 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -26,32 +26,22 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include - #include #include -//#include #include #include #include #include #include -#include #include #include #include -#include #include #include #include #include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -60,14 +50,14 @@ #include #include #include - #endif #include +#include #include #include -#include "QtConcurrent/qtconcurrentrun.h" +#include #include #include @@ -163,123 +153,61 @@ DrawViewSection::~DrawViewSection() short DrawViewSection::mustExecute() const { - short result = 0; - if (!isRestoring()) { - result = (Scale.isTouched() || - Direction.isTouched() || - BaseView.isTouched() || - SectionNormal.isTouched() || - SectionOrigin.isTouched() ); + if (isRestoring()) { + return TechDraw::DrawView::mustExecute(); } - if (result) { - return result; + + if (Scale.isTouched() || + Direction.isTouched() || + BaseView.isTouched() || + SectionNormal.isTouched() || + SectionOrigin.isTouched() ) { + return 1; } + return TechDraw::DrawView::mustExecute(); } void DrawViewSection::onChanged(const App::Property* prop) { - App::Document* doc = getDocument(); - if (!isRestoring()) { - if (prop == &SectionSymbol) { - std::string lblText = "Section " + - std::string(SectionSymbol.getValue()) + - " - " + - std::string(SectionSymbol.getValue()); - Label.setValue(lblText); - } else if (prop == &SectionOrigin) { - App::DocumentObject* base = BaseView.getValue(); - TechDraw::DrawView* dv = dynamic_cast(base); - if (dv) { - dv->requestPaint(); - } - } else if (prop == &CutSurfaceDisplay) { - if (CutSurfaceDisplay.isValue("PatHatch")) { - makeLineSets(); - } - } - - if ((prop == &FileHatchPattern) && doc) { - if (!FileHatchPattern.isEmpty()) { - Base::FileInfo fi(FileHatchPattern.getValue()); - if (fi.isReadable()) { - replaceSvgIncluded(FileHatchPattern.getValue()); - } - } - } - - if ((prop == &FileGeomPattern) && doc) { - if (!FileGeomPattern.isEmpty()) { - Base::FileInfo fi(FileGeomPattern.getValue()); - if (fi.isReadable()) { - replacePatIncluded(FileGeomPattern.getValue()); - } - } - } + if (isRestoring()) { + DrawView::onChanged(prop); + return; } - if (prop == &FileGeomPattern || + App::Document* doc = getDocument(); + if (prop == &SectionSymbol) { + std::string lblText = "Section " + + std::string(SectionSymbol.getValue()) + + " - " + + std::string(SectionSymbol.getValue()); + Label.setValue(lblText); + } else if (prop == &CutSurfaceDisplay) { + if (CutSurfaceDisplay.isValue("PatHatch")) { + makeLineSets(); + } + } else if ((prop == &FileHatchPattern) && doc) { + if (!FileHatchPattern.isEmpty()) { + Base::FileInfo fi(FileHatchPattern.getValue()); + if (fi.isReadable()) { + replaceSvgIncluded(FileHatchPattern.getValue()); + } + } + } else if ((prop == &FileGeomPattern) && doc) { + if (!FileGeomPattern.isEmpty()) { + Base::FileInfo fi(FileGeomPattern.getValue()); + if (fi.isReadable()) { + replacePatIncluded(FileGeomPattern.getValue()); + } + } + } else if (prop == &FileGeomPattern || prop == &NameGeomPattern ) { makeLineSets(); } + DrawView::onChanged(prop); } -void DrawViewSection::makeLineSets() -{ -// Base::Console().Message("DVS::makeLineSets()\n"); - if (!PatIncluded.isEmpty()) { - std::string fileSpec = PatIncluded.getValue(); - Base::FileInfo fi(fileSpec); - std::string ext = fi.extension(); - if (!fi.isReadable()) { - Base::Console().Message("%s can not read hatch file: %s\n", getNameInDocument(), fileSpec.c_str()); - } else { - if ( (ext == "pat") || - (ext == "PAT") ) { - if ((!fileSpec.empty()) && - (!NameGeomPattern.isEmpty())) { - std::vector specs = - DrawGeomHatch::getDecodedSpecsFromFile(fileSpec, - NameGeomPattern.getValue()); - m_lineSets.clear(); - for (auto& hl: specs) { - //hl.dump("hl from section"); - LineSet ls; - ls.setPATLineSpec(hl); - m_lineSets.push_back(ls); - } - } - } - } - } -} - -//this could probably always use FileHatchPattern as input? -void DrawViewSection::replaceSvgIncluded(std::string newSvgFile) -{ -// Base::Console().Message("DVS::replaceSvgHatch(%s)\n", newSvgFile.c_str()); - if (SvgIncluded.isEmpty()) { - setupSvgIncluded(); - } else { - std::string tempName = SvgIncluded.getExchangeTempFile(); - DrawUtil::copyFile(newSvgFile, tempName); - SvgIncluded.setValue(tempName.c_str()); - } -} - -void DrawViewSection::replacePatIncluded(std::string newPatFile) -{ -// Base::Console().Message("DVS::replacePatHatch(%s)\n", newPatFile.c_str()); - if (PatIncluded.isEmpty()) { - setupPatIncluded(); - } else { - std::string tempName = PatIncluded.getExchangeTempFile(); - DrawUtil::copyFile(newPatFile, tempName); - PatIncluded.setValue(tempName.c_str()); - } -} - App::DocumentObjectExecReturn *DrawViewSection::execute() { if (!keepUpdated()) { @@ -293,22 +221,23 @@ App::DocumentObjectExecReturn *DrawViewSection::execute() TechDraw::DrawViewPart* dvp = nullptr; if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { + //this can probably only happen with scripting return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object"); } else { dvp = static_cast(base); } - TopoDS_Shape baseShape; + TopoDS_Shape baseShape = dvp->getSourceShape(); if (FuseBeforeCut.getValue()) { baseShape = dvp->getSourceShapeFused(); - } else { - baseShape = dvp->getSourceShape(); } if (baseShape.IsNull()) { return DrawView::execute(); } + m_saveShape = baseShape; //save shape for 2nd pass + // checkXDirection(); bool haveX = checkXDirection(); if (!haveX) { @@ -322,20 +251,6 @@ App::DocumentObjectExecReturn *DrawViewSection::execute() sectionExec(baseShape); addShapes2d(); - //second pass if required - if (ScaleType.isValue("Automatic")) { - if (!checkFit()) { - double newScale = autoScale(); - Scale.setValue(newScale); - Scale.purgeTouched(); - if (geometryObject) { - delete geometryObject; - geometryObject = nullptr; - sectionExec(baseShape); - } - } - } - return DrawView::execute(); } @@ -344,7 +259,8 @@ void DrawViewSection::sectionExec(TopoDS_Shape& baseShape) // Base::Console().Message("DVS::sectionExec() - %s baseShape.IsNull: %d\n", // getNameInDocument(), baseShape.IsNull()); - if (waitingForCut()) { + if (waitingForHlr() || + waitingForCut()) { return; } @@ -352,11 +268,16 @@ void DrawViewSection::sectionExec(TopoDS_Shape& baseShape) //should be caught before this return; } + if (geometryObject) { + delete geometryObject; + geometryObject = nullptr; + } try { QObject::connect(&m_cutWatcher, SIGNAL(finished()), this, SLOT(onSectionCutFinished())); m_cutFuture = QtConcurrent::run(this, &DrawViewSection::makeSectionCut, baseShape); m_cutWatcher.setFuture(m_cutFuture); + waitingForCut(true); } catch (...) { Base::Console().Message("DVS::sectionExec - failed to make section cut"); @@ -369,7 +290,6 @@ void DrawViewSection::makeSectionCut(TopoDS_Shape &baseShape) // Base::Console().Message("DVS::makeSectionCut() - %s - baseShape.IsNull: %d\n", // getNameInDocument(), baseShape.IsNull()); - waitingForCut(true); showProgressMessage(getNameInDocument(), "is making section cut"); // cut base shape with tool @@ -400,6 +320,7 @@ void DrawViewSection::makeSectionCut(TopoDS_Shape &baseShape) // We need to copy the shape to not modify the BRepstructure BRepBuilderAPI_Copy BuilderCopy(baseShape); TopoDS_Shape myShape = BuilderCopy.Shape(); + m_saveShape = myShape; //save shape for 2nd pass // perform cut BRep_Builder builder; @@ -502,11 +423,24 @@ void DrawViewSection::postHlrTasks(void) { // Base::Console().Message("DVS::postHlrTasks() - %s\n", getNameInDocument()); + DrawViewPart::postHlrTasks(); + + //second pass if required + if (ScaleType.isValue("Automatic")) { + if (!checkFit()) { + double newScale = autoScale(); + Scale.setValue(newScale); + Scale.purgeTouched(); + sectionExec(m_saveShape); + } + } + overrideKeepUpdated(false); + + // build section face geometry TopoDS_Compound faceIntersections = findSectionPlaneIntersections(m_rawShape); if (faceIntersections.IsNull()) { requestPaint(); - DrawViewPart::postHlrTasks(); return; } @@ -536,32 +470,25 @@ void DrawViewSection::postHlrTasks(void) BRepBuilderAPI_Transform xformer(fromR3); xformer.Perform(scaledSection, true); if (xformer.IsDone()) { - sectionFaces = TopoDS::Compound(xformer.Shape()); -// BRepTools::Write(sectionFaces, "DVSXFaces.brep"); //debug + sectionTopoDSFaces = TopoDS::Compound(xformer.Shape()); } else { Base::Console().Message("DVS::sectionExec - face xform failed\n"); } - sectionFaces = TopoDS::Compound(GeometryObject::invertGeometry(sectionFaces)); //handle Qt -y + sectionTopoDSFaces = TopoDS::Compound(GeometryObject::invertGeometry(sectionTopoDSFaces)); //handle Qt -y - //turn section faces into something we can draw + //turn section faces into TD geometry tdSectionFaces.clear(); - TopExp_Explorer sectionExpl(sectionFaces, TopAbs_FACE); - int iface = 0; + TopExp_Explorer sectionExpl(sectionTopoDSFaces, TopAbs_FACE); for (; sectionExpl.More(); sectionExpl.Next()) { - iface++; const TopoDS_Face& face = TopoDS::Face(sectionExpl.Current()); TechDraw::FacePtr sectionFace(std::make_shared()); TopExp_Explorer expFace(face, TopAbs_WIRE); - int iwire = 0; for ( ; expFace.More(); expFace.Next()) { - iwire++; TechDraw::Wire* w = new TechDraw::Wire(); const TopoDS_Wire& wire = TopoDS::Wire(expFace.Current()); - int iedge = 0; TopExp_Explorer expWire(wire, TopAbs_EDGE); for ( ; expWire.More(); expWire.Next()) { - iedge++; const TopoDS_Edge& edge = TopoDS::Edge(expWire.Current()); TechDraw::BaseGeomPtr e = BaseGeom::baseFactory(edge); if (e) { @@ -573,15 +500,11 @@ void DrawViewSection::postHlrTasks(void) tdSectionFaces.push_back(sectionFace); } - App::DocumentObject* base = BaseView.getValue(); - if (base != nullptr) { - if (base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { - TechDraw::DrawViewPart* dvp = static_cast(base); - dvp->requestPaint(); //to refresh section line - } + TechDraw::DrawViewPart* dvp = dynamic_cast(BaseView.getValue()); + if (dvp) { + dvp->requestPaint(); //to refresh section line } requestPaint(); - DrawViewPart::postHlrTasks(); } //activities that depend on a valid section cut @@ -590,12 +513,21 @@ void DrawViewSection::postSectionCutTasks() std::vector children = getInList(); for (auto& c: children) { if (c->getTypeId().isDerivedFrom(DrawViewPart::getClassTypeId())) { - //details or sections need cut shape + //details or sections of this need cut shape c->recomputeFeature(); } } } +bool DrawViewSection::waitingForResult() const +{ + if (DrawViewPart::waitingForResult() || + waitingForCut()) { + return true; + } + return false; +} + gp_Pln DrawViewSection::getSectionPlane() const { gp_Ax2 viewAxis = getSectionCS(); @@ -604,14 +536,12 @@ gp_Pln DrawViewSection::getSectionPlane() const return gp_Pln(viewAxis3); } - //! tries to find the intersection of the section plane with the shape giving a collection of planar faces TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shape& shape) { // Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument()); if(shape.IsNull()){ - //a) this shouldn't happen - //b) if it does, we should throw something + // this shouldn't happen Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument()); return TopoDS_Compound(); } @@ -622,22 +552,17 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap builder.MakeCompound(result); TopExp_Explorer expFaces(shape, TopAbs_FACE); - int i; - int dbAdded = 0; - for (i = 1 ; expFaces.More(); expFaces.Next(), i++) { + for ( ; expFaces.More(); expFaces.Next()) { const TopoDS_Face& face = TopoDS::Face(expFaces.Current()); BRepAdaptor_Surface adapt(face); if (adapt.GetType() == GeomAbs_Plane){ gp_Pln plnFace = adapt.Plane(); - if(plnSection.Contains(plnFace.Location(), Precision::Confusion()) && plnFace.Axis().IsParallel(plnSection.Axis(), Precision::Angular())) { - dbAdded++; builder.Add(result, face); } } } -// BRepTools::Write(result, "DVSIntersect.brep"); //debug return result; } @@ -646,34 +571,32 @@ std::pair DrawViewSection::sectionLineEnds() { std::pair result; Base::Vector3d stdZ(0.0, 0.0, 1.0); - double baseRotation = getBaseDVP()->Rotation.getValue(); //Qt degrees + double baseRotation = getBaseDVP()->Rotation.getValue(); //Qt degrees are clockwise Base::Rotation rotator(stdZ, baseRotation * M_PI / 180.0); Base::Rotation unrotator(stdZ, - baseRotation * M_PI / 180.0); auto sNorm = SectionNormal.getValue(); - double angle = M_PI / 2.0; auto axis = getBaseDVP()->Direction.getValue(); Base::Vector3d stdOrg(0.0, 0.0, 0.0); - Base::Vector3d sLineDir = DrawUtil::vecRotate(sNorm, angle, axis, stdOrg); - sLineDir.Normalize(); - Base::Vector3d sLineDir2 = - axis.Cross(sNorm); - sLineDir2.Normalize(); - Base::Vector3d sLineOnBase = getBaseDVP()->projectPoint(sLineDir2); - sLineOnBase.Normalize(); + Base::Vector3d sectionLineDir = - axis.Cross(sNorm); + sectionLineDir.Normalize(); + sectionLineDir = getBaseDVP()->projectPoint(sectionLineDir); //convert to base view CS + sectionLineDir.Normalize(); - auto sOrigin = SectionOrigin.getValue(); - Base::Vector3d adjSectionOrg = sOrigin - getBaseDVP()->getOriginalCentroid(); - Base::Vector3d sOrgOnBase = getBaseDVP()->projectPoint(adjSectionOrg); + Base::Vector3d sectionOrg = SectionOrigin.getValue() - getBaseDVP()->getOriginalCentroid(); + sectionOrg = getBaseDVP()->projectPoint(sectionOrg); //convert to base view CS + //get the unscaled X and Y ranges of the base view geometry auto bbx = getBaseDVP()->getBoundingBox(); double xRange = bbx.MaxX - bbx.MinX; xRange /= getBaseDVP()->getScale(); double yRange = bbx.MaxY - bbx.MinY; yRange /= getBaseDVP()->getScale(); - sOrgOnBase = rotator.multVec(sOrgOnBase); - sLineOnBase = rotator.multVec(sLineOnBase); - result = DrawUtil::boxIntersect2d(sOrgOnBase, sLineOnBase, xRange, yRange); //unscaled + sectionOrg = rotator.multVec(sectionOrg); + sectionLineDir = rotator.multVec(sectionLineDir); + + result = DrawUtil::boxIntersect2d(sectionOrg, sectionLineDir, xRange, yRange); //unscaled result.first = unrotator.multVec(result.first); result.second = unrotator.multVec(result.second); @@ -704,26 +627,26 @@ Base::Vector3d DrawViewSection::getXDirection() const // Base::Console().Message("DVS::getXDirection() - %s\n", Label.getValue()); Base::Vector3d result(1.0, 0.0, 0.0); //default X App::Property* prop = getPropertyByName("XDirection"); - if (prop) { //have an XDirection property - Base::Vector3d propVal = XDirection.getValue(); - if (DrawUtil::fpCompare(propVal.Length(), 0.0)) { //but it has no value - std::string sectName = SectionDirection.getValueAsString(); - gp_Ax2 cs = getCSFromBase(sectName); + if (prop) { + //we have an XDirection property + if (DrawUtil::fpCompare(XDirection.getValue().Length(), 0.0)) { + //but it has no value, so we make a value + gp_Ax2 cs = getCSFromBase(SectionDirection.getValueAsString()); gp_Dir gXDir = cs.XDirection(); result = Base::Vector3d(gXDir.X(), gXDir.Y(), gXDir.Z()); } else { - result = propVal; //normal case. XDirection is set. + //XDirection is good, so we use it + result = XDirection.getValue(); } - } else { //no Property. can this happen? - std::string sectName = SectionDirection.getValueAsString(); - gp_Ax2 cs = getCSFromBase(sectName); - gp_Dir gXDir = cs.XDirection(); - result = Base::Vector3d(gXDir.X(), - gXDir.Y(), - gXDir.Z()); - + } else { + //no XDirection property. can this happen? + gp_Ax2 cs = getCSFromBase(SectionDirection.getValueAsString()); + gp_Dir gXDir = cs.XDirection(); + result = Base::Vector3d(gXDir.X(), + gXDir.Y(), + gXDir.Z()); } return result; } @@ -731,14 +654,13 @@ Base::Vector3d DrawViewSection::getXDirection() const void DrawViewSection::setCSFromBase(const std::string sectionName) { // Base::Console().Message("DVS::setCSFromBase(%s)\n", sectionName.c_str()); - gp_Ax2 CS = getCSFromBase(sectionName); - gp_Dir gDir = CS.Direction(); + gp_Dir gDir = getCSFromBase(sectionName).Direction(); Base::Vector3d vDir(gDir.X(), gDir.Y(), gDir.Z()); Direction.setValue(vDir); SectionNormal.setValue(vDir); - gp_Dir gxDir = CS.XDirection(); + gp_Dir gxDir = getCSFromBase(sectionName).XDirection(); Base::Vector3d vXDir(gxDir.X(), gxDir.Y(), gxDir.Z()); @@ -830,15 +752,15 @@ std::vector DrawViewSection::getDrawableLines(int i) // Base::Console().Message("DVS::getDrawableLines(%d) - lineSets: %d\n", i, m_lineSets.size()); std::vector result; result = DrawGeomHatch::getTrimmedLinesSection(this,m_lineSets, - getSectionTFace(i), + getSectionTopoDSFace(i), HatchScale.getValue()); return result; } -TopoDS_Face DrawViewSection::getSectionTFace(int i) +TopoDS_Face DrawViewSection::getSectionTopoDSFace(int i) { TopoDS_Face result; - TopExp_Explorer expl(sectionFaces, TopAbs_FACE); + TopExp_Explorer expl(sectionTopoDSFaces, TopAbs_FACE); int count = 1; for (; expl.More(); expl.Next(), count++) { if (count == i+1) { @@ -848,15 +770,6 @@ TopoDS_Face DrawViewSection::getSectionTFace(int i) return result; } -void DrawViewSection::unsetupObject() -{ - TechDraw::DrawViewPart* base = getBaseDVP(); - if (base) { - base->touch(); - } - DrawViewPart::unsetupObject(); -} - TechDraw::DrawViewPart* DrawViewSection::getBaseDVP() const { TechDraw::DrawViewPart* baseDVP = nullptr; @@ -881,43 +794,17 @@ TechDraw::DrawProjGroupItem* DrawViewSection::getBaseDPGI() const return baseDPGI; } -void DrawViewSection::getParameters() +// setup / tear down routines + +void DrawViewSection::unsetupObject() { -// Base::Console().Message("DVS::getParameters()\n"); - Base::ReferencehGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General"); - - bool fuseFirst = hGrp->GetBool("SectionFuseFirst", false); - FuseBeforeCut.setValue(fuseFirst); + TechDraw::DrawViewPart* base = getBaseDVP(); + if (base) { + base->touch(); + } + DrawViewPart::unsetupObject(); } -bool DrawViewSection::debugSection() const -{ - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/debug"); - - bool result = hGrp->GetBool("debugSection",false); - return result; -} - -int DrawViewSection::prefCutSurface() const -{ -// Base::Console().Message("DVS::prefCutSurface()\n"); - Base::ReferencehGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Decorations"); - - int result = hGrp->GetInt("CutSurfaceDisplay", 2); //default to SvgHatch - return result; -} - -bool DrawViewSection::showSectionEdges() -{ - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General"); - return (hGrp->GetBool("ShowSectionEdges", true)); -} - - void DrawViewSection::onDocumentRestored() { // Base::Console().Message("DVS::onDocumentRestored()\n"); @@ -954,7 +841,32 @@ void DrawViewSection::setupObject() DrawViewPart::setupObject(); } -void DrawViewSection::setupSvgIncluded() +//hatch file routines + +//create geometric hatch lines +void DrawViewSection::makeLineSets(void) +{ +// Base::Console().Message("DVS::makeLineSets()\n"); + if (!PatIncluded.isEmpty()) { + std::string fileSpec = PatIncluded.getValue(); + Base::FileInfo fi(fileSpec); + std::string ext = fi.extension(); + if (!fi.isReadable()) { + Base::Console().Message("%s can not read hatch file: %s\n", getNameInDocument(), fileSpec.c_str()); + } else { + if ( (ext == "pat") || + (ext == "PAT") ) { + if ((!fileSpec.empty()) && + (!NameGeomPattern.isEmpty())) { + m_lineSets.clear(); + m_lineSets = DrawGeomHatch::makeLineSets(fileSpec, NameGeomPattern.getValue()); + } + } + } + } +} + +void DrawViewSection::setupSvgIncluded(void) { // Base::Console().Message("DVS::setupSvgIncluded()\n"); App::Document* doc = getDocument(); @@ -999,6 +911,69 @@ void DrawViewSection::setupPatIncluded() } } +//this could probably always use FileHatchPattern as input? +void DrawViewSection::replaceSvgIncluded(std::string newSvgFile) +{ +// Base::Console().Message("DVS::replaceSvgHatch(%s)\n", newSvgFile.c_str()); + if (SvgIncluded.isEmpty()) { + setupSvgIncluded(); + } else { + std::string tempName = SvgIncluded.getExchangeTempFile(); + DrawUtil::copyFile(newSvgFile, tempName); + SvgIncluded.setValue(tempName.c_str()); + } +} + +void DrawViewSection::replacePatIncluded(std::string newPatFile) +{ +// Base::Console().Message("DVS::replacePatHatch(%s)\n", newPatFile.c_str()); + if (PatIncluded.isEmpty()) { + setupPatIncluded(); + } else { + std::string tempName = PatIncluded.getExchangeTempFile(); + DrawUtil::copyFile(newPatFile, tempName); + PatIncluded.setValue(tempName.c_str()); + } +} + +// Parameter fetching routines + +void DrawViewSection::getParameters() +{ +// Base::Console().Message("DVS::getParameters()\n"); + Base::ReferencehGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General"); + + bool fuseFirst = hGrp->GetBool("SectionFuseFirst", false); + FuseBeforeCut.setValue(fuseFirst); +} + +bool DrawViewSection::debugSection(void) const +{ + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/debug"); + + bool result = hGrp->GetBool("debugSection",false); + return result; +} + +int DrawViewSection::prefCutSurface(void) const +{ +// Base::Console().Message("DVS::prefCutSurface()\n"); + Base::ReferencehGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Decorations"); + + int result = hGrp->GetInt("CutSurfaceDisplay", 2); //default to SvgHatch + return result; +} + +bool DrawViewSection::showSectionEdges(void) +{ + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General"); + return (hGrp->GetBool("ShowSectionEdges", true)); +} + #include // Python Drawing feature --------------------------------------------------------- diff --git a/src/Mod/TechDraw/App/DrawViewSection.h b/src/Mod/TechDraw/App/DrawViewSection.h index 9bcf95dadd..6fe0b9ce5d 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.h +++ b/src/Mod/TechDraw/App/DrawViewSection.h @@ -104,6 +104,7 @@ public: virtual void postSectionCutTasks(); void waitingForCut(bool s) { m_waitingForCut = s; } bool waitingForCut(void) const { return m_waitingForCut; } + bool waitingForResult() const override; std::vector getTDFaceGeometry() {return tdSectionFaces;} @@ -116,10 +117,9 @@ public: TechDraw::DrawViewPart* getBaseDVP() const; TechDraw::DrawProjGroupItem* getBaseDPGI() const; - TopoDS_Compound getSectionFaces() { return sectionFaces;} -// std::vector getSectionFaceWires(void) { return sectionFaceWires; } //obs? - TopoDS_Face getSectionTFace(int i); - void makeLineSets() ; + TopoDS_Compound getSectionTFaces() { return sectionTopoDSFaces;} + TopoDS_Face getSectionTopoDSFace(int i); + void makeLineSets(void) ; std::vector getDrawableLines(int i = 0); std::vector getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern); @@ -136,8 +136,7 @@ public Q_SLOTS: void onSectionCutFinished(void); protected: - TopoDS_Compound sectionFaces; //tSectionFaces -// std::vector sectionFaceWires; //obs??? getSectionFaceWires + TopoDS_Compound sectionTopoDSFaces; //needed for hatching std::vector m_lineSets; std::vector tdSectionFaces; diff --git a/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp b/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp index 75323958ff..46d6189204 100644 --- a/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp +++ b/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp @@ -116,7 +116,8 @@ App::DocumentObjectExecReturn *DrawViewSpreadsheet::execute() return new App::DocumentObjectExecReturn("Empty cell value"); Symbol.setValue(getSheetImage()); - + + overrideKeepUpdated(false); return TechDraw::DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/DrawWeldSymbol.cpp b/src/Mod/TechDraw/App/DrawWeldSymbol.cpp index 7d1549d8f4..7c503b03b1 100644 --- a/src/Mod/TechDraw/App/DrawWeldSymbol.cpp +++ b/src/Mod/TechDraw/App/DrawWeldSymbol.cpp @@ -120,9 +120,10 @@ App::DocumentObjectExecReturn *DrawWeldSymbol::execute() { // Base::Console().Message("DWS::execute()\n"); if (!keepUpdated()) { - return App::DocumentObject::StdReturn; + return DrawView::execute(); } - + + overrideKeepUpdated(false); return DrawView::execute(); } diff --git a/src/Mod/TechDraw/App/FeatureProjection.cpp b/src/Mod/TechDraw/App/FeatureProjection.cpp index 719c2eb949..8e2e8f19d0 100644 --- a/src/Mod/TechDraw/App/FeatureProjection.cpp +++ b/src/Mod/TechDraw/App/FeatureProjection.cpp @@ -19,7 +19,7 @@ * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ -//this file originally part of TechDraw workbench +//this file originally part of Drawing workbench //migrated to TechDraw workbench 2022-01-26 by Wandererfan diff --git a/src/Mod/TechDraw/App/GeometryObject.cpp b/src/Mod/TechDraw/App/GeometryObject.cpp index 09adc63f6b..7d2c247a06 100644 --- a/src/Mod/TechDraw/App/GeometryObject.cpp +++ b/src/Mod/TechDraw/App/GeometryObject.cpp @@ -178,10 +178,10 @@ void GeometryObject::projectShape(const TopoDS_Shape& inShape, catch (const Standard_Failure& e) { Base::Console().Error("GO::projectShape - OCC error - %s - while projecting shape\n", e.GetMessageString()); - throw Base::RuntimeError("GeometryObject::hlrExecute - OCC error"); + throw Base::RuntimeError("GeometryObject::projectShape - OCC error"); } catch (...) { - throw Base::RuntimeError("GeometryObject::hlrExecute - unknown error"); + throw Base::RuntimeError("GeometryObject::projectShape - unknown error"); } try { @@ -249,13 +249,18 @@ void GeometryObject::projectShape(const TopoDS_Shape& inShape, } } catch (const Standard_Failure& e) { - throw Base::RuntimeError("GeometryObject::hlrExecute - OCC error occurred while extracting edges"); + throw Base::RuntimeError("GeometryObject::projectShape - OCC error occurred while extracting edges"); } catch (...) { - throw Base::RuntimeError("GeometryObject::hlrExecute - unknown error occurred while extracting edges"); + throw Base::RuntimeError("GeometryObject::projectShape - unknown error occurred while extracting edges"); } - //convert the hlr output into TD Geometry + makeTDGeometry(); +} + +//convert the hlr output into TD Geometry +void GeometryObject::makeTDGeometry() +{ extractGeometry(TechDraw::ecHARD, //always show the hard&outline visible lines true); extractGeometry(TechDraw::ecOUTLINE, @@ -340,8 +345,6 @@ void GeometryObject::projectShapeWithPolygonAlgo(const TopoDS_Shape& input, inCopy = BuilderCopy.Shape(); } - auto start = chrono::high_resolution_clock::now(); - Handle(HLRBRep_PolyAlgo) brep_hlrPoly; try { @@ -369,11 +372,10 @@ void GeometryObject::projectShapeWithPolygonAlgo(const TopoDS_Shape& input, catch (const Standard_Failure& e) { Base::Console().Error("GO::projectShapeWithPolygonAlgo - OCC error - %s - while projecting shape\n", e.GetMessageString()); + throw Base::RuntimeError("GeometryObject::projectShapeWithPolygonAlgo - OCC error"); } catch (...) { - Base::Console().Error("GO::projectShapeWithPolygonAlgo - unknown error while projecting shape\n"); -// throw Base::RuntimeError("GeometryObject::projectShapeWithPolygonAlgo - error occurred while projecting shape"); -// Standard_Failure::Raise("GeometryObject::projectShapeWithPolygonAlgo - error occurred while projecting shape"); + throw Base::RuntimeError("GeometryObject::projectShapeWithPolygonAlgo - unknown error"); } try { @@ -417,16 +419,13 @@ void GeometryObject::projectShapeWithPolygonAlgo(const TopoDS_Shape& input, catch (const Standard_Failure& e) { Base::Console().Error("GO::projectShapeWithPolygonAlgo - OCC error - %s - while extracting edges\n", e.GetMessageString()); + throw Base::RuntimeError("GeometryObject::projectShapeWithPolygonAlgo - OCC error occurred while extracting edges"); } catch (...) { - Base::Console().Error("GO::projectShapeWithPolygonAlgo - - error occurred while extracting edges\n"); -// throw Base::RuntimeError("GeometryObject::projectShapeWithPolygonAlgo - error occurred while extracting edges"); -// Standard_Failure::Raise("GeometryObject::projectShapeWithPolygonAlgo - error occurred while extracting edges"); + throw Base::RuntimeError("GeometryObject::projectShapeWithPolygonAlgo - unknown error occurred while extracting edges"); } - auto end = chrono::high_resolution_clock::now(); - auto diff = end - start; - double diffOut = chrono::duration (diff).count(); - Base::Console().Log("TIMING - %s GO spent: %.3f millisecs in HLRBRep_PolyAlgo & co\n", m_parentName.c_str(), diffOut); + + makeTDGeometry(); } TopoDS_Shape GeometryObject::projectFace(const TopoDS_Shape &face, diff --git a/src/Mod/TechDraw/App/GeometryObject.h b/src/Mod/TechDraw/App/GeometryObject.h index d090e3ea05..1f24baffe1 100644 --- a/src/Mod/TechDraw/App/GeometryObject.h +++ b/src/Mod/TechDraw/App/GeometryObject.h @@ -122,6 +122,7 @@ public: TopoDS_Shape projectFace(const TopoDS_Shape &face, const gp_Ax2 &CS); + void makeTDGeometry(); void extractGeometry(edgeClass category, bool visible); void addFaceGeom(FacePtr f); void clearFaceGeom(); diff --git a/src/Mod/TechDraw/App/LandmarkDimension.cpp b/src/Mod/TechDraw/App/LandmarkDimension.cpp index 3deabd111c..466a1d8150 100644 --- a/src/Mod/TechDraw/App/LandmarkDimension.cpp +++ b/src/Mod/TechDraw/App/LandmarkDimension.cpp @@ -153,7 +153,9 @@ App::DocumentObjectExecReturn *LandmarkDimension::execute() // dvp->resetReferenceVerts(); dvp->addReferencesToGeom(); - dvp->requestPaint(); + dvp->requestPaint(); + + overrideKeepUpdated(false); return dvdResult; } diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index d3c547a05a..316977d36e 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -340,10 +340,9 @@ QGIViewClip* QGIView::getClipGroup() return result; } -void QGIView::updateView(bool update) +void QGIView::updateView(bool forceUpdate) { // Base::Console().Message("QGIV::updateView() - %s\n",getViewObject()->getNameInDocument()); - (void) update; //allow/prevent dragging if (getViewObject()->isLocked()) { @@ -352,6 +351,11 @@ void QGIView::updateView(bool update) setFlag(QGraphicsItem::ItemIsMovable, true); } + if (getViewObject() && forceUpdate) { + setPosition(Rez::guiX(getViewObject()->X.getValue()), + Rez::guiX(getViewObject()->Y.getValue())); + } + double appRotation = getViewObject()->Rotation.getValue(); double guiRotation = rotation(); if (!TechDraw::DrawUtil::fpCompare(appRotation,guiRotation)) { diff --git a/src/Mod/TechDraw/Gui/QGIViewSection.cpp b/src/Mod/TechDraw/Gui/QGIViewSection.cpp index 2f9a9f1cde..44d98de155 100644 --- a/src/Mod/TechDraw/Gui/QGIViewSection.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewSection.cpp @@ -67,25 +67,26 @@ void QGIViewSection::draw() void QGIViewSection::drawSectionFace() { auto section( dynamic_cast(getViewObject()) ); - if (!section) + if (!section) { return; + } - if (!section->hasGeometry()) + if (!section->hasGeometry()) { return; + } + Gui::ViewProvider* gvp = QGIView::getViewProvider(section); ViewProviderViewSection* sectionVp = dynamic_cast(gvp); if (!sectionVp || !sectionVp->ShowCutSurface.getValue()) return; - float lineWidth = sectionVp->LineWidth.getValue(); - auto sectionFaces( section->getTDFaceGeometry() ); if (sectionFaces.empty()) { - Base::Console(). - Log("INFO - QGIViewSection::drawSectionFace - No sectionFaces available. Check Section plane.\n"); return; } + float lineWidth = sectionVp->LineWidth.getValue(); + std::vector::iterator fit = sectionFaces.begin(); int i = 0; for(; fit != sectionFaces.end(); fit++, i++) { diff --git a/src/Mod/TechDraw/Gui/TaskProjGroup.cpp b/src/Mod/TechDraw/Gui/TaskProjGroup.cpp index 3e86aa8596..8da0ecd39e 100644 --- a/src/Mod/TechDraw/Gui/TaskProjGroup.cpp +++ b/src/Mod/TechDraw/Gui/TaskProjGroup.cpp @@ -264,7 +264,7 @@ void TaskProjGroup::scaleTypeChanged(int index) // Automatic Scale Type //block recompute multiView->ScaleType.setValue("Automatic"); - double autoScale = multiView->calculateAutomaticScale(); + double autoScale = multiView->autoScale(); multiView->Scale.setValue(autoScale); //unblock recompute diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp index 50b7b774c0..471588d71f 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp @@ -350,7 +350,6 @@ void ViewProviderPage::removeMDIView(void) MDIViewPage* ViewProviderPage::getMDIViewPage() const { if (m_mdiView.isNull()) { - Base::Console().Log("VPP::getMDIViewPage has no m_mdiView!\n"); return nullptr; } return m_mdiView; diff --git a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp index b7057db979..4a3ccc77c8 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp @@ -70,20 +70,6 @@ ViewProviderRichAnno::~ViewProviderRichAnno() { } -bool ViewProviderRichAnno::setEdit(int ModNum) -{ -// Base::Console().Message("VPRA::setEdit(%d)\n",ModNum); - if (ModNum != ViewProvider::Default ) { - return ViewProviderDrawingView::setEdit(ModNum); - } - if (Gui::Control().activeDialog()) { //TaskPanel already open! - return false; - } - Gui::Selection().clearSelection(); - Gui::Control().showDialog(new TaskDlgRichAnno(this)); - return true; -} - bool ViewProviderRichAnno::doubleClicked() { // Base::Console().Message("VPRA::doubleClicked()\n"); diff --git a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h index 82c29c0a3d..2d3e37998c 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h +++ b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h @@ -55,7 +55,6 @@ public: bool useNewSelectionModel() const override {return false;} void updateData(const App::Property*) override; void onChanged(const App::Property* p) override; - bool setEdit(int ModNum) override; bool doubleClicked() override; bool canDelete(App::DocumentObject* obj) const override;