From c1f7407b255d7e4a5e63e37f69b5c0190519f95e Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Mon, 23 Aug 2021 20:26:12 -0500 Subject: [PATCH 001/101] [Gui] Add hidden pref to lock toolbars When arranged vertically, the bar that allows the dragging of toolbars can cause problems with the toolbar appearance. This adds a hidden preference that controls whether the toolbars are movable. --- src/Gui/ToolBarManager.cpp | 18 ++++++++++++++++++ src/Gui/ToolBarManager.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/Gui/ToolBarManager.cpp b/src/Gui/ToolBarManager.cpp index b96167114c..7221c1fbb3 100644 --- a/src/Gui/ToolBarManager.cpp +++ b/src/Gui/ToolBarManager.cpp @@ -250,6 +250,11 @@ void ToolBarManager::setup(ToolBarItem* toolBarItems) (*it)->hide(); (*it)->toggleViewAction()->setVisible(false); } + + hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp") + ->GetGroup("Preferences")->GetGroup("General"); + bool lockToolBars = hPref->GetBool("LockToolBars", false); + setMovable(!lockToolBars); } void ToolBarManager::setup(ToolBarItem* item, QToolBar* toolbar) const @@ -314,6 +319,12 @@ void ToolBarManager::restoreState() const toolbar->setVisible(hPref->GetBool(toolbarName.constData(), toolbar->isVisible())); } } + + + hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp") + ->GetGroup("Preferences")->GetGroup("General"); + bool lockToolBars = hPref->GetBool("LockToolBars", false); + setMovable(!lockToolBars); } void ToolBarManager::retranslate() const @@ -327,6 +338,13 @@ void ToolBarManager::retranslate() const } } +void Gui::ToolBarManager::setMovable(bool moveable) const +{ + for (auto& tb : toolBars()) { + tb->setMovable(moveable); + } +} + QToolBar* ToolBarManager::findToolBar(const QList& toolbars, const QString& item) const { for (QList::ConstIterator it = toolbars.begin(); it != toolbars.end(); ++it) { diff --git a/src/Gui/ToolBarManager.h b/src/Gui/ToolBarManager.h index 82230044f6..ed92657642 100644 --- a/src/Gui/ToolBarManager.h +++ b/src/Gui/ToolBarManager.h @@ -80,6 +80,8 @@ public: void restoreState() const; void retranslate() const; + void setMovable(bool movable) const; + protected: void setup(ToolBarItem*, QToolBar*) const; /** Returns a list of all currently existing toolbars. */ From f4c50e3701cc8591c85894f13368778a199292ca Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Mon, 20 Sep 2021 15:55:34 -0500 Subject: [PATCH 002/101] [Spreadsheet] Refactor and simplify paste code --- src/Mod/Spreadsheet/App/PropertySheet.cpp | 56 ++++++++--------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index c4798e74d1..3e857b547d 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -367,71 +367,51 @@ void PropertySheet::copyCells(Base::Writer &writer, const std::vector &ra writer.Stream() << "" << std::endl; } -void PropertySheet::pasteCells(XMLReader &reader, const CellAddress &addr) { +void PropertySheet::pasteCells(XMLReader& reader, const CellAddress& addr) { AtomicPropertyChange signaller(*this); bool first = true; - int roffset=0,coffset=0; + int roffset = 0, coffset = 0; reader.readElement("Cells"); - int rangeCount = reader.getAttributeAsInteger("count"); - - for(;rangeCount;--rangeCount) { + for (int rangeCount = reader.getAttributeAsInteger("count"); rangeCount != 0; --rangeCount) { reader.readElement("Range"); CellAddress from(reader.getAttribute("from")); CellAddress to(reader.getAttribute("to")); - int cellCount = reader.getAttributeAsInteger("count"); - Range range(from,to); - bool hasCells = !!cellCount; - for(;cellCount;--cellCount) { - reader.readElement("Cell"); - CellAddress src(reader.getAttribute("address")); - if(first) { + Range range(from, to); + for (int cellCount = reader.getAttributeAsInteger("count"); cellCount != 0; --cellCount) { + if (first) { first = false; roffset = addr.row() - from.row(); coffset = addr.col() - from.col(); - }else - if (!range.next()) - break; - while(src!=*range) { - CellAddress dst(*range); - dst.setRow(dst.row()+roffset); - dst.setCol(dst.col()+coffset); - owner->clear(dst); - owner->cellUpdated(dst); - if (!range.next()) - break; } - CellAddress dst(src.row()+roffset, src.col()+coffset); + reader.readElement("Cell"); + CellAddress src(reader.getAttribute("address")); + CellAddress dst(src.row() + roffset, src.col() + coffset); + owner->clear(dst); + owner->cellUpdated(dst); + auto cell = owner->getNewCell(dst); - cell->setSpans(-1,-1); - cell->restore(reader,true); + cell->setSpans(-1, -1); + cell->restore(reader, true); int rows, cols; - if (cell->getSpans(rows, cols) && (rows > 1 || cols > 1)) + if (cell->getSpans(rows, cols) && (rows > 1 || cols > 1)) mergeCells(dst, CellAddress(dst.row() + rows - 1, dst.col() + cols - 1)); - if(roffset || coffset) { + if (roffset || coffset) { OffsetCellsExpressionVisitor visitor(*this, roffset, coffset); cell->visit(visitor); - if(visitor.changed()) + if (visitor.changed()) recomputeDependencies(dst); } dirty.insert(dst); owner->cellUpdated(dst); } - if(!hasCells || range.next()) { - do { - CellAddress dst(*range); - dst.setRow(dst.row()+roffset); - dst.setCol(dst.col()+coffset); - owner->clear(dst); - owner->cellUpdated(dst); - }while(range.next()); - } } signaller.tryInvoke(); } + Cell * PropertySheet::cellAt(CellAddress address) { std::map::const_iterator j = mergedCells.find(address); From a27d270fa9a72eb71d48870d27a5048bac604f07 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Tue, 21 Sep 2021 14:32:42 -0500 Subject: [PATCH 003/101] [Spreadsheet] Add support for copying empty cells --- src/Mod/Spreadsheet/App/PropertySheet.cpp | 27 ++++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index 3e857b547d..8a6fa6542d 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -341,25 +341,26 @@ void PropertySheet::Restore(Base::XMLReader &reader) signaller.tryInvoke(); } -void PropertySheet::copyCells(Base::Writer &writer, const std::vector &ranges) const { +void PropertySheet::copyCells(Base::Writer& writer, const std::vector& ranges) const { writer.Stream() << "" << std::endl; writer.Stream() << "" << std::endl; writer.incInd(); - for(auto range : ranges) { - auto r = range; - int count = 0; - do { - if(getValue(*r)) - ++count; - }while(r.next()); + for (auto range : ranges) { writer.Stream() << writer.ind() << "" << std::endl; + << "\" to=\"" << range.toCellString() << "\" count=\"" << range.size() << "\">" << std::endl; writer.incInd(); do { auto cell = getValue(*range); - if(cell) + if (cell) { cell->save(writer); - }while(range.next()); + } + else { + // The cell is empty, so when it's pasted it needs to clear the existing contents + writer.Stream() << writer.ind() << ""; + } + } while (range.next()); writer.decInd(); writer.Stream() << writer.ind() << "" << std::endl; } @@ -374,12 +375,12 @@ void PropertySheet::pasteCells(XMLReader& reader, const CellAddress& addr) { int roffset = 0, coffset = 0; reader.readElement("Cells"); - for (int rangeCount = reader.getAttributeAsInteger("count"); rangeCount != 0; --rangeCount) { + for (int rangeCount = reader.getAttributeAsInteger("count"); rangeCount > 0; --rangeCount) { reader.readElement("Range"); CellAddress from(reader.getAttribute("from")); CellAddress to(reader.getAttribute("to")); Range range(from, to); - for (int cellCount = reader.getAttributeAsInteger("count"); cellCount != 0; --cellCount) { + for (int cellCount = reader.getAttributeAsInteger("count"); cellCount > 0; --cellCount) { if (first) { first = false; roffset = addr.row() - from.row(); From 5810bde0de3c23a7b864d7836189d7927857c940 Mon Sep 17 00:00:00 2001 From: carlopav Date: Sat, 28 Aug 2021 16:39:11 +0200 Subject: [PATCH 004/101] Draft: Grid added option to disable human figure representation The "gridShowHuman" preference was introduced to disable the human figure representation in the grid. --- src/Mod/Draft/draftguitools/gui_trackers.py | 22 +++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_trackers.py b/src/Mod/Draft/draftguitools/gui_trackers.py index 2756a6786c..32430e139f 100644 --- a/src/Mod/Draft/draftguitools/gui_trackers.py +++ b/src/Mod/Draft/draftguitools/gui_trackers.py @@ -1106,16 +1106,18 @@ class gridTracker(Tracker): self.textpos1.translation.setValue((-bound+self.space,-border+self.space,z)) self.textpos2.translation.setValue((-bound-self.space,-bound+self.space,z)) # human from BIM workbench - loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) - try: - import BimProject - hpts = BimProject.getHuman(loc) - except Exception: - # BIM not installed - pass - else: - mpts.extend([tuple(p) for p in hpts]) - midx.append(len(hpts)) + param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + if param.GetBool("gridShowHuman", True): + try: + import BimProject + loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) + hpts = BimProject.getHuman(loc) + mpts.extend([tuple(p) for p in hpts]) + midx.append(len(hpts)) + except Exception: + # BIM not installed + pass + else: self.text1.string = " " self.text2.string = " " From 67e0395aede5882f6ceea4389c3720504da8f120 Mon Sep 17 00:00:00 2001 From: carlopav Date: Sun, 26 Sep 2021 12:11:39 +0200 Subject: [PATCH 005/101] Draft: Grid added option in preferences dialog to display the human figure . --- .../Resources/ui/preferences-draftsnap.ui | 66 ++++++++++++++++--- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui b/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui index 9b4634878c..983afad5ac 100644 --- a/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui +++ b/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui @@ -17,7 +17,16 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 @@ -252,9 +261,9 @@ - - - + + + @@ -323,6 +332,25 @@ + + + + <html><head/><body><p>If checked, a human figure silhouette is displayed at the grid center. This option is only effective if the BIM workbench is installed and if &quot;Show grid border&quot; option is enabled.</p></body></html> + + + Show human figure + + + true + + + gridShowHuman + + + Mod/Draft + + + @@ -525,7 +553,7 @@ The color of the grid - + 50 50 @@ -572,7 +600,16 @@ - + + 0 + + + 0 + + + 0 + + 0 @@ -618,22 +655,31 @@ 5 + + 10 + DraftEditMaxObjects Mod/Draft - - 10 - - + + 0 + + + 0 + + + 0 + + 0 From dfd8b82fa231eb18bdeeb28cd46624d8541b5eaa Mon Sep 17 00:00:00 2001 From: carlopav Date: Sun, 26 Sep 2021 11:48:57 +0200 Subject: [PATCH 006/101] Draft: updated working plane BIM figure Display the human figure at the grid corner. The silhouette is displayed only if: - BIM Workbench is available; - preference BaseApp/Preferences/Mod/Draft/gridShowHuman is True; - the working plane normal is vertical. --- src/Mod/Draft/draftguitools/gui_trackers.py | 52 +++++++++++++++------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_trackers.py b/src/Mod/Draft/draftguitools/gui_trackers.py index 32430e139f..ae5ed9a563 100644 --- a/src/Mod/Draft/draftguitools/gui_trackers.py +++ b/src/Mod/Draft/draftguitools/gui_trackers.py @@ -1009,6 +1009,13 @@ class gridTracker(Tracker): self.coords2 = coin.SoCoordinate3() self.lines2 = coin.SoLineSet() # big squares + # human figure + mat_human = coin.SoMaterial() + mat_human.transparency.setValue(0.3*(1-gtrans)) + mat_human.diffuseColor.setValue(col) + self.coords_human = coin.SoCoordinate3() + self.human = coin.SoLineSet() + # axes mat3 = coin.SoMaterial() mat3.transparency.setValue(gtrans) @@ -1030,6 +1037,9 @@ class gridTracker(Tracker): s.addChild(mat2) s.addChild(self.coords2) s.addChild(self.lines2) + s.addChild(mat_human) + s.addChild(self.coords_human) + s.addChild(self.human) s.addChild(mbind3) s.addChild(mat3) s.addChild(self.coords3) @@ -1105,19 +1115,6 @@ class gridTracker(Tracker): self.text2.string = txt self.textpos1.translation.setValue((-bound+self.space,-border+self.space,z)) self.textpos2.translation.setValue((-bound-self.space,-bound+self.space,z)) - # human from BIM workbench - param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") - if param.GetBool("gridShowHuman", True): - try: - import BimProject - loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) - hpts = BimProject.getHuman(loc) - mpts.extend([tuple(p) for p in hpts]) - midx.append(len(hpts)) - except Exception: - # BIM not installed - pass - else: self.text1.string = " " self.text2.string = " " @@ -1132,8 +1129,36 @@ class gridTracker(Tracker): self.coords3.point.setValues(apts) #self.lines3.numVertices.setValues(aidx) self.pts = pts + self.displayHumanFigure() self.setAxesColor() + def displayHumanFigure(self): + """ Display the human figure at the grid corner. + The silhouette is displayed only if: + - BIM Workbench is available; + - preference BaseApp/Preferences/Mod/Draft/gridShowHuman is True; + - the working plane normal is vertical. + """ + numlines = self.numlines // self.mainlines // 2 * 2 * self.mainlines + bound = (numlines // 2) * self.space + pts = [] + pidx = [] + param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + if param.GetBool("gridShowHuman", True) and \ + FreeCAD.DraftWorkingPlane.axis.getAngle(FreeCAD.Vector(0,0,1)) < 0.001: + try: + import BimProject + loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) + hpts = BimProject.getHuman(loc) + pts.extend([tuple(p) for p in hpts]) + pidx.append(len(hpts)) + except Exception: + # BIM not installed + return + self.human.numVertices.deleteValues(0) + self.coords_human.point.setValues(pts) + self.human.numVertices.setValues(pidx) + def setAxesColor(self): """set axes color""" cols = [0,0] @@ -1182,6 +1207,7 @@ class gridTracker(Tracker): P = FreeCAD.DraftWorkingPlane.position self.trans.rotation.setValue([Q[0], Q[1], Q[2], Q[3]]) self.trans.translation.setValue([P.x, P.y, P.z]) + self.displayHumanFigure() self.setAxesColor() self.on() From a1499c297e7b222f6fa67c404676684dece1420b Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 28 Sep 2021 14:49:22 +0200 Subject: [PATCH 007/101] Draft: fix shortcuts in menus and more (InitGui.py) --- src/Mod/Draft/InitGui.py | 46 +++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 8802be6af4..ced2528c63 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -92,25 +92,47 @@ class DraftWorkbench(FreeCADGui.Workbench): # Set up command lists import draftutils.init_tools as it - self.drawing_commands = it.get_draft_drawing_commands() + if hasattr(it, "get_draft_drawing_commands_temp"): + self.drawing_commands = it.get_draft_drawing_commands_temp() + else: + self.drawing_commands = it.get_draft_drawing_commands() self.annotation_commands = it.get_draft_annotation_commands() - self.modification_commands = it.get_draft_modification_commands() + if hasattr(it, "get_draft_modification_commands_temp"): + self.modification_commands = it.get_draft_modification_commands_temp() + else: + self.modification_commands = it.get_draft_modification_commands() + self.utility_commands_menu = it.get_draft_utility_commands_menu() + self.utility_commands_toolbar = it.get_draft_utility_commands_toolbar() self.context_commands = it.get_draft_context_commands() self.line_commands = it.get_draft_line_commands() - self.utility_commands = it.get_draft_utility_commands() - self.utility_small = it.get_draft_small_commands() # Set up toolbars - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft creation tools"), self.drawing_commands) - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"), self.annotation_commands) - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft modification tools"), self.modification_commands) - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft utility tools"), self.utility_small) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft creation tools"), + self.drawing_commands) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"), + self.annotation_commands) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft modification tools"), + self.modification_commands) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft utility tools"), + self.utility_commands_toolbar) # Set up menus - self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Drafting"), self.drawing_commands) - self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Annotation"), self.annotation_commands) - self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Modification"), self.modification_commands) - self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Utilities"), self.utility_commands + self.context_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Draft", "&Drafting")], + self.drawing_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Draft", "&Annotation")], + self.annotation_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Draft", "&Modification")], + self.modification_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Draft", "&Utilities")], + self.utility_commands_menu) # Set up preferences pages if hasattr(FreeCADGui, "draftToolBar"): From f4ce6a8291856fba21c089062a3148d525ba8f28 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 28 Sep 2021 14:50:41 +0200 Subject: [PATCH 008/101] Draft: fix shortcuts in menus and more (init_tools.py) --- src/Mod/Draft/draftutils/init_tools.py | 174 +++++++++++++++++++------ 1 file changed, 137 insertions(+), 37 deletions(-) diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index 4812575d82..a2c5454db1 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -1,5 +1,6 @@ # *************************************************************************** -# * (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2021 FreeCAD Developers * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -20,13 +21,9 @@ # * USA * # * * # *************************************************************************** -"""Provides lists of commands in order to set up toolbars of the workbench. -This module returns lists of commands, so that the toolbars -can be initialized by Draft, and by other workbenches. -These commands should be defined in `DraftTools`, and in the individual -modules in `draftguitools`. -""" +"""Provides functions and lists of commands to set up Draft menus and toolbars.""" + ## @package init_tools # \ingroup draftutils # \brief Provides lists of commands to set up toolbars of the workbench. @@ -48,6 +45,35 @@ def get_draft_drawing_commands(): "Draft_ShapeString","Draft_Hatch"] +# This function replaces get_draft_drawing_commands. +# The "_temp" suffix should be removed when the BIM Workbench has been updated. +def get_draft_drawing_commands_temp(): + """Return the drawing commands list.""" + from draftguitools import gui_arcs + from draftguitools import gui_beziers + arc_group = gui_arcs.ArcGroup + bez_group = gui_beziers.BezierGroup + + return ["Draft_Line", + "Draft_Wire", + "Draft_Fillet", + ([QT_TRANSLATE_NOOP("Draft", "Arc tools")], + list(arc_group.GetCommands(arc_group))), # tuple len=2: submenu + ("Draft_ArcTools", ), # tuple len=1: toolbar flyout + "Draft_Circle", + "Draft_Ellipse", + "Draft_Rectangle", + "Draft_Polygon", + "Draft_BSpline", + ([QT_TRANSLATE_NOOP("Draft", "Bezier tools")], + list(bez_group.GetCommands(bez_group))), + ("Draft_BezierTools", ), + "Draft_Point", + "Draft_Facebinder", + "Draft_ShapeString", + "Draft_Hatch"] + + def get_draft_annotation_commands(): """Return the annotation commands list.""" return ["Draft_Text", "Draft_Dimension", @@ -59,6 +85,8 @@ def get_draft_array_commands(): return ["Draft_ArrayTools"] +# This function has been replaced by get_draft_utility_commands_toolbar. +# It should be removed when the BIM Workbench has been updated. def get_draft_small_commands(): """Return a list with only some utilities.""" return ["Draft_Layer", @@ -92,6 +120,42 @@ def get_draft_modification_commands(): return lst +# This function replaces get_draft_modification_commands. +# The "_temp" suffix should be removed when the BIM Workbench has been updated. +def get_draft_modification_commands_temp(): + """Return the modification commands list.""" + from draftguitools import gui_arrays + arr_group = gui_arrays.ArrayGroup + + return ["Draft_Move", + "Draft_Rotate", + "Draft_Scale", + "Draft_Mirror", + "Draft_Offset", + "Draft_Trimex", + "Draft_Stretch", + "Separator", + "Draft_Clone", + ([QT_TRANSLATE_NOOP("Draft", "Array tools")], + list(arr_group.GetCommands(arr_group))), # tuple len=2: submenu + ("Draft_ArrayTools", ), # tuple len=1: toolbar flyout + "Separator", + "Draft_Edit", + "Draft_SubelementHighlight", + "Separator", + "Draft_Join", + "Draft_Split", + "Draft_Upgrade", + "Draft_Downgrade", + "Separator", + "Draft_WireToBSpline", + "Draft_Draft2Sketch", + "Draft_Slope", + "Draft_FlipDimension", + "Separator", + "Draft_Shape2DView"] + + def get_draft_context_commands(): """Return the context menu commands list.""" return ["Draft_ApplyStyle", "Draft_ToggleDisplayMode", @@ -106,6 +170,8 @@ def get_draft_line_commands(): "Draft_CloseLine"] +# This function has been replaced by get_draft_utility_commands_menu. +# It should be removed when the BIM Workbench has been updated. def get_draft_utility_commands(): """Return the utility commands list.""" return ["Draft_Layer", @@ -116,6 +182,39 @@ def get_draft_utility_commands(): "Draft_AddConstruction"] +def get_draft_utility_commands_menu(): + """Return the utility commands list for the menu.""" + return ["Draft_SetStyle", + "Draft_ApplyStyle", + "Separator", + "Draft_Layer", + "Draft_AddNamedGroup", + "Draft_AddToGroup", + "Draft_SelectGroup", + "Draft_ToggleConstructionMode", + "Draft_AddConstruction", + "Separator", + "Draft_ToggleDisplayMode", + "Draft_ToggleGrid", + "Draft_SelectPlane", + "Draft_WorkingPlaneProxy", + "Separator", + "Draft_Heal", + "Draft_ToggleContinueMode", + "Draft_ShowSnapBar"] + + +def get_draft_utility_commands_toolbar(): + """Return the utility commands list for the toolbar.""" + return ["Draft_Layer", + "Draft_AddNamedGroup", + "Draft_AddToGroup", + "Draft_SelectGroup", + "Draft_AddConstruction", + "Draft_ToggleDisplayMode", + "Draft_WorkingPlaneProxy"] + + def get_draft_snap_commands(): """Return the snapping commands list.""" return ['Draft_Snap_Lock', @@ -130,47 +229,48 @@ def get_draft_snap_commands(): ] -def init_draft_toolbars(workbench): - """Initialize the Draft toolbars. +def init_toolbar(workbench, toolbar, cmd_list): + """Initialize a toolbar. Parameters ---------- workbench: Gui.Workbench - The workbench class on which the commands have to be available. - If called from within the `Initialize` method - of a workbench class defined inside `InitGui.py`, - it can be used as `setup_draft_toolbars(self)`. + The workbench. The commands from cmd_list must be available. + + toolbar: string + The name of the toolbar. + + cmd_list: list of strings or list of strings and tuples + See f.e. the return value of get_draft_drawing_commands_temp. """ - workbench.appendToolbar(QT_TRANSLATE_NOOP("Draft", - "Draft creation tools"), - get_draft_drawing_commands()) - workbench.appendToolbar(QT_TRANSLATE_NOOP("Draft", - "Draft annotation tools"), - get_draft_annotation_commands()) - workbench.appendToolbar(QT_TRANSLATE_NOOP("Draft", - "Draft modification tools"), - get_draft_modification_commands()) + for cmd in cmd_list: + if isinstance(cmd, tuple): + if len(cmd) == 1: + workbench.appendToolbar(toolbar, [cmd[0]]) + else: + workbench.appendToolbar(toolbar, [cmd]) -def init_draft_menus(workbench): - """Initialize the Draft menus. +def init_menu(workbench, menu_list, cmd_list): + """Initialize a menu. Parameters ---------- workbench: Gui.Workbench - The workbench class on which the commands have to be available. - If called from within the `Initialize` method - of a workbench class defined inside `InitGui.py`, - it can be used as `setup_draft_menus(self)`. + The workbench. The commands from cmd_list must be available. + + menu_list: list of strings + The main and optional submenu(s). The commands, and additonal + submenus (if any), are added to the last (sub)menu in the list. + + cmd_list: list of strings or list of strings and tuples + See f.e. the return value of get_draft_drawing_commands_temp. """ - workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Drafting"), - get_draft_drawing_commands()) - workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Annotation"), - get_draft_annotation_commands()) - workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Modification"), - get_draft_modification_commands()) - workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Utilities"), - get_draft_utility_commands() - + get_draft_context_commands()) + for cmd in cmd_list: + if isinstance(cmd, tuple): + if len(cmd) == 2: + workbench.appendMenu(menu_list + cmd[0], cmd[1]) + else: + workbench.appendMenu(menu_list, [cmd]) ## @} From f469b70654aea76cacf26fca26d2078a246a9b92 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 30 Sep 2021 13:02:52 -0500 Subject: [PATCH 009/101] [Fem] Clean up Fem.ts to remove extra translations --- src/Mod/Fem/Gui/Resources/translations/Fem.ts | 5621 ++++++++++++----- 1 file changed, 3940 insertions(+), 1681 deletions(-) diff --git a/src/Mod/Fem/Gui/Resources/translations/Fem.ts b/src/Mod/Fem/Gui/Resources/translations/Fem.ts index 4f4a6ffe68..d2d8413c0e 100755 --- a/src/Mod/Fem/Gui/Resources/translations/Fem.ts +++ b/src/Mod/Fem/Gui/Resources/translations/Fem.ts @@ -4,17 +4,12 @@ BoundarySelector - + Select Faces/Edges/Vertexes - - To add references select them in the 3D view and then click "Add". - - - - + To add references: select them in the 3D view and click "Add". @@ -22,47 +17,47 @@ ControlWidget - + Solver Control - + Working Directory - + Write - + Edit - + Elapsed Time: - + Run - + Re-write - + Re-run - + Abort @@ -70,67 +65,32 @@ GeometryElementsSelection - + Geometry reference selector for a - - Geometry reference selector for a - - - - + Add - - - Click on "Add" and select geometric elements to add them to the list. If no geometry is added to the list, all remaining ones are used. The following geometry elements are allowed to select: - - - - - Click on "Add" and select geometric elements to add them to the list. - - - - - The following geometry elements are allowed to select: - - Click on "Add" and select geometric elements to add them to the list.{}The following geometry elements are allowed to select: {}{}{} - - - If no geometry is added to the list, all remaining ones are used. - - - - - Click on "Add" and select geometric elements to add to the list. - - - - - Click on 'Add' and select geometric elements to add them to the list. - - {}If no geometry is added to the list, all remaining ones are used. - + Selection mode - + Solid @@ -138,17 +98,12 @@ SolidSelector - + Select Solids - - Select elements part of the solid that shall be added to the list. To than add the solid click "Add". - - - - + Select elements part of the solid that shall be added to the list. To add the solid click "Add". @@ -156,1310 +111,1421 @@ _Selector - + Add - + Remove - - FEM_Analysis - - - Analysis container - - - - - Creates an analysis container with standard solver CalculiX - - - - - FEM_ClippingPlaneAdd - - - Clipping plane on face - - - - - Add a clipping plane on a selected face - - - - - FEM_ClippingPlaneRemoveAll - - - Remove all clipping planes - - - - - FEM_ConstraintBodyHeatSource - - - Constraint body heat source - - - - - Creates a FEM constraint body heat source - - - - - FEM_ConstraintElectrostaticPotential - - - Constraint electrostatic potential - - - - - Creates a FEM constraint electrostatic potential - - - - - FEM_ConstraintFlowVelocity - - - Constraint flow velocity - - - - - Creates a FEM constraint flow velocity - - - - - FEM_ConstraintInitialFlowVelocity - - - Constraint initial flow velocity - - - - - Creates a FEM constraint initial flow velocity - - - - - FEM_ConstraintSelfWeight - - - Constraint self weight - - - - - Creates a FEM constraint self weight - - - - - FEM_ElementFluid1D - - - Fluid section for 1D flow - - - - - Creates a FEM Fluid section for 1D flow - - - - - FEM_ElementGeometry1D - - - Beam cross section - - - - - Creates a FEM beam cross section - - - - - FEM_ElementGeometry2D - - - Shell plate thickness - - - - - Creates a FEM shell plate thickness - - - - - FEM_ElementRotation1D - - - Beam rotation - - - - - Creates a FEM beam rotation - - - - - FEM_EquationElasticity - - - Elasticity equation - - - - - Creates a FEM equation for elasticity - - - - - FEM_EquationElectrostatic - - - Electrostatic equation - - - - - Creates a FEM equation for electrostatic - - - - - FEM_EquationFlow - - - Flow equation - - - - - Creates a FEM equation for flow - - - - - FEM_EquationFluxsolver - - - Fluxsolver equation - - - - - Creates a FEM equation for fluxsolver - - - - - FEM_EquationHeat - - - Fluxsolver heat - - - - - FEM_FEMMesh2Mesh - - - FEM mesh to mesh - - - - - Convert the surface of a FEM mesh to a mesh - - - - - FEM_MaterialFluid - - - Material for fluid - - - - - FEM material for Fluid - - - - - Creates a FEM material for Fluid - - - - - FEM_MaterialMechanicalNonlinear - - - Nonlinear mechanical material - - - - - Creates a nonlinear mechanical material - - - - - FEM_MaterialReinforced - - - Reinforced material (concrete) - - - - - FEM_MaterialSolid - - - Material for solid - - - - - FEM material for solid - - - - - FEM_MeshBoundaryLayer - - - FEM mesh boundary layer - - - - - Creates a FEM mesh boundary layer - - - - - FEM_MeshClear - - - Clear FEM mesh - - - - - Clear the Mesh of a FEM mesh object - - - - - FEM_MeshDisplayInfo - - - Display FEM mesh info - - - - - FEM_MeshGmshFromShape - - - FEM mesh from shape by Gmsh - - - - - Create a FEM mesh from a shape by Gmsh mesher - - - - - FEM mesh from shape by GMSH - - - - - Create a FEM mesh from a shape by GMSH mesher - - - - - FEM_MeshGroup - - - FEM mesh group - - - - - Creates a FEM mesh group - - - - - FEM_MeshNetgenFromShape - - - FEM mesh from shape by Netgen - - - - - FEM_MeshRegion - - - FEM mesh region - - - - - Creates a FEM mesh region - - - - - FEM_ResultShow - - - Show result - - - - - Shows and visualizes selected result data - - - - - FEM_ResultsPurge - - - Purge results - - - - - Purges all results from active analysis - - - - - FEM_SolverCalculiX - - - Solver CalculiX (experimental) - - - - - Creates a FEM solver CalculiX (experimental) - - - - - FEM_SolverCalculix - - - Solver CalculiX Standard - - - - - Creates a standard FEM solver CalculiX with ccx tools - - - - - Solver CalculiX - - - - - Creates a FEM solver CalculiX - - - - - FEM_SolverControl - - - Solver job control - - - - - Changes solver attributes and runs the calculations for the selected solver - - - - - FEM_SolverElmer - - - Solver Elmer - - - - - FEM_SolverRun - - - Run solver calculations - - - - - Runs the calculations for the selected solver - - - - - FEM_SolverZ88 - - - Solver Z88 - - - - - Creates a FEM solver Z88 - - - - - Fem_Command - - - Default Fem Command MenuText - - - - - Default Fem Command ToolTip - - - - - Material_Editor - - - Material editor - - - - - Opens the FreeCAD material editor - - - - - FEM_MeshFromShape - - - FEM mesh from shape by Netgen - - - - - Create a FEM volume mesh from a solid or face shape by Netgen internal mesher - - - - - FEM_MeshPrintInfo - - - Print FEM mesh info - - - - - FEM_BeamSection - - - Beam cross section - - - - - Creates a FEM beam cross section - - - - - FEM_FluidSection - - - Fluid section for 1D flow - - - - - Creates a FEM Fluid section for 1D flow - - - - - FEM_ShellThickness - - - Shell plate thickness - - - - - Creates a FEM shell plate thickness - - - - - Fem_Analysis - - - Analysis container - - - - - Creates a analysis container with standard solver CalculiX - - - - - New mechanical analysis - - - - - Create a new mechanical analysis - - - - - Fem_BeamSection - - - Beam cross section - - - - - Creates a FEM beam cross section - - - - - FEM Beam Cross Section Definition ... - - - - - Creates a FEM Beam Cross Section - - - - - Fem_ClearMesh - - - Clear FEM mesh - - - - - Clear the Mesh of a FEM mesh object - - - - - Fem_ConstraintSelfWeight - - - Constraint self weigt - - - - - Creates a FEM constraint self weigt - - - - - Fem_ControlSolver - - - Solver job control - - - - - Changes solver attributes and runs the calculations for the selected solver - - - - - Fem_FemMesh2Mesh - - - FEM mesh to mesh - - - - - Convert the surface of a FEM mesh to a mesh - - - - - Fem_MaterialMechanicalNonlinear - - - Nonlinear mechanical material - - - - - Creates a nonlinear mechanical material - - - - - Fem_MechanicalMaterial - - - Mechanical material - - - - - Mechanical material... - - - - - Creates a mechanical material - - - - - Creates or edit the mechanical material definition. - - - - - Fem_MeshFromShape - - - FEM mesh from shape by Netgen - - - - - Create a FEM volume mesh from a solid or face shape by Netgen internal mesher - - - - - Fem_MeshGmshFromShape - - - FEM mesh from shape by GMSH - - - - - Create a FEM mesh from a shape by GMSH mesher - - - - - Fem_MeshRegion - - - FEM mesh region - - - - - Creates a FEM mesh region - - - - - Fem_PrintMeshInfo - - - Print FEM mesh info - - - - - Fem_PurgeResults - - - Purge results - - - - - Purge results from an analysis - - - - - Purges all results from active analysis - - - - - Fem_RunAnalysis - - - Run solver calculations - - - - - Runs the calculations for the selected solver - - - - - Fem_ShellThickness - - - Shell plate thickness - - - - - Creates a FEM shell plate thickness - - - - - FEM Shell Plate Thickness Definition ... - - - - - Creates a FEM Shell Thickness - - - - - Fem_ShowResult - - - Show result - - - - - Show result information of an analysis - - - - - Shows and visualizes selected result data - - - - - Fem_SolverCalculix - - - Solver CalculiX - - - - - Creates a FEM solver CalculiX - - - - - Create FEM Solver CalculiX ... - - - - - Creates FEM Solver CalculiX - - - - - Fem_SolverZ88 - - - Solver Z88 - - - - - Creates a FEM solver Z88 - - - - - Fem_CreateFromShape - - - Create FEM mesh - - - - - Create FEM mesh from shape - - - - - Fem_NewMechanicalAnalysis - - - New mechanical analysis - - - - - Create a new mechanical analysis - - - - - Fem_Quick_Analysis - - - Run CalculiX ccx - - - - - Write .inp file and run CalculiX ccx - - - - - Fem_SolverJobControl - - - Start solver job control - - - - - Dialog to start the calculation of the selected solver - - - - - Fem_JobControl - - - Start solver job control - - - - - Dialog to start the calculation of the selected solver - - - - - Fem_Material - - - Mechanical material... - - - - - Creates or edit the mechanical material definition. - - - - - Fem_Result - - - Show result - - - - - Show result information of an analysis - - - - - CmdFemAddPart - - - Fem - Fem - - - - - Add a part to the Analysis - Add a part to the Analysis - - CmdFemConstraintBearing - + Fem - Fem + - - Create FEM bearing constraint - Create FEM bearing constraint + + Constraint bearing + - - Create FEM constraint for a bearing - Create FEM constraint for a bearing + + Creates a FEM constraint for a bearing + + + + + CmdFemConstraintContact + + + Fem + + + + + Constraint contact + + + + + Creates a FEM constraint for contact between faces + CmdFemConstraintDisplacement - + Fem - Fem + - - Create FEM displacement constraint - Create FEM displacement constraint + + Constraint displacement + - - Create FEM constraint for a displacement acting on a face - Create FEM constraint for a displacement acting on a face + + Creates a FEM constraint for a displacement acting on a geometric entity + CmdFemConstraintFixed - + Fem - Fem + - - Create FEM fixed constraint - Create FEM fixed constraint + + Constraint fixed + - - Create FEM constraint for a fixed geometric entity - Create FEM constraint for a fixed geometric entity + + Creates a FEM constraint for a fixed geometric entity + + + + + CmdFemConstraintFluidBoundary + + + Fem + + + + + Fluid boundary condition + + + + + Create fluid boundary condition on face entity for Computional Fluid Dynamics + CmdFemConstraintForce - + Fem - Fem + - - Create FEM force constraint - Create FEM force constraint + + Constraint force + - - Create FEM constraint for a force acting on a geometric entity - Create FEM constraint for a force acting on a geometric entity + + Creates a FEM constraint for a force acting on a geometric entity + CmdFemConstraintGear - + Fem - Fem + - - Create FEM gear constraint - Create FEM gear constraint + + Constraint gear + - - Create FEM constraint for a gear - Create FEM constraint for a gear + + Creates a FEM constraint for a gear + + + + + CmdFemConstraintHeatflux + + + Fem + + + + + Constraint heatflux + + + + + Creates a FEM constraint for a heatflux acting on a face + + + + + CmdFemConstraintInitialTemperature + + + Fem + + + + + Constraint initial temperature + + + + + Creates a FEM constraint for initial temperature acting on a body + + + + + CmdFemConstraintPlaneRotation + + + Fem + + + + + Constraint plane rotation + + + + + Creates a FEM constraint for plane rotation face + CmdFemConstraintPressure - + Fem - Fem + - - Create FEM pressure constraint - Create FEM pressure constraint + + Constraint pressure + - - Create FEM constraint for a pressure acting on a face - Create FEM constraint for a pressure acting on a face + + Creates a FEM constraint for a pressure acting on a face + CmdFemConstraintPulley - + Fem - Fem + - - Create FEM pulley constraint - Create FEM pulley constraint + + Constraint pulley + - - Create FEM constraint for a pulley - Create FEM constraint for a pulley + + Creates a FEM constraint for a pulley + - CmdFemCreateAnalysis + CmdFemConstraintSpring - + Fem - Fem + - - - Create a FEM analysis - Create a FEM analysis + + Constraint spring + + + + + Creates a FEM constraint for a spring acting on a face + + + + + CmdFemConstraintTemperature + + + Fem + + + + + Constraint temperature + + + + + Creates a FEM constraint for a temperature/concentrated heat flux acting on a face + + + + + CmdFemConstraintTransform + + + Fem + + + + + Constraint transform + + + + + Create FEM constraint for transforming a face + CmdFemCreateNodesSet - + Fem - Fem + - - - Define/create a nodes set... - Define/create a nodes set... + + Nodes set + - + + Creates a FEM mesh nodes set + + + + Wrong selection - Verkeerde keuse + - + Select a single FEM mesh or nodes set, please. - Select a single FEM mesh or nodes set, please. - - - - CmdFemCreateSolver - - - Fem - Fem - - - - - Add a solver to the Analysis - Add a solver to the Analysis + CmdFemDefineNodesSet - + Fem - Fem + - - - + + Node set by poly + + + + + Create node set by Poly - Create node set by Poly + - FemGui::DlgSettingsFemImp + CmdFemPostApllyChanges - - FEM - FEM + + Fem + - + + Apply changes to pipeline + + + + + Apply changes to parameters directly and not on recompute only... + + + + + CmdFemPostClipFilter + + + Fem + + + + + Region clip filter + + + + + Define/create a clip filter which uses functions to define the cliped region + + + + + Wrong selection + + + + + Select a pipeline, please. + + + + + CmdFemPostCreateDataAtPointFilter + + + Data At Point + + + + + CmdFemPostCutFilter + + + Fem + + + + + Function cut filter + + + + + Cut the data along an implicit function + + + + + CmdFemPostDataAlongLineFilter + + + Fem + + + + + Line clip filter + + + + + Define/create a clip filter which clips a field along a line + + + + + CmdFemPostDataAtPointFilter + + + Fem + + + + + Data at point clip filter + + + + + Define/create a clip filter which clips a field data at point + + + + + CmdFemPostFunctions + + + Fem + + + + + Filter functions + + + + + Functions for use in postprocessing filter... + + + + + Plane + + + + + Sphere + + + + + CmdFemPostLinearizedStressesFilter + + + Fem + + + + + Stress linearization plot + + + + + Define/create stress linearization plots + + + + + + Wrong selection + + + + + + Select a Clip filter which clips a STRESS field along a line, please. + + + + + CmdFemPostPipelineFromResult + + + Fem + + + + + Post pipeline from result + + + + + Creates a post processing pipeline from a result object + + + + + Wrong selection type + + + + + Select a result object, please. + + + + + CmdFemPostScalarClipFilter + + + Fem + + + + + Scalar clip filter + + + + + Define/create a clip filter which clips a field with a scalar value + + + + + CmdFemPostWarpVectorFilter + + + Fem + + + + + Warp filter + + + + + Warp the geometry along a vector field by a certain factor + + + + + Command + + + Make FEM constraint for bearing + + + + + Make FEM constraint contact on face + + + + + Make FEM constraint displacement on face + + + + + Make FEM constraint fixed geometry + + + + + Create fluid boundary condition + + + + + Make FEM constraint force on geometry + + + + + Make FEM constraint for gear + + + + + Make FEM constraint heatflux on face + + + + + Make FEM constraint initial temperature on body + + + + + Make FEM constraint Plane Rotation face + + + + + Make FEM constraint pressure on face + + + + + Make FEM constraint spring on face + + + + + Make FEM constraint for pulley + + + + + Make FEM constraint temperature on face + + + + + Make FEM constraint transform on face + + + + + Place robot + + + + + Edit nodes set + + + + + Create nodes set + + + + + Create filter + + + + + Create function + + + + + Create pipeline from result + + + + + Edit Mirror + + + + + Dialog + + + + + Dialog + + + + + Mesh groups detected. Please choose values for the different groups. + + + + + Id + + + + + Label + + + + + Elements + + + + + Not Marked + + + + + Marked + + + + + Select the vertices, lines and surfaces: + + + + + + Temperature: + + + + + + 25 + + + + + + ºC + + + + + Add + + + + + Remove + + + + + Insert component's + initial temperature: + + + + + FEM_PostCreateFunctions + + + Create a plane function, defined by its origin and normal + + + + + Create a sphere function, defined by its center and radius + + + + + FemGui::DlgSettingsFemCcxImp + + + CalculiX - CalculiX + - - Use internal editor for .inp files - Use internal editor for .inp files - - - - External editor: - External editor: - - - + Leave blank to use default CalculiX ccx binary file - Leave blank to use default CalculiX ccx binary file + - - ccx binary - ccx binary + + Input file Editor + - - Working directory - Working directory + + Use internal editor for *.inp files + - - Default analysis settings - Default analysis settings + + External editor: + - - Default type on analysis - Default type on analysis + + Search in known binary directories + - - Static - Static + + ccx binary path + - - Frequency - Frequency + + Input file splitting + - - Eigenmode number - Eigenmode number + + Split writing of *.inp + - + + CalculiX binary + + + + + Analysis defaults + + + + Type - Soort + - + + Default type on analysis + + + + + Static + + + + + Frequency + + + + + Thermomech + + + + + Solver defaults + + + + + Time incrementation control parameter + + + + + Use non ccx defaults + + + + + Use non-linear geometry + + + + + Matrix solver + + + + + Number of CPU's to use (Spooles only) + + + + + Non-linear geometry + + + + + Default + + + + + Spooles + + + + + Iterative Scaling + + + + + Iterative Cholesky + + + + + Time Initial Step + + + + + Time End + + + + + 3D Output, unchecked for 2D + + + + + Beam, shell element 3D output format + + + + + Thermo mechanical defaults + + + + + Maximum number of iterations + + + + + Use steady state + + + + + Analysis type (transient or steady state) + + + + + Frequency defaults + + + + + Eigenmode number + + + + High frequency limit - High frequency limit + - + Low frequency limit - Low frequency limit + - - + + Hz - Hz + + + + + FemGui::DlgSettingsFemElmerImp + + + Elmer + - - Materials - Materials + + Elmer binaries + - + + Leave blank to use default ElmerGrid binary file + + + + + ElmerSolver binary path + + + + + ElmerGrid binary path + + + + + ElmerGrid: + + + + + + Search in known binary directories + + + + + ElmerSolver: + + + + + Leave blank to use default Elmer elmer binary file + + + + + FemGui::DlgSettingsFemExportAbaqus + + + INP + + + + + Export + + + + + Mesh groups are exported too. +Every constraint and, if there are different materials, material +consists of two mesh groups, faces and nodes where the +constraint or material is applied. + + + + + Export group data + + + + + All: All elements will be exported. + +Highest: Only the highest elements will be exported. This means +for means volumes for a volume mesh and faces for a shell mesh. + +FEM: Only FEM elements will be exported. This means only edges +not belonging to faces and faces not belonging to volumes. + + + + + element parameter: All: all elements, highest: highest elements only, FEM: FEM elements only (only edges not belonging to faces and faces not belonging to volumes) + + + + + All + + + + + Highest + + + + + FEM + + + + + Which mesh elements to export + + + + + FemGui::DlgSettingsFemGeneralImp + + + General + + + + + Working directory for solving analysis and gmsh meshing + + + + + sdfsdfsdfds + + + + + Temporary directories + + + + + Let the application manage (create, delete) the working directories for all solver. Use temporary directories. + + + + + Beside .FCStd file + + + + + Create a directory in the same folder in which the FCStd file of the document is located. Use Subfolder for each solver (e.g. for a file ./mydoc.FCStd and a solver with the label Elmer002 use ./mydoc/Elmer002). + + + + + Use custom directory + + + + + Use directory set below. Create own subdirectory for every solver. Name directory after the solver label prefixed with the document name. + + + + + Path: + + + + + Overwrite solver working directory with the directory chosen above + + + + + Mesh + + + + + Create mesh groups for analysis reference shapes (highly experimental) + + + + + Results + + + + + Keep results on calculation re-run + + + + + Restore result dialog settings + + + + + Hide constraints when open result dialog + + + + + FemGui::DlgSettingsFemGmshImp + + + Gmsh + + + + + Gmsh binary + + + + + Search in known binary directories + + + + + gmsh + + + + + gmsh binary path + + + + + Leave blank to use default gmsh binary file + + + + + FemGui::DlgSettingsFemInOutVtk + + + VTK + + + + + Import + + + + + Which object to import into + + + + + VTK result object: A FreeCAD FEM VTK result object will be imported +(equals to the object which was exported). + +FEM mesh object: The results in the VTK file will be omitted, only the +mesh data will be imported and a FreeCAD FEM mesh object will be created. + +FreeCAD result object: The imported data will be converted into a +FreeCAD FEM Result object. Note: this setting needs the exact result +component names and thus it only works properly with VTK files +exported from FreeCAD. + + + + + Choose in which object to import into + + + + + VTK result object + + + + + FEM mesh object + + + + + FreeCAD result object + + + + + FemGui::DlgSettingsFemMaterialImp + + + Material + + + + + Card resources + + + + Use built-in materials - Use built-in materials + - - Use materials from .FreeCAD/Materials directory - Use materials from .FreeCAD/Materials directory + + Use materials from Materials directory in users FreeCAD user pref directory. + - + Use materials from user defined directory - Use materials from user defined directory + - + User directory - User directory + + + + + Card sorting and duplicates + + + + + Delete card duplicates + + + + + Sort by resources (opposite would be sort by cards) + + + + + FemGui::DlgSettingsFemMystranImp + + + + Mystran + + + + + Mystran binary + + + + + Search in known binary directories + + + + + Mystran binary path + + + + + Leave blank to use default Mystran binary file location + + + + + Comments + + + + + write comments to input file + + + + + FemGui::DlgSettingsFemZ88Imp + + + Z88 + + + + + Z88 binary + + + + + Search in known binary directories + + + + + z88r + + + + + z88r binary path + + + + + Leave blank to use default Z88 z88r binary file + FemGui::TaskAnalysisInfo - + Nodes set - Nodes set + FemGui::TaskCreateNodeSet - + Nodes set - Nodes set + FemGui::TaskDlgFemConstraint - - + + Input error - Invoerfout + - + You must specify at least one reference - You must specify at least one reference + FemGui::TaskDlgFemConstraintBearing - + Input error - Invoerfout + + + + + FemGui::TaskDlgFemConstraintContact + + + Input error + @@ -1467,691 +1533,2019 @@ Input error - Invoerfout + + + + + FemGui::TaskDlgFemConstraintFluidBoundary + + + Input error + FemGui::TaskDlgFemConstraintForce - - + + Input error - Invoerfout + - + Please specify a force greater than 0 - Please specify a force greater than 0 + FemGui::TaskDlgFemConstraintGear - + Input error - Invoerfout + + + + + FemGui::TaskDlgFemConstraintHeatflux + + + Input error + + + + + FemGui::TaskDlgFemConstraintInitialTemperature + + + + Input error + FemGui::TaskDlgFemConstraintPressure - - + Input error - Invoerfout - - - - Please specify a pressure greater than 0 - Please specify a pressure greater than 0 + FemGui::TaskDlgFemConstraintPulley - + Input error - Invoerfout + + + + + FemGui::TaskDlgFemConstraintSpring + + + Input error + + + + + FemGui::TaskDlgFemConstraintTemperature + + + Input error + + + + + FemGui::TaskDlgFemConstraintTransform + + + Input error + FemGui::TaskDlgMeshShapeNetgen - + Edit FEM mesh - Edit FEM mesh + - + Meshing failure - Meshing failure + + + + + FemGui::TaskDlgPost + + + Input error + FemGui::TaskDriver - + Nodes set - Nodes set + FemGui::TaskFemConstraint - + FEM constraint parameters - FEM constraint parameters + + + + + Delete + FemGui::TaskFemConstraintBearing - - Delete - Vee uit - - - - - - - - + + + + + + Selection error - Selection error + - + Please use only a single reference for bearing constraint - Please use only a single reference for bearing constraint + - + Only faces can be picked - Only faces can be picked + - + Only cylindrical faces can be picked - Only cylindrical faces can be picked + - + Only planar faces can be picked - Only planar faces can be picked + - + Only linear edges can be picked - Only linear edges can be picked + - + Only faces and edges can be picked - Only faces and edges can be picked + + + + + FemGui::TaskFemConstraintContact + + + + Delete + + + + + + + + + + + + + + + + + + + + + Selection error + + + + + Only one face in object! - moved to master face + + + + + + Only one master face and one slave face for a contact constraint! + + + + + + + + Nothing selected! + + + + + + Only one slave face for a contact constraint! + + + + + + + + Selected object is not a part! + + + + + + Only faces can be picked + + + + + Only one master for a contact constraint! + + + + + Only one master face for a contact constraint! + FemGui::TaskFemConstraintDisplacement - - Delete - Vee uit - - - - - - + + + + + Selection error - Selection error + - - + + Nothing selected! - Nothing selected! + - - + + Selected object is not a part! - Selected object is not a part! + + + + + Only one type of selection (vertex,face or edge) per constraint allowed! + FemGui::TaskFemConstraintFixed - - Delete - Vee uit - - - - + + + + + Selection error - Selection error + - - Mixed shape types are not possible. Use a second constraint instead - Mixed shape types are not possible. Use a second constraint instead + + + Nothing selected! + - - Only faces, edges and vertices can be picked - Only faces, edges and vertices can be picked + + + Selected object is not a part! + + + + + Only one type of selection (vertex,face or edge) per constraint allowed! + + + + + FemGui::TaskFemConstraintFluidBoundary + + + Basic + + + + + Turbulence + + + + + Thermal + + + + + select boundary type, faces and set value + + + + + Intensity [0~1] + + + + + Dissipation Rate [m2/s3] + + + + + Length Scale[m] + + + + + Viscosity Ratio [1] + + + + + Hydraulic Diameter [m] + + + + + + Gradient [K/m] + + + + + Flux [W/m2] + + + + + Empty selection + + + + + Select an edge or a face, please. + + + + + + + + + Wrong selection + + + + + Selected object is not a part object! + + + + + Only one planar face or edge can be selected! + + + + + Only planar faces can be picked for 3D + + + + + Only planar edges can be picked for 2D + + + + + Only faces for 3D part or edges for 2D can be picked + + + + + + + + + Selection error + + + + + + Nothing selected! + + + + + + Selected object is not a part! + + + + + Only one type of selection (vertex,face or edge) per constraint allowed! + FemGui::TaskFemConstraintForce - - Delete - Vee uit - - - - Point load - Point load - - - - Line load - Line load - - - - Area load - Area load - - - - - - - + + + + + Selection error - Selection error + - - Mixed shape types are not possible. Use a second constraint instead - Mixed shape types are not possible. Use a second constraint instead + + + Nothing selected! + - - Only faces, edges and vertices can be picked - Only faces, edges and vertices can be picked + + + Selected object is not a part! + - - Only planar faces can be picked - Only planar faces can be picked + + Only one type of selection (vertex,face or edge) per constraint allowed! + - - Only linear edges can be picked - Only linear edges can be picked + + + Wrong selection + - - Only faces and edges can be picked - Only faces and edges can be picked + + Select an edge or a face, please. + FemGui::TaskFemConstraintGear - - - + + + Selection error - Selection error + - + Only planar faces can be picked - Only planar faces can be picked + - + Only linear edges can be picked - Only linear edges can be picked + - + Only faces and edges can be picked - Only faces and edges can be picked + + + + + FemGui::TaskFemConstraintHeatflux + + + + + + + + Selection error + + + + + + Nothing selected! + + + + + + Selected object is not a part! + + + + + + Selection must only consist of faces! + + + + + FemGui::TaskFemConstraintPlaneRotation + + + + + + + + + + Selection error + + + + + + Only one face can be selected for a plane rotation constraint! + + + + + + Nothing selected! + + + + + + Selected object is not a part! + + + + + Only faces can be picked + + + + + Only planar faces can be picked + FemGui::TaskFemConstraintPressure - - Delete - Vee uit - - - + + + + + Selection error - Selection error + - + + + Nothing selected! + + + + + + Selected object is not a part! + + + + Only faces can be picked - Only faces can be picked + FemGui::TaskFemConstraintPulley - + Pulley diameter - Pulley diameter + - + Torque [Nm] - Torque [Nm] + + + + + FemGui::TaskFemConstraintSpring + + + + + + + Selection error + + + + + + Nothing selected! + + + + + + Selected object is not a part! + + + + + Only faces can be picked + + + + + FemGui::TaskFemConstraintTemperature + + + + + + Selection error + + + + + + Nothing selected! + + + + + + Selected object is not a part! + + + + + FemGui::TaskFemConstraintTransform + + + Constraint update error + + + + + The transformable faces have changed. Please add only the transformable faces and remove non-transformable faces! + + + + + + + + + + + + + + Selection error + + + + + + Nothing selected! + + + + + + Only one face for rectangular transform constraint! + + + + + + Selected object is not a part! + + + + + Only one face for transform constraint! + + + + + Only faces can be picked + + + + + Only cylindrical faces can be picked + + + + + Only transformable faces can be selected! Apply displacement constraint to surface first then apply constraint to surface + FemGui::TaskObjectName - + TaskObjectName - TaskObjectName + + + + + FemGui::TaskPostClip + + + Clip region, choose implicit function + + + + + FemGui::TaskPostCut + + + Function cut, choose implicit function + + + + + FemGui::TaskPostDataAlongLine + + + Data along a line options + + + + + FemGui::TaskPostDataAtPoint + + + Data at point options + + + + + FemGui::TaskPostDisplay + + + Result display options + + + + + FemGui::TaskPostFunction + + + Implicit function + + + + + FemGui::TaskPostScalarClip + + + Scalar clip options + + + + + FemGui::TaskPostWarpVector + + + Warp options + FemGui::TaskTetParameter - + Tet Parameter - Tet Parameter + FemGui::ViewProviderFemAnalysis - + Activate analysis - Activate analysis + FemGui::ViewProviderFemMeshShapeNetgen - + Meshing failure - Meshing failure + - + The FEM module is built without NETGEN support. Meshing will not work!!! - The FEM module is built without NETGEN support. Meshing will not work!!! + + + + + FemMaterial + + + + FEM material + + + + + + + Material + + + + + Category + + + + + choose... + + + + + Material card + + + + + Material name + + + + + + + TextLabel + + + + + Material Description + + + + + Editing material + + + + + use FreeCAD material editor + + + + + use this task panel + + + + + Basic Properties + + + + + Density + + + + + 8000 kg/m^3 + + + + + Mechanical Properties + + + + + Young's Modulus: + + + + + 200 GPa + + + + + Poisson Ratio: + + + + + Fluidic Properties + + + + + Kinematic viscosity: + + + + + 0.000001 m^2/s + + + + + Thermal Properties + + + + + Thermal Conductivity: + + + + + 50 W/m/K + + + + + Expansion Coefficient: + + + + + 12 um/m/K + + + + + Specific Heat: + + + + + 500 J/kg/K + + + + + Vol Expansion Coeff + + + + + 0.001 m/m/K + + + + + Matrix Material + + + + + + Choose + + + + + + Name + + + + + + Edit + + + + + + Properties + + + + + + Description + + + + + Reinforcement Material + Form - - + Form - Vorm + - - Cross Section - Cross Section + + Fluid Section Parameter + - - - Use FreeCAD Property Editor - Use FreeCAD Property Editor + + Liquid Section Parameter + - - to edit the cross section values - to edit the cross section values + + Pipe Area + - - - References - References + + + + + + + + + + + + + 0 mm^2 + - - - Leave references blank - Leave references blank + + + Hydraulic Radius + - - - to choose all remaining shapes - to choose all remaining shapes + + + + 0 mm + - - - Add reference - Add reference + + Manning Coefficient + - - Thickness - Dikte + + + Initial Area + - - to edit the thickness value - to edit the thickness value + + Enlarged Area + + + + + Contracted Area + + + + + Inlet Pressure + + + + + + Pressure + + + + + Inlet Mass Flow Rate + + + + + + Mass flow rate + + + + + + 1 kg/s + + + + + Outlet Pressure + + + + + Outlet Mass Flow Rate + + + + + + + + + Pipe Area + + + + + Entrance Area + + + + + Diaphragm Area + + + + + Bend Radius/Pipe Diameter + + + + + Bend Angle + + + + + Head loss coefficient + + + + + Gate valve closing coefficient + + + + + Pump Characteristic + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + Flow rate [mm^3/s] + + + + + Head Loss[mm] + + + + + Grain diameter + + + + + Cross section form factor + + + + + Gas Section Parameter + + + + + Open Channel Section Parameter + + + + + Centrif parameter + + + + + + + + + Parameter + + + + + Rotation frequency f<sub>rot</sub> [rps] + + + + + revolutions per second + + + + + + + + + + + + + + 0.0 + + + + + 1/s + + + + + SectionPrint parameter + + + + + Tie parameter + + + + + Tolerance: + + + + + + + Constraint Properties + + + + + Potential: + + + + + Potential Constant + + + + + Farfield / Electric infinity + + + + + + + + + + + + unspecified + + + + + V + + + + + Capacity Body: + Enabled by 'Calculate Capacity Matrix' in Electrostatic equation + + + + + Calculate Electric Force + + + + + Beam section parameter + + + + + + Cross section parameter + + + + + Width: + + + + + Height: + + + + + + Diameter: + + + + + Thickness: + + + + + Shell thickness parameter + + + + + Thickness: + + + + + Beam section rotation + + + + + Rotation: + + + + + + Velocity x: + + + + + + Velocity y: + + + + + + Velocity z: + + + + + + + + + + m/s + + + + + normal to boundary + + + + + Mesh boundary layer settings + + + + + Max Layers + + + + + 1.0 + + + + + Min/1st thickness + + + + + Growth ratio + + + + + Mesh group + + + + + Identifier used for mesh export + + + + + Name + + + + + Label + + + + + Mesh region + + + + + Max element size: + - MechanicalMaterial + GmshMesh - - Mechanical analysis - Mechanical analysis + + FEM Mesh by Gmsh + - - Working directory - Working directory + + FEM Mesh Parameter + - - ... - ... + + Element dimension: + - - Analysis type - Analysis type + + Max element size (0.0 = Auto): + - - Static - Static + + + 0.0 + - - Frequency - Frequency + + Min element size (0.0 = Auto): + - - Write .inp file - Write .inp file + + Element order: + - - Edit .inp file - Edit .inp file + + Gmsh + - - Run Calculix - Run Calculix - - - + Time: - Time: + - - Mechanical material - Mechanical material + + Gmsh version + + + + + PlaneWidget + + + Form + - - Material - Materiaal + + Origin + - - choose... - choose... - - - - Material Description - Material Description - - - - References - References - - - - Leave references blank - Leave references blank - - - - to choose all remaining shapes - to choose all remaining shapes - - - - Add reference - Add reference - - - - Properties - Properties - - - - Young's Modulus: - Young's Modulus: - - - - Poisson Ratio: - Poisson Ratio: - - - - Density - Density - - - - External material resources - External material resources - - - - MatWeb database... - MatWeb database... + + Normal + QObject - + No active Analysis - No active Analysis + - + You need to create or activate a Analysis - You need to create or activate a Analysis + - - - - - - Wrong selection - Verkeerde keuse - - - - - - Your FreeCAD is build without NETGEN support. Meshing will not work.... - Your FreeCAD is build without NETGEN support. Meshing will not work.... - - - - - Select an edge, face or body. Only one body is allowed. - Kies 'n rand, vlak of liggaam. Slegs een liggaam word toegelaat. - - - - - Wrong object type - Verkeerde voorwerpsoort - - - - - Fillet works only on parts - Ronding werk slegs op onderdele - - - + Ok - Ok + - + Cancel - Kanselleer + - + Edit constraint - Edit constraint + - - - - - + + + + + + + + A dialog is already open in the task panel - 'n Dialoog is reeds oop in die taakpaneel + - - - - - + + + + + + + + Do you want to close this dialog? - Wil jy hierdie dialoog toe maak? + - + Meshing - Meshing + - + Constraint force - Constraint force + - - - Constraint normal stress - Constraint normal stress + + + + + + + + FEM + - - [Nodes: %1, Edges: %2, Faces: %3, Polygons: %4, Volumes: %5, Polyhedrons: %6] - [Nodes: %1, Edges: %2, Faces: %3, Polygons: %4, Volumes: %5, Polyhedrons: %6] + + + Import-Export + + + + + [Nodes: %1, Edges: %2, Faces: %3, Polygons: %4, Volumes: %5, Polyhedrons: %6, Groups: %7] + + + + + Constraint Contact + + + + + Constraint displacement + + + + + Constraint fixed + + + + + Constraint fluid boundary + + + + + Constraint heat flux + + + + + Constraint initial temperature + + + + + Constraint planerotation + + + + + Constraint pressure + + + + + Constraint pulley + + + + + Constraint spring + + + + + Constraint temperature + + + + + Constraint transform + + + + + Edit post processing object + ShowDisplacement - + Show result - Show result + - + Result type - Result type + - - Y displacement - Y displacement + + Displacement Magnitude + - - X displacement - X displacement - - - - Z displacement - Z displacement - - - + None - Geen + - - Von Mises stress - Von Mises stress + + Displacement Y + - - Abs displacement - Abs displacement + + Displacement X + - - Avg: - Avg: + + Peeq + - - Max: - Max: + + Displacement Z + - + + Temperature + + + + + von Mises Stress + + + + + Max Principal Stress + + + + + Min Principal Stress + + + + + Max Shear Stress (Tresca) + + + + + Mass Flow Rate + + + + + Network Pressure + + + + Min: - Min: + - + + Max: + + + + + Histogram + + + + Displacement - Displacement + - + Show - Show + - + Factor: - Factor: + - + Slider max: - Slider max: + + + + + User defined equation + + + + + Calculate and plot + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">P1-P3 # Stress intensity stress equation. Available values are numpy array format. Calculation np.function can be used on available values. </span></p></body></html> + + + + + Hints user defined equations + + + + + Available result types: + + + + + displacement: x, y, z + + + + + mass flow rate: MF + + + + + network pressure: NP + + + + + von Mises stress: vM + + + + + temperature: T + + + + + min. principal stress vector: s1x, s1y, s1z + + + + + principal stresses: P1, P2, P3 + + + + + reinforcement ratio: rx, ry, rz + + + + + equivalent plastic strain: Peeq + + + + + med. principal stress vector: s2x, s2y, s2z + + + + + stress: sxx, syy, szz, sxy, sxz, syz + + + + + strain: exx, eyy, ezz, exy, exz, eyz + + + + + Mohr Coulomb: mc + + + + + max. principal stress vector: s3x, s3y, s3z + + + + + SolverCalculix + + + Mechanical analysis + + + + + Working directory + + + + + ... + + + + + Analysis type + + + + + Thermo mechanical + + + + + Check Mesh + + + + + Frequency + + + + + Static + + + + + Buckling + + + + + Write .inp file + + + + + Edit .inp file + + + + + Run CalculiX + + + + + Time: + + + + + SphereWidget + + + Form + + + + + Radius + + + + + Center + @@ -2159,17 +3553,17 @@ Form - Vorm + Meshes: - Meshes: + Constraints - Beperkings + @@ -2177,57 +3571,57 @@ Form - Vorm + Volume - Volume + Surface - Surface + Nodes: 0 - Nodes: 0 + Poly - Poly + Box - Boks + Pick - Pick + Add - Voeg by + Angle-search - Angle-search + - Collect adjancent nodes - Collect adjancent nodes + Collect adjacent nodes + Stop angle: - Stop angle: + @@ -2235,7 +3629,7 @@ Form - Vorm + @@ -2243,52 +3637,52 @@ Form - Vorm + Add reference - Add reference + Load [N] - Load [N] + Diameter - Diameter + Other diameter - Other diameter + Center distance - Center distance + Direction - Rigting + Reverse direction - Omgekeerde rigting + Location - Location + Distance - Afstand + @@ -2296,72 +3690,112 @@ Form - Vorm + Add reference - Add reference + Gear diameter - Gear diameter + - Other pulley dia - Other pulley dia + Other pulley diameter + Center distance - Center distance + Force - Force + Belt tension force - Belt tension force + Driven pulley - Driven pulley + Force location [deg] - Force location [deg] + Force Direction - Force Direction + Reversed direction - Reversed direction + Axial free - Axial free + Location - Location + Distance - Afstand + + + + + TaskFemConstraintContact + + + Form + + + + + Select master face, click Add or Remove + + + + + + Add + + + + + + Remove + + + + + Select slave face, click Add or Remove + + + + + Contact Stiffness + + + + + Friction coefficient + @@ -2369,27 +3803,27 @@ Prescribed Displacement - Prescribed Displacement + Select multiple face(s), click Add or Remove - Select multiple face(s), click Add or Remove + Add - Voeg by + Remove - Verwyder + Displacement x - Displacement x + @@ -2399,7 +3833,7 @@ Free - Free + @@ -2409,37 +3843,37 @@ Fixed - Fixed + Displacement y - Displacement y + Displacement z - Displacement z + Rotations are only valid for Beam and Shell elements. - Rotations are only valid for Beam and Shell elements. + Rotation x - Rotation x + Rotation y - Rotation y + Rotation z - Rotation z + @@ -2447,40 +3881,281 @@ Form - Vorm + - Add reference - Add reference + Select multiple face(s), click Add or Remove + + + + + Add + + + + + Remove + + + + + TaskFemConstraintFluidBoundary + + + Form + + + + + Boundary + + + + + Subtype + + + + + Select multiple face(s), click Add or Remove + + + + + Add + + + + + Remove + + + + + Help text + + + + + Tab 1 + + + + + Value [Unit] + + + + + Select a planar edge or face, then press this button + + + + + Direction + + + + + The direction of the edge or the direction of the +normal vector of the face is used as direction + + + + + Reverse direction + + + + + Page + + + + + Turbulence specification + + + + + Intensity + + + + + Length [m] + + + + + Tab 2 + + + + + Type + + + + + Temperature[K] + + + + + Heat flux [W/m2] + + + + + HT coeff + TaskFemConstraintForce - - - Form - Vorm - - - - Add reference - Add reference - + Prescribed Force + + + + + Select multiple face(s), click Add or Remove + + + + + Add + + + + + Remove + + + + Load [N] - Load [N] + - + + Select a planar edge or face, then press this button + + + + Direction - Rigting + - + + The direction of the edge or the direction of the +normal vector of the face is used as direction + + + + Reverse direction - Omgekeerde rigting + + + + + TaskFemConstraintHeatflux + + + TaskFemConstraintHeatflux + + + + + Select multiple face(s), click Add or Remove: + + + + + Add + + + + + Remove + + + + + Surface Convection + + + + + + Surface heat flux + + + + + Film coefficient + + + + + 1 W/m^2/K + + + + + Ambient Temperature + + + + + + 300 K + + + + + TaskFemConstraintInitialTemperature + + + Dialog + + + + + Insert component's initial temperature: + + + + + 300 K + + + + + TaskFemConstraintPlaneRotation + + + Form + + + + + Select a single face, click Add or Remove + + + + + Add + + + + + Remove + @@ -2488,27 +4163,168 @@ Form - Vorm + - Add reference - Add reference + Select multiple face(s), click Add or Remove + - + + Add + + + + + Remove + + + + Pressure - Pressure + - - 1 MPa - 1 MPa + + 0 MPa + - - Reverse direction - Omgekeerde rigting + + Reverse Direction + + + + + TaskFemConstraintSpring + + + Form + + + + + Select multiple face(s), click Add or Remove + + + + + Add + + + + + Remove + + + + + 0 + + + + + Normal Stiffness + + + + + Tangential Stiffness + + + + + TaskFemConstraintTemperature + + + Form + + + + + Select multiple face(s), click Add or Remove + + + + + Add + + + + + Remove + + + + + + Temperature + + + + + Concentrated heat flux + + + + + 300 K + + + + + TaskFemConstraintTransform + + + Form + + + + + Rectangular transform + + + + + Cylindrical transform + + + + + Select a face, click Add or Remove + + + + + Add + + + + + Remove + + + + + Rotation about X-Axis + + + + + Rotation about Y-Axis + + + + + Rotation about Z-Axis + + + + + + Transformable surfaces + @@ -2516,7 +4332,292 @@ Form - Vorm + + + + + TaskPostClip + + + Form + + + + + Create + + + + + Inside Out + + + + + Cut Cells + + + + + TaskPostCut + + + Form + + + + + Create + + + + + TaskPostDataAlongLine + + + Form + + + + + Point1 + + + + + Point2 + + + + + Select Points + + + + + Resolution + + + + + Mode + + + + + Field + + + + + Vector + + + + + Create Plot + + + + + TaskPostDataAtPoint + + + Form + + + + + Center + + + + + Select Point + + + + + Field + + + + + TaskPostDisplay + + + Form + + + + + Mode + + + + + + Outline + + + + + + Surface + + + + + + Surface with Edges + + + + + + Wireframe + + + + + Coloring + + + + + Field + + + + + Vector + + + + + Magnitute + + + + + X + + + + + Y + + + + + Z + + + + + Styling + + + + + Transparency + + + + + TaskPostScalarClip + + + Form + + + + + Scalar + + + + + Outline + + + + + Surface + + + + + Surface with Edges + + + + + Wireframe + + + + + Min scalar + + + + + Clip scalar + + + + + Max scalar + + + + + -100000 + + + + + 0 + + + + + Clip inside out + + + + + TaskPostWarpVector + + + Form + + + + + Vector + + + + + warp vectors + + + + + Min warp + + + + + Warp factor + + + + + Max warp + @@ -2524,87 +4625,87 @@ Form - Vorm + Max. Size: - Max. Size: + Second order - Second order + Fineness: - Fineness: + VeryCoarse - VeryCoarse + Coarse - Coarse + Moderate - Moderate + Fine - Fine + VeryFine - VeryFine + UserDefined - UserDefined + Growth Rate: - Growth Rate: + Nbr. Segs per Edge: - Nbr. Segs per Edge: + Nbr. Segs per Radius: - Nbr. Segs per Radius: + Optimize - Optimize + Node count: - Node count: + Triangle count: - Triangle count: + - Tetraeder count: - Tetraeder count: + Tetrahedron count: + @@ -2612,12 +4713,170 @@ FEM - FEM + &FEM - &FEM + + + + + Model + + + + + M&odel + + + + + Materials + + + + + &Materials + + + + + Element Geometry + + + + + &Element Geometry + + + + + Electrostatic Constraints + + + + + &Electrostatic Constraints + + + + + Fluid Constraints + + + + + &Fluid Constraints + + + + + Geometrical Constraints + + + + + &Geometrical Constraints + + + + + Mechanical Constraints + + + + + &Mechanical Constraints + + + + + Thermal Constraints + + + + + &Thermal Constraints + + + + + Constraints without solver + + + + + &Constraints without solver + + + + + Overwrite Constants + + + + + &Overwrite Constants + + + + + Mesh + + + + + M&esh + + + + + Solve + + + + + &Solve + + + + + Results + + + + + &Results + + + + + Filter functions + + + + + &Filter functions + + + + + Utilities + + + + + setupFilter + + + Error: Wrong or no or to many vtk post processing objects. + + + + + The filter could not set up. Select one vtk post processing pipeline object, or select nothing and make sure there is exact one vtk post processing pipline object in the document. + From ef7127a4563111021c024aa0ff001bf682330e9f Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 30 Sep 2021 15:03:26 -0500 Subject: [PATCH 010/101] [Tools] Strip translations from base TS files --- src/Tools/updatets.py | 45 ++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/Tools/updatets.py b/src/Tools/updatets.py index 8cd1e14d22..0c344e6f1f 100755 --- a/src/Tools/updatets.py +++ b/src/Tools/updatets.py @@ -146,37 +146,32 @@ def update_translation(entry): print (f"EXTRACTING STRINGS FOR {entry['tsname']}") print ("=============================================") cur = os.getcwd() + log_redirect = f" 2>> {cur}/tsupdate_stderr.log 1>> {cur}/tsupdate_stdout.log" os.chdir(entry["workingdir"]) existingjsons = [f for f in os.listdir(".") if f.endswith(".json")] - filename = entry["tsname"] + ".pro" - print("Running qmake -project") - os.system(f"{QMAKE} -project -o {filename}") - #only update the master ts file + project_filename = entry["tsname"] + ".pro" tsBasename = os.path.join(entry["tsdir"],entry["tsname"]) - mainTranslation = f"{LUPDATE} {filename} -ts {tsBasename}.ts" - print(mainTranslation) - os.system(mainTranslation) - os.remove(filename) + + execline = [] + execline.append (f"{QMAKE} -project -o {project_filename}") + execline.append (f"sed 's/.*<\/translation>/<\/translation>/g' {tsBasename}.ts > {tsBasename}.ts.temp") + execline.append (f"touch {tsBasename}.ts") # In case it didn't get created above + execline.append (f"{LUPDATE} {project_filename} -ts {tsBasename}.ts {log_redirect}") + execline.append (f"mv {tsBasename}.ts.temp {tsBasename}.ts") + execline.append (f"{PYLUPDATE} `find ./ -name \"*.py\"` -ts {tsBasename}py.ts {log_redirect}") + execline.append (f"{LCONVERT} -i {tsBasename}py.ts {tsBasename}.ts -o {tsBasename}.ts {log_redirect}") + execline.append (f"rm {tsBasename}py.ts") + print(f"Executing special commands in {entry['workingdir']}:") + for line in execline: + print (line) + os.system(line) + print() + + os.remove(project_filename) # lupdate creates json files since Qt5.something. Remove them here too for jsonfile in [f for f in os.listdir(".") if f.endswith(".json")]: if not jsonfile in existingjsons: os.remove(jsonfile) - - # Also try to do a python lupdate - execline0 = f"touch {tsBasename}.ts" # In case it didn't get created above - execline1 = f"{PYLUPDATE} `find ./ -name \"*.py\"` -ts {tsBasename}py.ts" - execline2 = f"{LCONVERT} -i {tsBasename}py.ts {tsBasename}.ts -o {tsBasename}.ts" - execline3 = f"rm {tsBasename}py.ts" - print(f"Executing special commands in {entry['workingdir']}:") - print(execline0) - os.system(execline0) - print(execline1) - os.system(execline1) - print(execline2) - os.system(execline2) - print(execline3) - os.system(execline3) - print() os.chdir(cur) @@ -192,6 +187,8 @@ def main(): for i in directories: update_translation(i) print("\nIf updatets.py was run successfully, the next step is to run ./src/Tools/updatecrowdin.py") + print("stderr output from lupdate can be found in tsupdate_stderr.log") + print("stdout output from lupdate can be found in tsupdate_stdout.log") if __name__ == "__main__": main() From 19084494e84eb77c8082b7be0b84dbd0eb0f2ac2 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 2 Oct 2021 09:42:49 +0200 Subject: [PATCH 011/101] Update init_tools.py Removed the temp code. Changed the order of the functions. Only one item per line to make the lists more legible. --- src/Mod/Draft/draftutils/init_tools.py | 130 ++++++++----------------- 1 file changed, 39 insertions(+), 91 deletions(-) diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index a2c5454db1..9a5f226dff 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -36,18 +36,6 @@ from PySide.QtCore import QT_TRANSLATE_NOOP def get_draft_drawing_commands(): - """Return the drawing commands list.""" - return ["Draft_Line", "Draft_Wire", "Draft_Fillet", - "Draft_ArcTools", - "Draft_Circle", "Draft_Ellipse", "Draft_Rectangle", - "Draft_Polygon", "Draft_BSpline", "Draft_BezierTools", - "Draft_Point", "Draft_Facebinder", - "Draft_ShapeString","Draft_Hatch"] - - -# This function replaces get_draft_drawing_commands. -# The "_temp" suffix should be removed when the BIM Workbench has been updated. -def get_draft_drawing_commands_temp(): """Return the drawing commands list.""" from draftguitools import gui_arcs from draftguitools import gui_beziers @@ -76,53 +64,13 @@ def get_draft_drawing_commands_temp(): def get_draft_annotation_commands(): """Return the annotation commands list.""" - return ["Draft_Text", "Draft_Dimension", - "Draft_Label", "Draft_AnnotationStyleEditor"] - - -def get_draft_array_commands(): - """Return the array commands list.""" - return ["Draft_ArrayTools"] - - -# This function has been replaced by get_draft_utility_commands_toolbar. -# It should be removed when the BIM Workbench has been updated. -def get_draft_small_commands(): - """Return a list with only some utilities.""" - return ["Draft_Layer", - "Draft_WorkingPlaneProxy", - "Draft_ToggleDisplayMode", - "Draft_AddNamedGroup", - "Draft_AddToGroup", - "Draft_SelectGroup", - "Draft_AddConstruction"] + return ["Draft_Text", + "Draft_Dimension", + "Draft_Label", + "Draft_AnnotationStyleEditor"] def get_draft_modification_commands(): - """Return the modification commands list.""" - lst = ["Draft_Move", "Draft_Rotate", - "Draft_Scale", "Draft_Mirror", - "Draft_Offset", "Draft_Trimex", - "Draft_Stretch", - "Separator", - "Draft_Clone"] - lst += get_draft_array_commands() - lst += ["Separator", - "Draft_Edit", "Draft_SubelementHighlight", - "Separator", - "Draft_Join", "Draft_Split", - "Draft_Upgrade", "Draft_Downgrade", - "Separator", - "Draft_WireToBSpline", "Draft_Draft2Sketch", - "Draft_Slope", "Draft_FlipDimension", - "Separator", - "Draft_Shape2DView"] - return lst - - -# This function replaces get_draft_modification_commands. -# The "_temp" suffix should be removed when the BIM Workbench has been updated. -def get_draft_modification_commands_temp(): """Return the modification commands list.""" from draftguitools import gui_arrays arr_group = gui_arrays.ArrayGroup @@ -156,32 +104,6 @@ def get_draft_modification_commands_temp(): "Draft_Shape2DView"] -def get_draft_context_commands(): - """Return the context menu commands list.""" - return ["Draft_ApplyStyle", "Draft_ToggleDisplayMode", - "Draft_AddNamedGroup", "Draft_AddToGroup", "Draft_SelectGroup", - "Draft_SelectPlane", "Draft_ShowSnapBar", - "Draft_ToggleGrid", "Draft_SetStyle"] - - -def get_draft_line_commands(): - """Return the line commands list.""" - return ["Draft_UndoLine", "Draft_FinishLine", - "Draft_CloseLine"] - - -# This function has been replaced by get_draft_utility_commands_menu. -# It should be removed when the BIM Workbench has been updated. -def get_draft_utility_commands(): - """Return the utility commands list.""" - return ["Draft_Layer", - "Draft_Heal", - "Draft_ToggleConstructionMode", - "Draft_ToggleContinueMode", - "Draft_WorkingPlaneProxy", - "Draft_AddConstruction"] - - def get_draft_utility_commands_menu(): """Return the utility commands list for the menu.""" return ["Draft_SetStyle", @@ -218,15 +140,41 @@ def get_draft_utility_commands_toolbar(): def get_draft_snap_commands(): """Return the snapping commands list.""" return ['Draft_Snap_Lock', - 'Draft_Snap_Endpoint', 'Draft_Snap_Midpoint', - 'Draft_Snap_Center', 'Draft_Snap_Angle', - 'Draft_Snap_Intersection', 'Draft_Snap_Perpendicular', - 'Draft_Snap_Extension', 'Draft_Snap_Parallel', - 'Draft_Snap_Special', 'Draft_Snap_Near', - 'Draft_Snap_Ortho', 'Draft_Snap_Grid', - 'Draft_Snap_WorkingPlane', 'Draft_Snap_Dimensions', - 'Separator', 'Draft_ToggleGrid' - ] + 'Draft_Snap_Endpoint', + 'Draft_Snap_Midpoint', + 'Draft_Snap_Center', + 'Draft_Snap_Angle', + 'Draft_Snap_Intersection', + 'Draft_Snap_Perpendicular', + 'Draft_Snap_Extension', + 'Draft_Snap_Parallel', + 'Draft_Snap_Special', + 'Draft_Snap_Near', + 'Draft_Snap_Ortho', + 'Draft_Snap_Grid', + 'Draft_Snap_WorkingPlane', + 'Draft_Snap_Dimensions', + 'Separator', 'Draft_ToggleGrid'] + + +def get_draft_context_commands(): + """Return the context menu commands list.""" + return ["Draft_ApplyStyle", + "Draft_ToggleDisplayMode", + "Draft_AddNamedGroup", + "Draft_AddToGroup", + "Draft_SelectGroup", + "Draft_SelectPlane", + "Draft_ShowSnapBar", + "Draft_ToggleGrid", + "Draft_SetStyle"] + + +def get_draft_line_commands(): + """Return the line commands list.""" + return ["Draft_UndoLine", + "Draft_FinishLine", + "Draft_CloseLine"] def init_toolbar(workbench, toolbar, cmd_list): From 9687262cfcd6f2184e82274eb72ffa31ccad67ba Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 2 Oct 2021 09:44:01 +0200 Subject: [PATCH 012/101] Update InitGui.py Removed temp code. --- src/Mod/Draft/InitGui.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index ced2528c63..1952d50e0c 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -92,15 +92,9 @@ class DraftWorkbench(FreeCADGui.Workbench): # Set up command lists import draftutils.init_tools as it - if hasattr(it, "get_draft_drawing_commands_temp"): - self.drawing_commands = it.get_draft_drawing_commands_temp() - else: - self.drawing_commands = it.get_draft_drawing_commands() + self.drawing_commands = it.get_draft_drawing_commands() self.annotation_commands = it.get_draft_annotation_commands() - if hasattr(it, "get_draft_modification_commands_temp"): - self.modification_commands = it.get_draft_modification_commands_temp() - else: - self.modification_commands = it.get_draft_modification_commands() + self.modification_commands = it.get_draft_modification_commands() self.utility_commands_menu = it.get_draft_utility_commands_menu() self.utility_commands_toolbar = it.get_draft_utility_commands_toolbar() self.context_commands = it.get_draft_context_commands() From d6b7ab69378c421e10d6ab8d6b5df930f60c0156 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 2 Oct 2021 09:45:22 +0200 Subject: [PATCH 013/101] Update InitGui.py Updated to use the new Draft code. --- src/Mod/Arch/InitGui.py | 152 ++++++++++++++++++++++++++++------------ 1 file changed, 107 insertions(+), 45 deletions(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 1c40171a93..99df49632b 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -51,37 +51,83 @@ class ArchWorkbench(FreeCADGui.Workbench): import Draft_rc import DraftTools import DraftGui - from draftguitools import gui_circulararray - from draftguitools import gui_polararray - from draftguitools import gui_orthoarray - from draftguitools import gui_arrays import Arch_rc import Arch + from ArchStructure import _ArchStructureGroupCommand + from ArchAxis import _ArchAxisGroupCommand + from ArchPanel import CommandPanelGroup + from ArchMaterial import _ArchMaterialToolsCommand + from ArchPipe import _ArchPipeGroupCommand + + stru_group = _ArchStructureGroupCommand + axis_group = _ArchAxisGroupCommand + pan_group = CommandPanelGroup + mat_group = _ArchMaterialToolsCommand + pipe_group = _ArchPipeGroupCommand + # Set up command lists - self.archtools = ["Arch_Wall", "Arch_StructureTools", "Arch_Rebar", - "Arch_CurtainWall","Arch_BuildingPart", - "Arch_Project", "Arch_Site", "Arch_Building", - "Arch_Floor", "Arch_Reference", - "Arch_Window", "Arch_Roof", "Arch_AxisTools", - "Arch_SectionPlane", "Arch_Space", "Arch_Stairs", - "Arch_PanelTools", "Arch_Equipment", - "Arch_Frame", "Arch_Fence", "Arch_Truss", - "Arch_Profile","Arch_MaterialTools", - "Arch_Schedule", "Arch_PipeTools", - "Arch_CutPlane", "Arch_CutLine", - "Arch_Add", "Arch_Remove", "Arch_Survey"] - self.utilities = ["Arch_Component", "Arch_CloneComponent", - "Arch_SplitMesh", "Arch_MeshToShape", - "Arch_SelectNonSolidMeshes", "Arch_RemoveShape", - "Arch_CloseHoles", "Arch_MergeWalls", "Arch_Check", - "Arch_ToggleIfcBrepFlag", "Arch_3Views", - "Arch_IfcSpreadsheet", "Arch_ToggleSubs"] + self.archtools = ["Arch_Wall", + ([QT_TRANSLATE_NOOP("Arch", "Structure tools")], + list(stru_group.GetCommands(stru_group))), # tuple len=2: submenu + ("Arch_StructureTools", ), # tuple len=1: toolbar flyout + "Arch_Rebar_Submenu", # will be replaced or removed + "Arch_Rebar", # may be replaced + "Arch_CurtainWall", + "Arch_BuildingPart", + "Arch_Project", + "Arch_Site", + "Arch_Building", + "Arch_Floor", + "Arch_Reference", + "Arch_Window", + "Arch_Roof", + ([QT_TRANSLATE_NOOP("Arch", "Axis tools")], + list(axis_group.GetCommands(axis_group))), + ("Arch_AxisTools", ), + "Arch_SectionPlane", + "Arch_Space", + "Arch_Stairs", + ([QT_TRANSLATE_NOOP("Arch", "Panel tools")], + list(pan_group.GetCommands(pan_group))), + ("Arch_PanelTools", ), + "Arch_Equipment", + "Arch_Frame", + "Arch_Fence", + "Arch_Truss", + "Arch_Profile", + ([QT_TRANSLATE_NOOP("Arch", "Material tools")], + list(mat_group.GetCommands(mat_group))), + ("Arch_MaterialTools", ), + "Arch_Schedule", + ([QT_TRANSLATE_NOOP("Arch", "Pipe tools")], + list(pipe_group.GetCommands(pipe_group))), + ("Arch_PipeTools", ), + "Arch_CutPlane", + "Arch_CutLine", + "Arch_Add", + "Arch_Remove", + "Arch_Survey"] + + self.utilities = ["Arch_Component", + "Arch_CloneComponent", + "Arch_SplitMesh", + "Arch_MeshToShape", + "Arch_SelectNonSolidMeshes", + "Arch_RemoveShape", + "Arch_CloseHoles", + "Arch_MergeWalls", + "Arch_Check", + "Arch_ToggleIfcBrepFlag", + "Arch_3Views", + "Arch_IfcSpreadsheet", + "Arch_ToggleSubs"] # Add the rebar tools from the Reinforcement addon, if available try: import RebarTools except Exception: + del self.archtools[3] # remove "Arch_Rebar_Submenu" pass else: class RebarGroupCommand: @@ -97,42 +143,58 @@ class ArchWorkbench(FreeCADGui.Workbench): def IsActive(self): return not FreeCAD.ActiveDocument is None FreeCADGui.addCommand('Arch_RebarTools', RebarGroupCommand()) - self.archtools[2] = "Arch_RebarTools" + self.archtools[3] = ([QT_TRANSLATE_NOOP("Arch", "Rebar tools")], + RebarTools.RebarCommands + ["Arch_Rebar"]) + self.archtools[4] = ("Arch_RebarTools", ) # Set up Draft command lists import draftutils.init_tools as it self.draft_drawing_commands = it.get_draft_drawing_commands() self.draft_annotation_commands = it.get_draft_annotation_commands() self.draft_modification_commands = it.get_draft_modification_commands() + self.draft_utility_commands = it.get_draft_utility_commands_menu() self.draft_context_commands = it.get_draft_context_commands() self.draft_line_commands = it.get_draft_line_commands() - self.draft_utility_commands = it.get_draft_utility_commands() # Set up toolbars - self.appendToolbar(QT_TRANSLATE_NOOP("Workbench", "Arch tools"), self.archtools) - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft creation tools"), self.draft_drawing_commands) - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"), self.draft_annotation_commands) - self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft modification tools"), self.draft_modification_commands) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Workbench", "Arch tools"), + self.archtools) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft creation tools"), + self.draft_drawing_commands) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"), + self.draft_annotation_commands) + it.init_toolbar(self, + QT_TRANSLATE_NOOP("Draft", "Draft modification tools"), + self.draft_modification_commands) # Set up menus - self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Arch"), - QT_TRANSLATE_NOOP("arch", "Utilities")], - self.utilities) - self.appendMenu(QT_TRANSLATE_NOOP("arch", "&Arch"), self.archtools) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Arch", "&Arch"), + QT_TRANSLATE_NOOP("Arch", "Utilities")], + self.utilities) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Arch", "&Arch")], + self.archtools) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Arch", "&Draft"), + QT_TRANSLATE_NOOP("Arch", "Creation")], + self.draft_drawing_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Arch", "&Draft"), + QT_TRANSLATE_NOOP("Arch", "Annotation")], + self.draft_annotation_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Arch", "&Draft"), + QT_TRANSLATE_NOOP("Arch", "Modification")], + self.draft_modification_commands) + it.init_menu(self, + [QT_TRANSLATE_NOOP("Arch", "&Draft"), + QT_TRANSLATE_NOOP("Arch", "Utilities")], + self.draft_utility_commands) - self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"), - QT_TRANSLATE_NOOP("arch", "Creation")], - self.draft_drawing_commands) - self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"), - QT_TRANSLATE_NOOP("arch", "Annotation")], - self.draft_annotation_commands) - self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"), - QT_TRANSLATE_NOOP("arch", "Modification")], - self.draft_modification_commands) - self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"), - QT_TRANSLATE_NOOP("arch", "Utilities")], - self.draft_utility_commands - + self.draft_context_commands) FreeCADGui.addIconPath(":/icons") FreeCADGui.addLanguagePath(":/translations") From c7cc7fa0fd7c1e05deaa1d945b0977007f26e8c6 Mon Sep 17 00:00:00 2001 From: Tomas Pavlicek Date: Sun, 3 Oct 2021 13:43:53 +0200 Subject: [PATCH 014/101] TechDraw - Balloon updates --- src/Mod/TechDraw/App/DrawPage.cpp | 1 - src/Mod/TechDraw/App/DrawPage.h | 1 - src/Mod/TechDraw/App/DrawViewBalloon.cpp | 1 + src/Mod/TechDraw/Gui/Command.cpp | 54 ++++++- .../Gui/DlgPrefsTechDrawAnnotation.ui | 9 ++ src/Mod/TechDraw/Gui/QGIView.cpp | 2 - src/Mod/TechDraw/Gui/QGIViewBalloon.cpp | 15 +- src/Mod/TechDraw/Gui/QGVPage.cpp | 144 ++++++++++++------ src/Mod/TechDraw/Gui/QGVPage.h | 15 +- src/Mod/TechDraw/Gui/Resources/TechDraw.qrc | 1 + .../Gui/Resources/icons/bottomline.svg | 35 +++++ src/Mod/TechDraw/Gui/TaskBalloon.ui | 9 ++ src/Mod/TechDraw/Gui/ViewProviderPage.h | 1 + 13 files changed, 233 insertions(+), 55 deletions(-) create mode 100644 src/Mod/TechDraw/Gui/Resources/icons/bottomline.svg diff --git a/src/Mod/TechDraw/App/DrawPage.cpp b/src/Mod/TechDraw/App/DrawPage.cpp index 7d944593e8..f35835c0f6 100644 --- a/src/Mod/TechDraw/App/DrawPage.cpp +++ b/src/Mod/TechDraw/App/DrawPage.cpp @@ -100,7 +100,6 @@ DrawPage::DrawPage(void) "Auto-numbering for Balloons"); Scale.setConstraints(&scaleRange); - balloonPlacing = false; balloonParent = nullptr; } diff --git a/src/Mod/TechDraw/App/DrawPage.h b/src/Mod/TechDraw/App/DrawPage.h index 17b2c383bd..f9973b9d3a 100644 --- a/src/Mod/TechDraw/App/DrawPage.h +++ b/src/Mod/TechDraw/App/DrawPage.h @@ -94,7 +94,6 @@ public: bool isUnsetting(void) { return nowUnsetting; } void requestPaint(void); std::vector getAllViews(void) ; - bool balloonPlacing; DrawViewPart *balloonParent; //could be many balloons on page? int getNextBalloonIndex(void); diff --git a/src/Mod/TechDraw/App/DrawViewBalloon.cpp b/src/Mod/TechDraw/App/DrawViewBalloon.cpp index 684cbc934b..0bad648181 100644 --- a/src/Mod/TechDraw/App/DrawViewBalloon.cpp +++ b/src/Mod/TechDraw/App/DrawViewBalloon.cpp @@ -87,6 +87,7 @@ const char* DrawViewBalloon::balloonTypeEnums[]= {"Circular", "Hexagon", "Square", "Rectangle", + "Line", NULL}; DrawViewBalloon::DrawViewBalloon(void) diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index 49cf9170d0..2002008728 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -94,7 +94,11 @@ #include "TaskActiveView.h" #include "TaskDetail.h" #include "ViewProviderPage.h" +#include "ViewProviderViewPart.h" +#include "QGIViewPart.h" +#include "Rez.h" +class Vertex; using namespace TechDrawGui; using namespace TechDraw; using namespace std; @@ -801,6 +805,34 @@ bool _checkDrawViewPartBalloon(Gui::Command* cmd) { return true; } +bool _checkDirectPlacement(const QGIViewPart *viewPart, const std::vector &subNames, QPointF &placement) +{ + if (subNames.size() != 1) { + return false; + } + + std::string geoType = TechDraw::DrawUtil::getGeomTypeFromName(subNames[0]); + if (geoType == "Vertex") { + int index = TechDraw::DrawUtil::getIndexFromName(subNames[0]); + TechDraw::Vertex *vertex = static_cast(viewPart->getViewObject())->getProjVertexByIndex(index); + if (vertex) { + placement = viewPart->mapToScene(Rez::guiX(vertex->x()), Rez::guiX(vertex->y())); + return true; + } + } + else if (geoType == "Edge") { + int index = TechDraw::DrawUtil::getIndexFromName(subNames[0]); + TechDraw::BaseGeom *geo = static_cast(viewPart->getViewObject())->getGeomByIndex(index); + if (geo) { + Base::Vector3d midPoint(Rez::guiX(geo->getMidPoint())); + placement = viewPart->mapToScene(midPoint.x, midPoint.y); + return true; + } + } + + return false; +} + DEF_STD_CMD_A(CmdTechDrawBalloon) CmdTechDrawBalloon::CmdTechDrawBalloon() @@ -826,6 +858,7 @@ void CmdTechDrawBalloon::activated(int iMsg) return; std::vector selection = getSelection().getSelectionEx(); + auto objFeat( dynamic_cast(selection[0].getObject()) ); if( objFeat == nullptr ) { return; @@ -833,10 +866,25 @@ void CmdTechDrawBalloon::activated(int iMsg) TechDraw::DrawPage* page = objFeat->findParentPage(); std::string PageName = page->getNameInDocument(); - - page->balloonParent = objFeat; - page->balloonPlacing = true; + page->balloonParent = objFeat; + + Gui::Document *guiDoc = Gui::Application::Instance->getDocument(page->getDocument()); + ViewProviderPage *pageVP = dynamic_cast(guiDoc->getViewProvider(page)); + ViewProviderViewPart *partVP = dynamic_cast(guiDoc->getViewProvider(objFeat)); + + if (pageVP && partVP) { + QGVPage *viewPage = pageVP->getGraphicsView(); + if (viewPage) { + viewPage->startBalloonPlacing(); + + QGIViewPart *viewPart = dynamic_cast(partVP->getQView()); + QPointF placement; + if (viewPart && _checkDirectPlacement(viewPart, selection[0].getSubNames(), placement)) { + viewPage->createBalloon(placement, objFeat); + } + } + } } bool CmdTechDrawBalloon::isActive(void) diff --git a/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAnnotation.ui b/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAnnotation.ui index 0e6d4f080d..1f484413a9 100644 --- a/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAnnotation.ui +++ b/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAnnotation.ui @@ -424,6 +424,15 @@ :/icons/rectangle.svg:/icons/rectangle.svg + + + Line + + + + :/icons/bottomline.svg:/icons/bottomline.svg + + diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index 71d7fe6913..70c7f2d2e3 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -118,8 +118,6 @@ QGIView::QGIView() m_lockWidth = (double) sizeLock.width(); m_lockHeight = (double) sizeLock.height(); m_lock->hide(); - - setCursor(Qt::ArrowCursor); } QGIView::~QGIView() diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp index a100894875..6a06f65beb 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp @@ -676,6 +676,7 @@ void QGIViewBalloon::drawBalloon(bool dragged) float scale = balloon->ShapeScale.getValue(); double offsetLR = 0; + double offsetUD = 0; QPainterPath balloonPath; if (strcmp(balloonType, "Circular") == 0) { @@ -747,16 +748,26 @@ void QGIViewBalloon::drawBalloon(bool dragged) balloonPath.moveTo(lblCenter.x + (radius * cos(startAngle)), lblCenter.y + (radius * sin(startAngle))); balloonPath.addPolygon(triangle); } + else if (strcmp(balloonType, "Line") == 0) { + textHeight = textHeight*scale + Rez::guiX(0.5); + textWidth = textWidth*scale + Rez::guiX(1.0); + + offsetLR = textWidth/2.0; + offsetUD = textHeight/2.0; + + balloonPath.moveTo(lblCenter.x - textWidth/2.0, lblCenter.y + offsetUD); + balloonPath.lineTo(lblCenter.x + textWidth/2.0, lblCenter.y + offsetUD); + } balloonShape->setPath(balloonPath); offsetLR = (lblCenter.x < arrowTipX) ? offsetLR : -offsetLR ; - if (DrawUtil::fpCompare(kinkLength, 0.0)) { //if no kink, then dLine start sb on line from center to arrow + if (DrawUtil::fpCompare(kinkLength, 0.0) && strcmp(balloonType, "Line")) { //if no kink, then dLine start sb on line from center to arrow dLineStart = lblCenter; kinkPoint = dLineStart; } else { - dLineStart.y = lblCenter.y; + dLineStart.y = lblCenter.y + offsetUD; dLineStart.x = lblCenter.x + offsetLR ; kinkLength = (lblCenter.x < arrowTipX) ? kinkLength : -kinkLength; kinkPoint.y = dLineStart.y; diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index 76e84a9748..81654e5d04 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -57,6 +57,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -126,6 +132,7 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGraphicsScene* s, QWidget *parent) m_renderer(Native), drawBkg(true), m_vpPage(0), + balloonPlacing(false), panningActive(false) { assert(vp); @@ -166,13 +173,13 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGraphicsScene* s, QWidget *parent) setAlignment(Qt::AlignCenter); setDragMode(ScrollHandDrag); - setCursor(QCursor(Qt::ArrowCursor)); + resetCursor(); setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); bkgBrush = new QBrush(getBackgroundColor()); balloonCursor = new QLabel(this); - balloonCursor->setPixmap(QPixmap(QString::fromUtf8(":/icons/TechDraw_Balloon.svg"))); + balloonCursor->setPixmap(prepareCursorPixmap("TechDraw_Balloon.svg", balloonHotspot = QPoint(8, 59))); balloonCursor->hide(); resetCachedContent(); @@ -184,11 +191,17 @@ QGVPage::~QGVPage() } +void QGVPage::startBalloonPlacing(void) +{ + balloonPlacing = true; + activateCursor(QCursor(*balloonCursor->pixmap(), balloonHotspot.x(), balloonHotspot.y())); +} + void QGVPage::cancelBalloonPlacing(void) { - getDrawPage()->balloonPlacing = false; - balloonCursor->hide(); - QApplication::restoreOverrideCursor(); + balloonPlacing = false; + balloonCursor->hide(); + resetCursor(); } void QGVPage::drawBackground(QPainter *p, const QRectF &) @@ -448,12 +461,13 @@ QGIView * QGVPage::addViewBalloon(TechDraw::DrawViewBalloon *balloon) QGIView *parent = 0; parent = findParent(vBalloon); - if(parent) + if (parent) { addBalloonToParent(vBalloon,parent); + } - if (getDrawPage()->balloonPlacing) { - vBalloon->placeBalloon(balloon->origin); - cancelBalloonPlacing(); + if (balloonPlacing) { + vBalloon->placeBalloon(balloon->origin); + cancelBalloonPlacing(); } return vBalloon; @@ -470,6 +484,32 @@ void QGVPage::addBalloonToParent(QGIViewBalloon* balloon, QGIView* parent) balloon->setZValue(ZVALUE::DIMENSION); } +void QGVPage::createBalloon(QPointF origin, DrawViewPart *parent) +{ + std::string featName = getDrawPage()->getDocument()->getUniqueObjectName("Balloon"); + std::string pageName = getDrawPage()->getNameInDocument(); + + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon")); + TechDraw::DrawViewBalloon *balloon = 0; + + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon")); + Command::doCommand(Command::Doc, "App.activeDocument().addObject('TechDraw::DrawViewBalloon','%s')", featName.c_str()); + Command::doCommand(Command::Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", pageName.c_str(), featName.c_str()); + + balloon = dynamic_cast(getDrawPage()->getDocument()->getObject(featName.c_str())); + if (!balloon) { + throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n"); + } + + balloon->SourceView.setValue(parent); + balloon->origin = origin; + + Gui::Command::commitCommand(); + + balloon->recomputeFeature(); + parent->touch(true); +} + QGIView * QGVPage::addViewDimension(TechDraw::DrawViewDimension *dim) { auto dimGroup( new QGIViewDimension ); @@ -1119,21 +1159,14 @@ void QGVPage::kbPanScroll(int xMove, int yMove) void QGVPage::enterEvent(QEvent *event) { QGraphicsView::enterEvent(event); - if(getDrawPage()->balloonPlacing) { + if (balloonPlacing) { balloonCursor->hide(); - QApplication::setOverrideCursor(QCursor(QPixmap(QString::fromUtf8(":/icons/TechDraw_Balloon.svg")),0,32)); - } else { - QApplication::restoreOverrideCursor(); - viewport()->setCursor(Qt::ArrowCursor); } } void QGVPage::leaveEvent(QEvent * event) { - QApplication::restoreOverrideCursor(); - if(getDrawPage()->balloonPlacing) { - - + if (balloonPlacing) { int left_x; if (balloonCursorPos.x() < 32) left_x = 0; @@ -1192,33 +1225,9 @@ void QGVPage::mouseMoveEvent(QMouseEvent *event) void QGVPage::mouseReleaseEvent(QMouseEvent *event) { - if(getDrawPage()->balloonPlacing) { - QApplication::restoreOverrideCursor(); + if (balloonPlacing) { balloonCursor->hide(); - - std::string FeatName = getDrawPage()->getDocument()->getUniqueObjectName("Balloon"); - std::string PageName = getDrawPage()->getNameInDocument(); - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon")); - TechDraw::DrawViewBalloon *balloon = 0; - - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon")); - Command::doCommand(Command::Doc,"App.activeDocument().addObject('TechDraw::DrawViewBalloon','%s')",FeatName.c_str()); - Command::doCommand(Command::Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); - - balloon = dynamic_cast(getDrawPage()->getDocument()->getObject(FeatName.c_str())); - if (!balloon) { - throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n"); - } - - balloon->SourceView.setValue(getDrawPage()->balloonParent); - balloon->origin = mapToScene(event->pos()); - - Gui::Command::commitCommand(); - balloon->recomputeFeature(); - - //Horrible hack to force Tree update - double x = getDrawPage()->balloonParent->X.getValue(); - getDrawPage()->balloonParent->X.setValue(x); + createBalloon(mapToScene(event->pos()), getDrawPage()->balloonParent); } if (event->button()&Qt::MiddleButton) { @@ -1227,7 +1236,7 @@ void QGVPage::mouseReleaseEvent(QMouseEvent *event) } QGraphicsView::mouseReleaseEvent(event); - viewport()->setCursor(Qt::ArrowCursor); + resetCursor(); } TechDraw::DrawPage* QGVPage::getDrawPage() @@ -1244,4 +1253,49 @@ QColor QGVPage::getBackgroundColor() return fcColor.asValue(); } +double QGVPage::getDevicePixelRatio() const { + for (Gui::MDIView *view : m_vpPage->getDocument()->getMDIViews()) { + if (view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + return static_cast(view)->getViewer()->devicePixelRatio(); + } + } + + return 1.0; +} + +QPixmap QGVPage::prepareCursorPixmap(const char *iconName, QPoint &hotspot) { + double cursorSize = 64.0; + double pixelRatio = getDevicePixelRatio(); + + if (pixelRatio != 1.0) { + cursorSize = 32.0*pixelRatio; + } + + QPixmap pixmap = Gui::BitmapFactory().pixmapFromSvg(iconName, QSizeF(cursorSize, cursorSize)); + if (pixelRatio == 1.0) { + pixmap = pixmap.scaled(32, 32); + hotspot /= 2; + } + pixmap.setDevicePixelRatio(pixelRatio); + +#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) + if (qGuiApp->platformName() == QLatin1String("xcb")) { + hotspot *= pixelRatio; + } +#endif + + return pixmap; +} + +void QGVPage::activateCursor(QCursor cursor) { + this->setCursor(cursor); + viewport()->setCursor(cursor); +} + +void QGVPage::resetCursor() { + this->setCursor(Qt::ArrowCursor); + viewport()->setCursor(Qt::ArrowCursor); +} + + #include diff --git a/src/Mod/TechDraw/Gui/QGVPage.h b/src/Mod/TechDraw/Gui/QGVPage.h index 52bbde1583..427d87a4f6 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.h +++ b/src/Mod/TechDraw/Gui/QGVPage.h @@ -93,6 +93,10 @@ public: QGIView* findParent(QGIView *) const; void addBalloonToParent(QGIViewBalloon* balloon, QGIView* parent); + void createBalloon(QPointF origin, TechDraw::DrawViewPart *parent); + void startBalloonPlacing(void); + void cancelBalloonPlacing(void); + void addDimToParent(QGIViewDimension* dim, QGIView* parent); void addLeaderToParent(QGILeaderLine* lead, QGIView* parent); @@ -118,6 +122,7 @@ public: void saveSvg(QString filename); void postProcessXml(QTemporaryFile& tempFile, QString filename, QString pagename); + public Q_SLOTS: void setHighQualityAntialiasing(bool highQualityAntialiasing); @@ -140,6 +145,12 @@ protected: QGITemplate *pageTemplate; + double getDevicePixelRatio() const; + QPixmap prepareCursorPixmap(const char *iconName, QPoint &hotspot); + + void activateCursor(QCursor cursor); + void resetCursor(); + private: RendererType m_renderer; @@ -153,9 +164,11 @@ private: double m_zoomIncrement; int m_reversePan; int m_reverseScroll; + + bool balloonPlacing; QLabel *balloonCursor; QPoint balloonCursorPos; - void cancelBalloonPlacing(void); + QPoint balloonHotspot; QPoint panOrigin; bool panningActive; diff --git a/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc b/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc index 45b09b6e62..887953a5dd 100644 --- a/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc +++ b/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc @@ -109,6 +109,7 @@ icons/rectangle.svg icons/triangle.svg icons/square.svg + icons/bottomline.svg icons/MRTE/menu.svg diff --git a/src/Mod/TechDraw/Gui/Resources/icons/bottomline.svg b/src/Mod/TechDraw/Gui/Resources/icons/bottomline.svg new file mode 100644 index 0000000000..f97073b88b --- /dev/null +++ b/src/Mod/TechDraw/Gui/Resources/icons/bottomline.svg @@ -0,0 +1,35 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/src/Mod/TechDraw/Gui/TaskBalloon.ui b/src/Mod/TechDraw/Gui/TaskBalloon.ui index b4c1911af1..fd58abd15e 100644 --- a/src/Mod/TechDraw/Gui/TaskBalloon.ui +++ b/src/Mod/TechDraw/Gui/TaskBalloon.ui @@ -164,6 +164,15 @@ :/icons/rectangle.svg:/icons/rectangle.svg + + + Line + + + + :/icons/bottomline.svg:/icons/bottomline.svg + + diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.h b/src/Mod/TechDraw/Gui/ViewProviderPage.h index 443feb3047..895f92f740 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.h +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.h @@ -91,6 +91,7 @@ public: void setFrameState(bool state); void toggleFrameState(void); void setTemplateMarkers(bool state); + QGVPage *getGraphicsView() { return m_graphicsView; } void setGraphicsView(QGVPage* gv); virtual bool canDelete(App::DocumentObject* obj) const override; From 3833fe21edc7a2d0120060dfc7dc72df070cb8b0 Mon Sep 17 00:00:00 2001 From: donovaly Date: Sun, 3 Oct 2021 03:10:43 +0200 Subject: [PATCH 015/101] [Spreadsheet] fix preferences UI - add missing layouts (Qt's designer warns too) - add spacers to assure a compact layout on all screens --- src/Mod/Spreadsheet/Gui/DlgSettings.ui | 314 ++++++++++++------------- 1 file changed, 154 insertions(+), 160 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/DlgSettings.ui b/src/Mod/Spreadsheet/Gui/DlgSettings.ui index 8d140c0b2c..39eaa4d4ed 100644 --- a/src/Mod/Spreadsheet/Gui/DlgSettings.ui +++ b/src/Mod/Spreadsheet/Gui/DlgSettings.ui @@ -6,181 +6,175 @@ 0 0 - 555 - 413 + 322 + 149 + + + 0 + 0 + + Spreadsheet - - - - 10 - 10 - 531 - 161 - - - - Import/Export Settings - - - - - 156 - 70 - 142 - 25 - - - - <html><head/><body><p>Character used to delimit strings, typically is single quote (') or double quote (&quot;). Must be a single character.</p></body></html> - - - - - - " - - - ImportExportQuoteCharacter - - - Mod/Spreadsheet - - - - - - 13 - 33 - 137 - 17 - - - - - 0 - 0 - - - - Delimiter Character: - - - - - - 156 - 113 - 142 - 25 - - - - <html><head/><body><p>Escape character, typically the backslash (\), used to indicate special unprintable characters, e.g. \t = tab. Must be a single character.</p></body></html> - - - \ - - - ImportExportEscapeCharacter - - - Mod/Spreadsheet - - - - - - 13 - 113 - 124 - 17 - - - - - 0 - 0 - - - - Escape Character: - - - - - - 156 - 33 - 142 - 25 - - - - <html><head/><body><p>Character to use as field delimiter. Default is tab, but also commonly used are commas (,) and semicolons (;). Select from the list or enter your own in the field. Must be a single character or the words <span style=" font-style:italic;">tab</span>, <span style=" font-style:italic;">comma</span>, or <span style=" font-style:italic;">semicolon</span>.</p></body></html> - - - true - - - tab - - - ImportExportDelimiter - - - Mod/Spreadsheet - - - - tab + + + + + Import/Export Settings - - - - ; + + + + + + 0 + 0 + + + + Escape Character: + + + + + + + <html><head/><body><p>Character used to delimit strings, typically is single quote (') or double quote (&quot;). Must be a single character.</p></body></html> + + + + + + " + + + ImportExportQuoteCharacter + + + Mod/Spreadsheet + + + + + + + + 0 + 0 + + + + Delimiter Character: + + + + + + + <html><head/><body><p>Escape character, typically the backslash (\), used to indicate special unprintable characters, e.g. \t = tab. Must be a single character.</p></body></html> + + + \ + + + ImportExportEscapeCharacter + + + Mod/Spreadsheet + + + + + + + + 0 + 0 + + + + Quote Character: + + + + + + + <html><head/><body><p>Character to use as field delimiter. Default is tab, but also commonly used are commas (,) and semicolons (;). Select from the list or enter your own in the field. Must be a single character or the words <span style=" font-style:italic;">tab</span>, <span style=" font-style:italic;">comma</span>, or <span style=" font-style:italic;">semicolon</span>.</p></body></html> + + + true + + + tab + + + ImportExportDelimiter + + + Mod/Spreadsheet + + + + tab + + + + + ; + + + + + , + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Vertical - - - - , + + + 20 + 20 + - - - - - - 13 - 70 - 117 - 17 - - - - - 0 - 0 - - - - Quote Character: - - - + + + - Gui::PrefLineEdit - QLineEdit + Gui::PrefComboBox + QComboBox
Gui/PrefWidgets.h
- Gui::PrefComboBox - QComboBox + Gui::PrefLineEdit + QLineEdit
Gui/PrefWidgets.h
From 0c3ba910aa927366b88f6621c1d70f4bf3eeda28 Mon Sep 17 00:00:00 2001 From: bartus Date: Sun, 3 Oct 2021 14:20:19 +0200 Subject: [PATCH 016/101] Fix linux build: undefined std:string_view Pop 'mesh' library c++ stranderd to c++17 Add required header --- src/Mod/Mesh/App/CMakeLists.txt | 2 ++ src/Mod/Mesh/App/Core/MeshIO.cpp | 1 + src/Mod/PartDesign/App/json.hpp | 1 + 3 files changed, 4 insertions(+) diff --git a/src/Mod/Mesh/App/CMakeLists.txt b/src/Mod/Mesh/App/CMakeLists.txt index 2d661aea12..c987d475f1 100644 --- a/src/Mod/Mesh/App/CMakeLists.txt +++ b/src/Mod/Mesh/App/CMakeLists.txt @@ -399,6 +399,8 @@ endif () add_library(Mesh SHARED ${Core_SRCS} ${WildMagic4_SRCS} ${Mesh_SRCS}) target_link_libraries(Mesh ${Mesh_LIBS}) +set_target_properties(Mesh PROPERTIES CXX_STANDARD_REQUIRED ON) +set_target_properties(Mesh PROPERTIES CXX_STANDARD 17) SET_BIN_DIR(Mesh Mesh /Mod/Mesh) diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 2c1655a588..09d1ad91dc 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/PartDesign/App/json.hpp b/src/Mod/PartDesign/App/json.hpp index 1c15051070..fb83a5cca0 100644 --- a/src/Mod/PartDesign/App/json.hpp +++ b/src/Mod/PartDesign/App/json.hpp @@ -43,6 +43,7 @@ SOFTWARE. #include // unique_ptr #include // accumulate #include // string, stoi, to_string +#include // string_view #include // declval, forward, move, pair, swap #include // vector From 57375ce7c2374893a25957c688fe4c83a81c5f48 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Oct 2021 16:45:45 +0200 Subject: [PATCH 017/101] Gui: [skip ci] add Gui::cmdAppDocumentArgs and support further string types with FormatString::str --- src/Gui/CommandT.h | 49 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/Gui/CommandT.h b/src/Gui/CommandT.h index ee29102d9f..64154d8cca 100644 --- a/src/Gui/CommandT.h +++ b/src/Gui/CommandT.h @@ -30,6 +30,7 @@ #include #include #include +#include #include namespace Gui { @@ -40,11 +41,24 @@ public: static std::string str(const std::string& s) { return s; } + static std::string str(const char* s) { + return s; + } + static std::string str(const QString& s) { + return s.toStdString(); + } static std::string str(const std::stringstream& s) { return s.str(); } + static std::string str(const std::ostringstream& s) { + return s.str(); + } static std::string str(const std::ostream& s) { - return dynamic_cast(s).str(); + if (typeid(s) == typeid(std::ostringstream)) + return dynamic_cast(s).str(); + else if (typeid(s) == typeid(std::stringstream)) + return dynamic_cast(s).str(); + throw Base::TypeError("Not a std::stringstream or std::ostringstream"); } static std::string toStr(boost::format& f) { return f.str(); @@ -152,6 +166,39 @@ inline void cmdAppDocument(const App::DocumentObject* obj, T&& cmd) { _cmdDocument(Gui::Command::Doc, obj, "App", std::forward(cmd)); } +/** Runs a command for accessing a document's attribute or method + * @param doc: pointer to a Document + * @param cmd: command string, supporting printf like formatter + * + * Example: + * @code{.cpp} + * cmdAppDocumentArgs(obj, "addObject('%s')", "Part::Feature"); + * @endcode + * + * Translates to command (assuming obj's document name is 'DocName': + * @code{.py} + * App.getDocument('DocName').addObject('Part::Feature') + * @endcode + */ +template +void cmdAppDocumentArgs(const App::Document* doc, const std::string& cmd, Args&&... args) { + std::string _cmd; + try { + boost::format fmt(cmd); + _cmd = FormatString::toStr(fmt, std::forward(args)...); + Gui::Command::doCommand(Gui::Command::Doc,"App.getDocument('%s').%s", + doc->getName(), _cmd.c_str()); + } + catch (const std::exception& e) { + Base::Console().Error("%s: %s\n", e.what(), cmd.c_str()); + } + catch (const Base::Exception&) { + Base::Console().Error("App.getDocument('%s').%s\n", + doc->getName(), _cmd.c_str()); + throw; + } +} + /** Runs a command for accessing an object's Gui::Document attribute or method * This function is an alternative to FCMD_VOBJ_DOC_CMD * @param obj: pointer to a DocumentObject From 69bfa47b0ecb51d3c4e1bb22d072359eb00cda17 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Oct 2021 16:46:32 +0200 Subject: [PATCH 018/101] Part: [skip ci] use Gui::cmdAppDocumentArgs in ShapeFromMesh dialog --- src/Mod/Part/Gui/ShapeFromMesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Part/Gui/ShapeFromMesh.cpp b/src/Mod/Part/Gui/ShapeFromMesh.cpp index f031582a6d..5d79b6ca4d 100644 --- a/src/Mod/Part/Gui/ShapeFromMesh.cpp +++ b/src/Mod/Part/Gui/ShapeFromMesh.cpp @@ -81,7 +81,7 @@ void ShapeFromMesh::perform() std::string mesh = (*it)->getNameInDocument(); std::string name = doc->getUniqueObjectName(mesh.c_str()); - Gui::cmdAppDocument(doc, std::ostringstream() << "addObject(\"Part::Feature\", \"" << name << "\")"); + Gui::cmdAppDocumentArgs(doc, "addObject('%s', '%s')", "Part::Feature", name); std::string partObj = App::DocumentObjectT(doc, name).getObjectPython(); std::string meshObj = App::DocumentObjectT(doc, mesh).getObjectPython(); From 41c30470f364623e2d8c850ec4e961641c4ca790 Mon Sep 17 00:00:00 2001 From: donovaly Date: Sun, 3 Oct 2021 02:53:44 +0200 Subject: [PATCH 019/101] [Sketch] Selection improvements as described here: https://forum.freecadweb.org/viewtopic.php?f=17&t=60569&p=537615#p537615 --- .../Gui/ConstraintMultiFilterDialog.ui | 34 ++++--------------- .../Sketcher/Gui/TaskSketcherConstrains.ui | 15 ++++---- 2 files changed, 15 insertions(+), 34 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui index 62a7396c33..76463253ba 100644 --- a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui +++ b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui @@ -9,22 +9,16 @@ 0 0 - 325 - 600 + 274 + 500 - + 0 0 - - - 16777215 - 700 - - Multiple filter selection @@ -39,16 +33,13 @@ - + 0 0 - - - 0 - 500 - + + QAbstractScrollArea::AdjustToContents QAbstractItemView::NoSelection @@ -217,19 +208,6 @@ - - - - Qt::Vertical - - - - 0 - 0 - - - - diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui index e7a3d82462..83149c0f26 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui @@ -181,8 +181,11 @@ 0 + + Click to select multiple filters + - ... + Select Multiple @@ -396,16 +399,16 @@ - - ConstraintView - QListWidget -
QListWidget
-
Gui::PrefCheckBox QCheckBox
Gui/PrefWidgets.h
+ + ConstraintView + QListWidget +
QListWidget
+
From f4a8f32db457e85c5319d2d4d53c3943271fdf03 Mon Sep 17 00:00:00 2001 From: donovaly Date: Sun, 3 Oct 2021 18:22:16 +0200 Subject: [PATCH 020/101] adjust preferred size to contain also the ALL entry --- src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui index 76463253ba..edbae5fc42 100644 --- a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui +++ b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui @@ -10,7 +10,7 @@ 0 0 274 - 500 + 512 From 007041b2ec82a9dc3ff316cfbe88c53ce6d727b2 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Mon, 4 Oct 2021 14:08:03 +0200 Subject: [PATCH 021/101] Sketcher: Reorder filter entries to match toolbar ================================================ https://forum.freecadweb.org/viewtopic.php?p=537777#p537777 --- src/Mod/Sketcher/Gui/ConstraintFilters.h | 28 +++++++-------- .../Gui/ConstraintMultiFilterDialog.ui | 34 +++++++++---------- .../Sketcher/Gui/TaskSketcherConstrains.ui | 26 +++++++------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ConstraintFilters.h b/src/Mod/Sketcher/Gui/ConstraintFilters.h index 5517592305..25a3defdd7 100644 --- a/src/Mod/Sketcher/Gui/ConstraintFilters.h +++ b/src/Mod/Sketcher/Gui/ConstraintFilters.h @@ -36,19 +36,19 @@ namespace ConstraintFilter { Datums = 2, Named = 3, NonDriving = 4, - Horizontal = 5, - Vertical = 6, - Coincident = 7, - PointOnObject = 8, + Coincident = 5, + PointOnObject = 6, + Vertical = 7, + Horizontal = 8, Parallel = 9, Perpendicular = 10, Tangent = 11, Equality = 12, Symmetric = 13, Block = 14, - Distance = 15, - HorizontalDistance = 16, - VerticalDistance = 17, + HorizontalDistance = 15, + VerticalDistance = 16, + Distance = 17, Radius = 18, Weight = 19, Diameter = 20, @@ -76,19 +76,19 @@ namespace ConstraintFilter { 1 << FilterValue::Datums | 1 << FilterValue::NonDriving | 1 << FilterValue::Distance | 1 << FilterValue::HorizontalDistance | 1 << FilterValue::VerticalDistance | 1 << FilterValue::Radius | 1 << FilterValue::Weight | 1 << FilterValue::Diameter | 1 << FilterValue::Angle | 1 << FilterValue::SnellsLaw, // Datum = all others not being geometric (2) 1 << FilterValue::Named, // Named = Just this (3) 1 << FilterValue::NonDriving, // NonDriving = Just this (4) - 1 << FilterValue::Horizontal, // Horizontal = Just this (5) - 1 << FilterValue::Vertical, // Vertical = Just this (6) - 1 << FilterValue::Coincident, // Coincident = Just this (7) - 1 << FilterValue::PointOnObject, // PointOnObject = Just this (8) + 1 << FilterValue::Coincident, // Coincident = Just this (5) + 1 << FilterValue::PointOnObject, // PointOnObject = Just this (6) + 1 << FilterValue::Vertical, // Vertical = Just this (7) + 1 << FilterValue::Horizontal, // Horizontal = Just this (8) 1 << FilterValue::Parallel, // Parallel = Just this (9) 1 << FilterValue::Perpendicular, // Perpendicular = Just this (10) 1 << FilterValue::Tangent, // Tangent = Just this (11) 1 << FilterValue::Equality, // Equality = Just this (12) 1 << FilterValue::Symmetric, // Symmetric = Just this (13) 1 << FilterValue::Block, // Block = Just this (14) - 1 << FilterValue::Distance, // Distance = Just this (15) - 1 << FilterValue::HorizontalDistance, // HorizontalDistance = Just this (16) - 1 << FilterValue::VerticalDistance, // VerticalDistance = Just this (17) + 1 << FilterValue::HorizontalDistance, // HorizontalDistance = Just this (15) + 1 << FilterValue::VerticalDistance, // VerticalDistance = Just this (16) + 1 << FilterValue::Distance, // Distance = Just this (17) 1 << FilterValue::Radius, // Radius = Just this (18) 1 << FilterValue::Weight, // Weight = Just this (19) 1 << FilterValue::Diameter, // Diameter = Just this (20) diff --git a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui index edbae5fc42..80dab0c6de 100644 --- a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui +++ b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.ui @@ -10,7 +10,7 @@ 0 0 274 - 512 + 600 @@ -69,17 +69,7 @@ - Non-Driving - - - - - Horizontal - - - - - Vertical + Reference @@ -92,6 +82,16 @@ Point on Object + + + Vertical + + + + + Horizontal + + Parallel @@ -122,11 +122,6 @@ Block - - - Distance - - Horizontal Distance @@ -137,6 +132,11 @@ Vertical Distance + + + Distance + + Radius diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui index 83149c0f26..5ede5770f6 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui @@ -6,7 +6,7 @@ 0 0 - 325 + 357 388 @@ -67,7 +67,12 @@ - Horizontal + Coincident + + + + + Point on Object @@ -77,12 +82,7 @@ - Coincident - - - - - Point on Object + Horizontal @@ -115,11 +115,6 @@ Block - - - Distance - - Horizontal Distance @@ -130,6 +125,11 @@ Vertical Distance + + + Distance + + Radius From e60e6c32f7c9ad1709dba9ec012e5e67e44999e9 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Mon, 4 Oct 2021 16:25:55 +0200 Subject: [PATCH 022/101] Sketcher: redefine filters and groups of filters ================================================ Filters redefined to match: https://forum.freecadweb.org/viewtopic.php?p=537777#p537777 Group "Datum" stops comprising group "Reference" Datums+References are now selectable as a multi-filter. Fixes the akward behaviour of multiselection: https://forum.freecadweb.org/viewtopic.php?p=537722#p537722 Now when a selection of a filter causes a group of filters comprising the selection to be fulfiled, this is also checked. --- src/Mod/Sketcher/Gui/ConstraintFilters.h | 2 +- .../Gui/ConstraintMultiFilterDialog.cpp | 38 ++++++++++++++++--- .../Sketcher/Gui/TaskSketcherConstrains.cpp | 2 +- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ConstraintFilters.h b/src/Mod/Sketcher/Gui/ConstraintFilters.h index 25a3defdd7..6f86e2e3f0 100644 --- a/src/Mod/Sketcher/Gui/ConstraintFilters.h +++ b/src/Mod/Sketcher/Gui/ConstraintFilters.h @@ -73,7 +73,7 @@ namespace ConstraintFilter { 1 << FilterValue::Geometric | 1 << FilterValue::Horizontal | 1 << FilterValue::Vertical | 1 << FilterValue::Coincident | 1 << FilterValue::PointOnObject | 1 << FilterValue::Parallel | 1 << FilterValue::Perpendicular | 1 << FilterValue::Tangent | 1 << FilterValue::Equality | 1 << FilterValue::Symmetric | 1 << FilterValue::Block | 1 << FilterValue::InternalAlignment, // Geometric = All others not being datums (1) - 1 << FilterValue::Datums | 1 << FilterValue::NonDriving | 1 << FilterValue::Distance | 1 << FilterValue::HorizontalDistance | 1 << FilterValue::VerticalDistance | 1 << FilterValue::Radius | 1 << FilterValue::Weight | 1 << FilterValue::Diameter | 1 << FilterValue::Angle | 1 << FilterValue::SnellsLaw, // Datum = all others not being geometric (2) + 1 << FilterValue::Datums | 1 << FilterValue::Distance | 1 << FilterValue::HorizontalDistance | 1 << FilterValue::VerticalDistance | 1 << FilterValue::Radius | 1 << FilterValue::Weight | 1 << FilterValue::Diameter | 1 << FilterValue::Angle | 1 << FilterValue::SnellsLaw, // Datum = all others not being geometric (2) 1 << FilterValue::Named, // Named = Just this (3) 1 << FilterValue::NonDriving, // NonDriving = Just this (4) 1 << FilterValue::Coincident, // Coincident = Just this (5) diff --git a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.cpp b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.cpp index 22e74bc5b8..88beca930f 100644 --- a/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.cpp +++ b/src/Mod/Sketcher/Gui/ConstraintMultiFilterDialog.cpp @@ -93,15 +93,43 @@ void ConstraintMultiFilterDialog::on_listMultiFilter_itemChanged(QListWidgetItem { int filterindex = ui->listMultiFilter->row(item); - auto aggregate = filterAggregates[filterindex]; + auto itemAggregate = filterAggregates[filterindex]; ui->listMultiFilter->blockSignals(true); - if(item->checkState() == Qt::Checked) { - for(int i = 0; i < ui->listMultiFilter->count(); i++) { - if(aggregate[i]) - ui->listMultiFilter->item(i)->setCheckState(Qt::Checked); + + for(int i = 0; i < ui->listMultiFilter->count(); i++) { + // any filter comprised on the filter of the activated item, gets the same check state + if(itemAggregate[i]) + ui->listMultiFilter->item(i)->setCheckState(item->checkState()); + + // if unchecking, in addition uncheck any group comprising the unchecked item + if(item->checkState() == Qt::Unchecked) { + if(filterAggregates[i][filterindex]) + ui->listMultiFilter->item(i)->setCheckState(Qt::Unchecked); } } + + // Now that all filters are correctly updated to match dependencies, + // if checking, in addition check any group comprising all items that are checked, and check it if all checked. + if(item->checkState() == Qt::Checked) { + for(int i = 0; i < ui->listMultiFilter->count(); i++) { + if(filterAggregates[i][filterindex]) { // only for groups comprising the changed filter + bool mustBeChecked = true; + + for(int j = 0; j < FilterValue::NumFilterValue; j++) { + if (i == j) + continue; + + if (filterAggregates[i][j]) // if it is in group + mustBeChecked = mustBeChecked && ui->listMultiFilter->item(j)->checkState() == Qt::Checked; + } + + if(mustBeChecked) + ui->listMultiFilter->item(i)->setCheckState(Qt::Checked); + } + } + } + ui->listMultiFilter->blockSignals(false); } diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index 6848c25815..26c199e421 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -1125,7 +1125,7 @@ bool TaskSketcherConstrains::isConstraintFiltered(QListWidgetItem * item) bool visible = true; bool showAll = (Filter == FilterValue::All); bool showGeometric = (Filter == FilterValue::Geometric); - bool showDatums = (Filter == FilterValue::Datums); + bool showDatums = (Filter == FilterValue::Datums && constraint->isDriving); bool showNamed = (Filter == FilterValue::Named && !(constraint->Name.empty())); bool showNonDriving = (Filter == FilterValue::NonDriving && !constraint->isDriving); From fa843ad0843866a7430c2220c4f9635e2cdfe79d Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 4 Oct 2021 16:13:41 +0200 Subject: [PATCH 023/101] FEM: writer base, improve working dir handling --- src/Mod/Fem/femsolver/writerbase.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Mod/Fem/femsolver/writerbase.py b/src/Mod/Fem/femsolver/writerbase.py index 05bd29ae50..6ecf97d022 100644 --- a/src/Mod/Fem/femsolver/writerbase.py +++ b/src/Mod/Fem/femsolver/writerbase.py @@ -55,19 +55,29 @@ class FemInputWriter(): self.analysis_type = self.solver_obj.AnalysisType self.document = self.analysis.Document # working dir - self.dir_name = dir_name # if dir_name was not given or if it exists but is not empty: create a temporary dir # Purpose: makes sure the analysis can be run even on wired situation - if not dir_name: + make_tmp_dir = False + if dir_name is None: FreeCAD.Console.PrintWarning( - "Error: FemInputWriter has no working_dir --> " - "we are going to make a temporary one!\n" + "Error: The working_dir in base input file writer class was not set. " + "A temporary directory is used.\n" ) - self.dir_name = self.document.TransientDir.replace( + make_tmp_dir = True + elif not os.path.isdir(dir_name): + FreeCAD.Console.PrintWarning( + "Error: The working_dir: '{}' given to " + "base input file writer class does not exist. " + "A temporary directory is used.\n".format(dir_name) + ) + make_tmp_dir = True + if make_tmp_dir is True: + dir_name = self.document.TransientDir.replace( "\\", "/" ) + "/FemAnl_" + analysis_obj.Uid[-4:] - if not os.path.isdir(self.dir_name): - os.mkdir(self.dir_name) + + os.mkdir(dir_name) + self.dir_name = dir_name # new class attributes self.fc_ver = FreeCAD.Version() From 8bb582f23f2a4bce0f1d0371ea5d42a97a5e38ff Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 4 Oct 2021 16:58:50 +0200 Subject: [PATCH 024/101] FEM: writer base, use tempfile module for the temp directory --- src/Mod/Fem/femsolver/writerbase.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Mod/Fem/femsolver/writerbase.py b/src/Mod/Fem/femsolver/writerbase.py index 6ecf97d022..3728ce9b1b 100644 --- a/src/Mod/Fem/femsolver/writerbase.py +++ b/src/Mod/Fem/femsolver/writerbase.py @@ -72,11 +72,12 @@ class FemInputWriter(): ) make_tmp_dir = True if make_tmp_dir is True: - dir_name = self.document.TransientDir.replace( - "\\", "/" - ) + "/FemAnl_" + analysis_obj.Uid[-4:] - - os.mkdir(dir_name) + from tempfile import mkdtemp + dir_name = mkdtemp(prefix="fcfem_") + FreeCAD.Console.PrintWarning( + "The working directory '{}' was created and will be used." + .format(dir_name) + ) self.dir_name = dir_name # new class attributes From 501dc5867ebd408a982c2eec38a207cff616abeb Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Oct 2021 10:59:07 +0200 Subject: [PATCH 025/101] Points: [skip ci] for CmdPointsConvert command make minimal value dependent on user settings of used decimals --- src/Mod/Points/Gui/Command.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Mod/Points/Gui/Command.cpp b/src/Mod/Points/Gui/Command.cpp index b3fa151137..9069c9d075 100644 --- a/src/Mod/Points/Gui/Command.cpp +++ b/src/Mod/Points/Gui/Command.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -197,10 +198,16 @@ CmdPointsConvert::CmdPointsConvert() void CmdPointsConvert::activated(int iMsg) { Q_UNUSED(iMsg); + double STD_OCC_TOLERANCE = 1e-6; + + int decimals = Base::UnitsApi::getDecimals(); + double tolerance_from_decimals = pow(10., -decimals); + + double minimal_tolerance = tolerance_from_decimals < STD_OCC_TOLERANCE ? STD_OCC_TOLERANCE : tolerance_from_decimals; bool ok; double tol = QInputDialog::getDouble(Gui::getMainWindow(), QObject::tr("Distance"), - QObject::tr("Enter maximum distance:"), 0.1, 0.05, 10.0, 2, &ok, Qt::MSWindowsFixedSizeDialogHint); + QObject::tr("Enter maximum distance:"), 0.1, minimal_tolerance, 10.0, decimals, &ok, Qt::MSWindowsFixedSizeDialogHint); if (!ok) return; From 0fc8460b0f9ca902fee802d32eb9e10695f49b02 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Oct 2021 12:42:48 +0200 Subject: [PATCH 026/101] Part: use UnitsApi::getDecimals in ShapeFromMesh dialog --- src/Mod/Part/Gui/ShapeFromMesh.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/Gui/ShapeFromMesh.cpp b/src/Mod/Part/Gui/ShapeFromMesh.cpp index 5d79b6ca4d..c570f6cf2b 100644 --- a/src/Mod/Part/Gui/ShapeFromMesh.cpp +++ b/src/Mod/Part/Gui/ShapeFromMesh.cpp @@ -28,7 +28,7 @@ #include "ShapeFromMesh.h" #include "ui_ShapeFromMesh.h" -#include +#include #include #include #include @@ -46,8 +46,7 @@ ShapeFromMesh::ShapeFromMesh(QWidget* parent, Qt::WindowFlags fl) double STD_OCC_TOLERANCE = 1e-6; - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units"); - int decimals = hGrp->GetInt("Decimals"); + int decimals = Base::UnitsApi::getDecimals(); double tolerance_from_decimals = pow(10., -decimals); double minimal_tolerance = tolerance_from_decimals < STD_OCC_TOLERANCE ? STD_OCC_TOLERANCE : tolerance_from_decimals; From 32592de8ce9b971b0435ad8a5a90c6269bc7ef00 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Oct 2021 12:43:28 +0200 Subject: [PATCH 027/101] App: expose methods of ComplexGeoData to Python --- src/App/ComplexGeoDataPy.xml | 101 +++++++++---- src/App/ComplexGeoDataPyImp.cpp | 246 ++++++++++++++++++++++++++++++-- 2 files changed, 313 insertions(+), 34 deletions(-) diff --git a/src/App/ComplexGeoDataPy.xml b/src/App/ComplexGeoDataPy.xml index c341734a18..65e3422e9c 100644 --- a/src/App/ComplexGeoDataPy.xml +++ b/src/App/ComplexGeoDataPy.xml @@ -5,7 +5,7 @@ Name="ComplexGeoDataPy" Twin="ComplexGeoData" Include="App/ComplexGeoData.h" - TwinPointer="ComplexGeoData" + TwinPointer="ComplexGeoData" Namespace="Data" FatherInclude="Base/PersistencePy.h" FatherNamespace="Base" @@ -14,34 +14,85 @@ Father of all complex geometric data types + + + Return a list of element types + + + + + Return the number of elements of a type + + Return vertexes and faces from a sub-element - - - Get the BoundBox of the object - - - - - - Get the current transformation of the object as placement - - - - - - Get the current transformation of the object as matrix - - - - - - Geometry Tag - - - + + + Return vertexes and lines from a sub-element + + + + + Return a tuple of points and normals with a given accuracy + + + + + Return a tuple of points and lines with a given accuracy + + + + + Return a tuple of points and triangles with a given accuracy + + + + + Apply an additional translation to the placement + + + + + Apply an additional rotation to the placement + + + + + Apply a transformation to the underlying geometry + + + + + Get the BoundBox of the object + + + + + + Get the center of gravity + + + + + + Get the current transformation of the object as placement + + + + + + Get the current transformation of the object as matrix + + + + + + Geometry Tag + + + diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index a89e02b29d..013035ef5b 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -22,6 +22,9 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif #include "ComplexGeoData.h" @@ -43,24 +46,52 @@ std::string ComplexGeoDataPy::representation(void) const return std::string(""); } -PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) +PyObject* ComplexGeoDataPy::getElementTypes(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + std::vector types = getComplexGeoDataPtr()->getElementTypes(); + Py::List list; + for (auto it : types) { + list.append(Py::String(it)); + } + return Py::new_reference_to(list); +} + +PyObject* ComplexGeoDataPy::countSubElements(PyObject *args) +{ + char *type; + if (!PyArg_ParseTuple(args, "s", &type)) + return nullptr; + + try { + unsigned long count = getComplexGeoDataPtr()->countSubElements(type); + return Py::new_reference_to(Py::Long(count)); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to count sub-elements from object"); + return nullptr; + } +} + +PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) { char *type; int index; if (!PyArg_ParseTuple(args, "si", &type, &index)) - return 0; + return nullptr; std::vector points; std::vector normals; std::vector facets; try { - Data::Segment* segm = getComplexGeoDataPtr()->getSubElement(type, index); - getComplexGeoDataPtr()->getFacesFromSubelement(segm, points, normals, facets); - delete segm; + std::unique_ptr segm(getComplexGeoDataPtr()->getSubElement(type, index)); + getComplexGeoDataPtr()->getFacesFromSubelement(segm.get(), points, normals, facets); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); - return 0; + return nullptr; } Py::Tuple tuple(2); @@ -82,17 +113,214 @@ PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) return Py::new_reference_to(tuple); } -Py::Object ComplexGeoDataPy::getBoundBox(void) const +PyObject* ComplexGeoDataPy::getLinesFromSubelement(PyObject *args) +{ + char *type; + int index; + if (!PyArg_ParseTuple(args, "si", &type, &index)) + return nullptr; + + std::vector points; + std::vector lines; + try { + std::unique_ptr segm(getComplexGeoDataPtr()->getSubElement(type, index)); + getComplexGeoDataPtr()->getLinesFromSubelement(segm.get(), points, lines); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) + vertex.append(Py::asObject(new Base::VectorPy(*it))); + tuple.setItem(0, vertex); + Py::List line; + for (std::vector::const_iterator + it = lines.begin(); it != lines.end(); ++it) { + Py::Tuple l(2); + l.setItem(0,Py::Int((int)it->I1)); + l.setItem(1,Py::Int((int)it->I2)); + line.append(l); + } + tuple.setItem(1, line); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::getPoints(PyObject *args) +{ + double accuracy = 0.05; + if (!PyArg_ParseTuple(args, "d", &accuracy)) + return nullptr; + + std::vector points; + std::vector normals; + try { + getComplexGeoDataPtr()->getPoints(points, normals, accuracy); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) { + vertex.append(Py::asObject(new Base::VectorPy(*it))); + } + tuple.setItem(0, vertex); + + Py::List normal; + for (std::vector::const_iterator it = normals.begin(); + it != normals.end(); ++it) { + vertex.append(Py::asObject(new Base::VectorPy(*it))); + } + tuple.setItem(1, normal); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::getLines(PyObject *args) +{ + double accuracy = 0.05; + if (!PyArg_ParseTuple(args, "d", &accuracy)) + return nullptr; + + std::vector points; + std::vector lines; + try { + getComplexGeoDataPtr()->getLines(points, lines, accuracy); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) + vertex.append(Py::asObject(new Base::VectorPy(*it))); + tuple.setItem(0, vertex); + Py::List line; + for (std::vector::const_iterator + it = lines.begin(); it != lines.end(); ++it) { + Py::Tuple l(2); + l.setItem(0,Py::Int((int)it->I1)); + l.setItem(1,Py::Int((int)it->I2)); + line.append(l); + } + tuple.setItem(1, line); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::getFaces(PyObject *args) +{ + double accuracy = 0.05; + if (!PyArg_ParseTuple(args, "d", &accuracy)) + return nullptr; + + std::vector points; + std::vector facets; + try { + getComplexGeoDataPtr()->getFaces(points, facets, accuracy); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) + vertex.append(Py::asObject(new Base::VectorPy(*it))); + tuple.setItem(0, vertex); + Py::List facet; + for (std::vector::const_iterator + it = facets.begin(); it != facets.end(); ++it) { + Py::Tuple f(3); + f.setItem(0,Py::Int((int)it->I1)); + f.setItem(1,Py::Int((int)it->I2)); + f.setItem(2,Py::Int((int)it->I3)); + facet.append(f); + } + tuple.setItem(1, facet); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::applyTranslation(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&obj)) + return nullptr; + + try { + Base::Vector3d move = static_cast(obj)->value(); + getComplexGeoDataPtr()->applyTranslation(move); + Py_Return; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation"); + return nullptr; + } +} + +PyObject* ComplexGeoDataPy::applyRotation(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type),&obj)) + return nullptr; + + try { + Base::Rotation rot = static_cast(obj)->value(); + getComplexGeoDataPtr()->applyRotation(rot); + Py_Return; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation"); + return nullptr; + } +} + +PyObject* ComplexGeoDataPy::transformGeometry(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&obj)) + return nullptr; + + try { + Base::Matrix4D mat = static_cast(obj)->value(); + getComplexGeoDataPtr()->transformGeometry(mat); + Py_Return; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to transform geometry"); + return nullptr; + } +} + +Py::Object ComplexGeoDataPy::getBoundBox() const { return Py::BoundingBox(getComplexGeoDataPtr()->getBoundBox()); } +Py::Object ComplexGeoDataPy::getCenterOfGravity() const +{ + Base::Vector3d center; + if (getComplexGeoDataPtr()->getCenterOfGravity(center)) + return Py::Vector(center); + throw Py::RuntimeError("Cannot get center of gravity"); +} + Py::Object ComplexGeoDataPy::getPlacement(void) const { return Py::Placement(getComplexGeoDataPtr()->getPlacement()); } -void ComplexGeoDataPy::setPlacement(Py::Object arg) +void ComplexGeoDataPy::setPlacement(Py::Object arg) { PyObject* p = arg.ptr(); if (PyObject_TypeCheck(p, &(Base::PlacementPy::Type))) { @@ -112,7 +340,7 @@ Py::Object ComplexGeoDataPy::getMatrix(void) const } // FIXME would be better to call it setTransform() as in all other interfaces... -void ComplexGeoDataPy::setMatrix(Py::Object arg) +void ComplexGeoDataPy::setMatrix(Py::Object arg) { PyObject* p = arg.ptr(); if (PyObject_TypeCheck(p, &(Base::MatrixPy::Type))) { From ff24678a7c7ab063acf5e7020bcfb1d0682bdb1d Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 5 Oct 2021 13:38:43 +0200 Subject: [PATCH 028/101] Update init_tools.py Removed "_temp" from docstrings. --- src/Mod/Draft/draftutils/init_tools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index 9a5f226dff..520e54a72c 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -189,7 +189,7 @@ def init_toolbar(workbench, toolbar, cmd_list): The name of the toolbar. cmd_list: list of strings or list of strings and tuples - See f.e. the return value of get_draft_drawing_commands_temp. + See f.e. the return value of get_draft_drawing_commands. """ for cmd in cmd_list: if isinstance(cmd, tuple): @@ -212,7 +212,7 @@ def init_menu(workbench, menu_list, cmd_list): submenus (if any), are added to the last (sub)menu in the list. cmd_list: list of strings or list of strings and tuples - See f.e. the return value of get_draft_drawing_commands_temp. + See f.e. the return value of get_draft_drawing_commands. """ for cmd in cmd_list: if isinstance(cmd, tuple): From f0025568033c25392c669294e33ab93906a50519 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:56:22 +0200 Subject: [PATCH 029/101] Update Draft.py --- src/Mod/Draft/Draft.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 5287778e8e..7dcef93c70 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -422,8 +422,8 @@ if App.GuiUp: from draftviewproviders.view_text import (ViewProviderText, ViewProviderDraftText) -from draftobjects.hatch import (Draft_Hatch_Object) -from draftmake.make_hatch import (make_hatch, makeHatch) +from draftobjects.hatch import (Hatch) +from draftmake.make_hatch import (make_hatch) if App.GuiUp: from draftviewproviders.view_hatch import (Draft_Hatch_ViewProvider) From 470f9307f1346c3e32bd5802c5da5c2bd1d21366 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:57:00 +0200 Subject: [PATCH 030/101] Update hatch.py --- src/Mod/Draft/draftobjects/hatch.py | 45 +++++++++++++++-------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/Mod/Draft/draftobjects/hatch.py b/src/Mod/Draft/draftobjects/hatch.py index 3e3eb3a8c3..aed15db243 100644 --- a/src/Mod/Draft/draftobjects/hatch.py +++ b/src/Mod/Draft/draftobjects/hatch.py @@ -30,7 +30,7 @@ from draftutils.translate import translate, QT_TRANSLATE_NOOP -class Draft_Hatch_Object: +class Hatch: def __init__(self,obj): @@ -41,12 +41,6 @@ class Draft_Hatch_Object: def setProperties(self,obj): pl = obj.PropertiesList - if not "Placement" in pl: - obj.addProperty("App::PropertyPlacement","Placement","Hatch", - QT_TRANSLATE_NOOP("App::Property","The placement of this object")) - if not "Shape" in pl: - obj.addProperty("Part::PropertyPartShape","Shape","Hatch", - QT_TRANSLATE_NOOP("App::Property","The shape of this object")) if not "Base" in pl: obj.addProperty("App::PropertyLink","Base","Hatch", QT_TRANSLATE_NOOP("App::Property","The base object used by this object")) @@ -103,23 +97,30 @@ class Draft_Hatch_Object: pla = obj.Placement shapes = [] for face in obj.Base.Shape.Faces: - face = face.copy() - if obj.Translate: - bpoint = face.CenterOfMass - norm = face.normalAt(0,0) - fpla = FreeCAD.Placement(bpoint,FreeCAD.Rotation(FreeCAD.Vector(0,0,1),norm)) - face.Placement = face.Placement.multiply(fpla.inverse()) - if obj.Rotation: - face.rotate(FreeCAD.Vector(),FreeCAD.Vector(0,0,1),obj.Rotation) - shape = TechDraw.makeGeomHatch(face,obj.Scale,obj.Pattern,obj.File) - if obj.Rotation: - shape.rotate(FreeCAD.Vector(),FreeCAD.Vector(0,0,1),-obj.Rotation) - if obj.Translate: - shape.Placement = shape.Placement.multiply(fpla) - shapes.append(shape) + if face.findPlane(): # Only planar faces. + face = face.copy() + if obj.Translate: + e = face.Edges[0] # Todo: check for almost zero-length edge. + sta = e.firstVertex().Point + end = e.lastVertex().Point + u = end.sub(sta).normalize() + w = face.normalAt(0, 0) + v = w.cross(u) + m = FreeCAD.Matrix(u.x, v.x, w.x, sta.x, + u.y, v.y, w.y, sta.y, + u.z, v.z, w.z, sta.z, + 0.0, 0.0, 0.0, 1.0) + face = face.transformGeometry(m.inverse()).Faces[0] + if obj.Rotation.Value: + face.rotate(FreeCAD.Vector(), FreeCAD.Vector(0,0,1), -obj.Rotation) + shape = TechDraw.makeGeomHatch(face, obj.Scale, obj.Pattern, obj.File) + if obj.Rotation.Value: + shape.rotate(FreeCAD.Vector(), FreeCAD.Vector(0,0,1), obj.Rotation) + if obj.Translate: + shape = shape.transformGeometry(m) + shapes.append(shape) if shapes: obj.Shape = Part.makeCompound(shapes) - obj.Placement = pla def getPatterns(self,filename): From 1f2a95f990de76350635df18735fa0c14b966fd6 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:58:09 +0200 Subject: [PATCH 031/101] Update gui_hatch.py --- src/Mod/Draft/draftguitools/gui_hatch.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_hatch.py b/src/Mod/Draft/draftguitools/gui_hatch.py index a853188a47..2f7f2a27a5 100644 --- a/src/Mod/Draft/draftguitools/gui_hatch.py +++ b/src/Mod/Draft/draftguitools/gui_hatch.py @@ -25,10 +25,11 @@ import os import FreeCAD +import draftguitools.gui_base as gui_base + from draftutils.translate import translate, QT_TRANSLATE_NOOP - -class Draft_Hatch: +class Draft_Hatch(gui_base.GuiCommandSimplest): def GetResources(self): @@ -36,7 +37,7 @@ class Draft_Hatch: return {'Pixmap' : "Draft_Hatch", 'MenuText': QT_TRANSLATE_NOOP("Draft_Hatch", "Hatch"), 'Accel': "H, A", - 'ToolTip' : QT_TRANSLATE_NOOP("Draft_Hatch", "Create hatches on selected faces")} + 'ToolTip' : QT_TRANSLATE_NOOP("Draft_Hatch", "Creates hatches on the faces of a selected object")} def Activated(self): @@ -89,7 +90,7 @@ class Draft_Hatch_TaskPanel: # create new hatch object FreeCAD.ActiveDocument.openTransaction("Create Hatch") FreeCADGui.addModule("Draft") - cmd = "Draft.makeHatch(" + cmd = "Draft.make_hatch(" cmd += "baseobject=FreeCAD.ActiveDocument.getObject(\""+self.baseobj.Name cmd += "\"),filename=\""+self.form.File.property("fileName") cmd += "\",pattern=\""+self.form.Pattern.currentText() From 30b784a59699c1c82f006413504226c4215421ad Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:58:47 +0200 Subject: [PATCH 032/101] Update make_hatch.py --- src/Mod/Draft/draftmake/make_hatch.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Mod/Draft/draftmake/make_hatch.py b/src/Mod/Draft/draftmake/make_hatch.py index 8f834f7767..fc3021e8ef 100644 --- a/src/Mod/Draft/draftmake/make_hatch.py +++ b/src/Mod/Draft/draftmake/make_hatch.py @@ -23,12 +23,12 @@ """This module contains FreeCAD commands for the Draft workbench""" import FreeCAD -from draftobjects.hatch import Draft_Hatch_Object +from draftobjects.hatch import Hatch from draftviewproviders.view_hatch import Draft_Hatch_ViewProvider -def makeHatch(baseobject, filename, pattern, scale, rotation): +def make_hatch(baseobject, filename, pattern, scale, rotation): - """makeHatch(baseobject, filename, pattern, scale, rotation): Creates and returns a + """make_hatch(baseobject, filename, pattern, scale, rotation): Creates and returns a hatch object made by applying the given pattern of the given PAT file to the faces of the given base object. Given scale and rotation factors are applied to the hatch object. The result is a Part-based object created in the active document.""" @@ -36,7 +36,7 @@ def makeHatch(baseobject, filename, pattern, scale, rotation): if not FreeCAD.ActiveDocument: return obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Hatch") - Draft_Hatch_Object(obj) + Hatch(obj) obj.Base = baseobject obj.File = filename obj.Pattern = pattern @@ -44,5 +44,3 @@ def makeHatch(baseobject, filename, pattern, scale, rotation): obj.Rotation = rotation if FreeCAD.GuiUp: Draft_Hatch_ViewProvider(obj.ViewObject) - -make_hatch = makeHatch From b6d90bf575342703390b84a8423c970768dde104 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Oct 2021 19:18:12 +0200 Subject: [PATCH 033/101] App: [skip ci] make Matrix a dynamic attribute of ComplexGeoDataPy --- src/App/ComplexGeoDataPy.xml | 6 ---- src/App/ComplexGeoDataPyImp.cpp | 62 ++++++++++++++++----------------- 2 files changed, 31 insertions(+), 37 deletions(-) diff --git a/src/App/ComplexGeoDataPy.xml b/src/App/ComplexGeoDataPy.xml index 65e3422e9c..c38e89532f 100644 --- a/src/App/ComplexGeoDataPy.xml +++ b/src/App/ComplexGeoDataPy.xml @@ -82,12 +82,6 @@ - - - Get the current transformation of the object as matrix - - - Geometry Tag diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index 013035ef5b..a493df7187 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -41,7 +41,7 @@ using namespace Data; using namespace Base; // returns a string which represent the object e.g. when printed in python -std::string ComplexGeoDataPy::representation(void) const +std::string ComplexGeoDataPy::representation() const { return std::string(""); } @@ -78,8 +78,8 @@ PyObject* ComplexGeoDataPy::countSubElements(PyObject *args) PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) { char *type; - int index; - if (!PyArg_ParseTuple(args, "si", &type, &index)) + unsigned long index; + if (!PyArg_ParseTuple(args, "sk", &type, &index)) return nullptr; std::vector points; @@ -104,9 +104,9 @@ PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) for (std::vector::const_iterator it = facets.begin(); it != facets.end(); ++it) { Py::Tuple f(3); - f.setItem(0,Py::Int((int)it->I1)); - f.setItem(1,Py::Int((int)it->I2)); - f.setItem(2,Py::Int((int)it->I3)); + f.setItem(0,Py::Int(int(it->I1))); + f.setItem(1,Py::Int(int(it->I2))); + f.setItem(2,Py::Int(int(it->I3))); facet.append(f); } tuple.setItem(1, facet); @@ -315,7 +315,7 @@ Py::Object ComplexGeoDataPy::getCenterOfGravity() const throw Py::RuntimeError("Cannot get center of gravity"); } -Py::Object ComplexGeoDataPy::getPlacement(void) const +Py::Object ComplexGeoDataPy::getPlacement() const { return Py::Placement(getComplexGeoDataPtr()->getPlacement()); } @@ -334,40 +334,40 @@ void ComplexGeoDataPy::setPlacement(Py::Object arg) } } -Py::Object ComplexGeoDataPy::getMatrix(void) const +Py::Int ComplexGeoDataPy::getTag() const { - return Py::Matrix(getComplexGeoDataPtr()->getTransform()); -} - -// FIXME would be better to call it setTransform() as in all other interfaces... -void ComplexGeoDataPy::setMatrix(Py::Object arg) -{ - PyObject* p = arg.ptr(); - if (PyObject_TypeCheck(p, &(Base::MatrixPy::Type))) { - Base::Matrix4D mat = static_cast(p)->value(); - getComplexGeoDataPtr()->setTransform(mat); - } - else { - std::string error = std::string("type must be 'Matrix', not "); - error += p->ob_type->tp_name; - throw Py::TypeError(error); - } -} - -Py::Int ComplexGeoDataPy::getTag() const { return Py::Int(getComplexGeoDataPtr()->Tag); } -void ComplexGeoDataPy::setTag(Py::Int tag) { +void ComplexGeoDataPy::setTag(Py::Int tag) +{ getComplexGeoDataPtr()->Tag = tag; } -PyObject *ComplexGeoDataPy::getCustomAttributes(const char* /*attr*/) const +PyObject* ComplexGeoDataPy::getCustomAttributes(const char* attr) const { - return 0; + // Support for backward compatibility + if (strcmp(attr, "Matrix") == 0) { + Py::Matrix mat(getComplexGeoDataPtr()->getTransform()); + return Py::new_reference_to(mat); + } + return nullptr; } -int ComplexGeoDataPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +int ComplexGeoDataPy::setCustomAttributes(const char* attr, PyObject* obj) { + // Support for backward compatibility + if (strcmp(attr, "Matrix") == 0) { + if (PyObject_TypeCheck(obj, &(Base::MatrixPy::Type))) { + Base::Matrix4D mat = static_cast(obj)->value(); + getComplexGeoDataPtr()->setTransform(mat); + return 1; + } + else { + std::string error = std::string("type must be 'Matrix', not "); + error += obj->ob_type->tp_name; + throw Py::TypeError(error); + } + } return 0; } From 7cf6230a0086fe83ad8c564b5145e6bc94efed73 Mon Sep 17 00:00:00 2001 From: mwganson Date: Tue, 5 Oct 2021 22:32:33 -0500 Subject: [PATCH 034/101] [AddonManager] -- put Restart now and Restart later as button text instead of in the dialog text --- src/Mod/AddonManager/AddonManager.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Mod/AddonManager/AddonManager.py b/src/Mod/AddonManager/AddonManager.py index 452fb7e90d..083bec0aa3 100644 --- a/src/Mod/AddonManager/AddonManager.py +++ b/src/Mod/AddonManager/AddonManager.py @@ -200,11 +200,14 @@ class CommandAddonManager: m.setWindowIcon(QtGui.QIcon(":/icons/AddonManager.svg")) m.setText(translate("AddonsInstaller", "You must restart FreeCAD for changes to take " - "effect. Press Ok to restart FreeCAD now, or " - "Cancel to restart later.")) + "effect.")) m.setIcon(m.Warning) m.setStandardButtons(m.Ok | m.Cancel) m.setDefaultButton(m.Cancel) + okBtn = m.button(QtGui.QMessageBox.StandardButton.Ok) + cancelBtn = m.button(QtGui.QMessageBox.StandardButton.Cancel) + okBtn.setText(translate("AddonsInstaller","Restart now")) + cancelBtn.setText(translate("AddonsInstaller","Restart later")) ret = m.exec_() if ret == m.Ok: shutil.rmtree(self.macro_repo_dir, onerror=self.remove_readonly) From b46e45419089a0b3b2e14eadcb7c0e073d61b9a3 Mon Sep 17 00:00:00 2001 From: mwganson Date: Tue, 5 Oct 2021 23:02:15 -0500 Subject: [PATCH 035/101] [Dragger] add dragger (Std_TransformManip) to right click context menu when right clicking on an object in the 3D view --- src/Gui/Workbench.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index cb54091f82..c1a50ab638 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -562,7 +562,7 @@ void StdWorkbench::setupContextMenu(const char* recipient, MenuItem* item) const *item << "Separator" << "Std_SetAppearance" << "Std_ToggleVisibility" << "Std_ToggleSelectability" << "Std_TreeSelection" << "Std_RandomColor" << "Separator" << "Std_Delete" - << "Std_SendToPythonConsole"; + << "Std_SendToPythonConsole" << "Std_TransformManip"; } } else if (strcmp(recipient,"Tree") == 0) From cba89c64a45192f932e1705b0e3b79752681d577 Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 4 Aug 2021 07:22:30 -0400 Subject: [PATCH 036/101] [FEM] Rename menuetext -> menutext --- src/Mod/Fem/femcommands/commands.py | 90 ++++++++++++++--------------- src/Mod/Fem/femcommands/manager.py | 6 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 64565ebd6a..5eb4472dc4 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -49,7 +49,7 @@ class _Analysis(CommandManager): def __init__(self): super(_Analysis, self).__init__() - self.menuetext = "Analysis container" + self.menutext = "Analysis container" self.accel = "S, A" self.tooltip = "Creates an analysis container with standard solver CalculiX" self.is_active = "with_document" @@ -74,7 +74,7 @@ class _ClippingPlaneAdd(CommandManager): def __init__(self): super(_ClippingPlaneAdd, self).__init__() - self.menuetext = "Clipping plane on face" + self.menutext = "Clipping plane on face" self.tooltip = "Add a clipping plane on a selected face" self.is_active = "with_document" @@ -123,7 +123,7 @@ class _ClippingPlaneRemoveAll(CommandManager): def __init__(self): super(_ClippingPlaneRemoveAll, self).__init__() - self.menuetext = "Remove all clipping planes" + self.menutext = "Remove all clipping planes" self.tooltip = "Remove all clipping planes" self.is_active = "with_document" @@ -143,7 +143,7 @@ class _ConstantVacuumPermittivity(CommandManager): def __init__(self): super(_ConstantVacuumPermittivity, self).__init__() self.pixmap = "fem-solver-analysis-thermomechanical.svg" - self.menuetext = "Constant vacuum permittivity" + self.menutext = "Constant vacuum permittivity" self.tooltip = "Creates a FEM constant vacuum permittivity to overwrite standard value" self.is_active = "with_document" self.is_active = "with_analysis" @@ -156,7 +156,7 @@ class _ConstraintBodyHeatSource(CommandManager): def __init__(self): super(_ConstraintBodyHeatSource, self).__init__() self.pixmap = "FEM_ConstraintHeatflux" # the heatflux icon is used - self.menuetext = "Constraint body heat source" + self.menutext = "Constraint body heat source" self.tooltip = "Creates a FEM constraint body heat source" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -167,7 +167,7 @@ class _ConstraintCentrif(CommandManager): def __init__(self): super(_ConstraintCentrif, self).__init__() - self.menuetext = "Constraint centrif" + self.menutext = "Constraint centrif" self.tooltip = "Creates a FEM constraint centrif" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -178,7 +178,7 @@ class _ConstraintElectrostaticPotential(CommandManager): def __init__(self): super(_ConstraintElectrostaticPotential, self).__init__() - self.menuetext = "Constraint electrostatic potential" + self.menutext = "Constraint electrostatic potential" self.tooltip = "Creates a FEM constraint electrostatic potential" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -189,7 +189,7 @@ class _ConstraintFlowVelocity(CommandManager): def __init__(self): super(_ConstraintFlowVelocity, self).__init__() - self.menuetext = "Constraint flow velocity" + self.menutext = "Constraint flow velocity" self.tooltip = "Creates a FEM constraint flow velocity" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -200,7 +200,7 @@ class _ConstraintInitialFlowVelocity(CommandManager): def __init__(self): super(_ConstraintInitialFlowVelocity, self).__init__() - self.menuetext = "Constraint initial flow velocity" + self.menutext = "Constraint initial flow velocity" self.tooltip = "Creates a FEM constraint initial flow velocity" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -211,7 +211,7 @@ class _ConstraintSectionPrint(CommandManager): def __init__(self): super(_ConstraintSectionPrint, self).__init__() - self.menuetext = "Constraint sectionprint" + self.menutext = "Constraint sectionprint" self.tooltip = "Creates a FEM constraint sectionprint" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -222,7 +222,7 @@ class _ConstraintSelfWeight(CommandManager): def __init__(self): super(_ConstraintSelfWeight, self).__init__() - self.menuetext = "Constraint self weight" + self.menutext = "Constraint self weight" self.tooltip = "Creates a FEM constraint self weight" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -233,7 +233,7 @@ class _ConstraintTie(CommandManager): def __init__(self): super(_ConstraintTie, self).__init__() - self.menuetext = "Constraint tie" + self.menutext = "Constraint tie" self.tooltip = "Creates a FEM constraint tie" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -244,7 +244,7 @@ class _ElementFluid1D(CommandManager): def __init__(self): super(_ElementFluid1D, self).__init__() - self.menuetext = "Fluid section for 1D flow" + self.menutext = "Fluid section for 1D flow" self.tooltip = "Creates a FEM fluid section for 1D flow" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -255,7 +255,7 @@ class _ElementGeometry1D(CommandManager): def __init__(self): super(_ElementGeometry1D, self).__init__() - self.menuetext = "Beam cross section" + self.menutext = "Beam cross section" self.tooltip = "Creates a FEM beam cross section" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -266,7 +266,7 @@ class _ElementGeometry2D(CommandManager): def __init__(self): super(_ElementGeometry2D, self).__init__() - self.menuetext = "Shell plate thickness" + self.menutext = "Shell plate thickness" self.tooltip = "Creates a FEM shell plate thickness" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -277,7 +277,7 @@ class _ElementRotation1D(CommandManager): def __init__(self): super(_ElementRotation1D, self).__init__() - self.menuetext = "Beam rotation" + self.menutext = "Beam rotation" self.tooltip = "Creates a FEM beam rotation" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -288,7 +288,7 @@ class _EquationElectrostatic(CommandManager): def __init__(self): super(_EquationElectrostatic, self).__init__() - self.menuetext = "Electrostatic equation" + self.menutext = "Electrostatic equation" self.tooltip = "Creates a FEM equation for electrostatic" self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -299,7 +299,7 @@ class _EquationElasticity(CommandManager): def __init__(self): super(_EquationElasticity, self).__init__() - self.menuetext = "Elasticity equation" + self.menutext = "Elasticity equation" self.tooltip = "Creates a FEM equation for elasticity" self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -310,7 +310,7 @@ class _EquationFlow(CommandManager): def __init__(self): super(_EquationFlow, self).__init__() - self.menuetext = "Flow equation" + self.menutext = "Flow equation" self.tooltip = "Creates a FEM equation for flow" self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -321,7 +321,7 @@ class _EquationFlux(CommandManager): def __init__(self): super(_EquationFlux, self).__init__() - self.menuetext = "Flux equation" + self.menutext = "Flux equation" self.tooltip = "Creates a FEM equation for flux" self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -332,7 +332,7 @@ class _EquationElectricforce(CommandManager): def __init__(self): super(_EquationElectricforce, self).__init__() - self.menuetext = "Electricforce equation" + self.menutext = "Electricforce equation" self.tooltip = "Creates a FEM equation for electric forces" self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -343,7 +343,7 @@ class _EquationHeat(CommandManager): def __init__(self): super(_EquationHeat, self).__init__() - self.menuetext = "Heat equation" + self.menutext = "Heat equation" self.tooltip = "Creates a FEM equation for heat" self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -355,7 +355,7 @@ class _Examples(CommandManager): def __init__(self): super(_Examples, self).__init__() self.pixmap = "FemWorkbench" - self.menuetext = "Open FEM examples" + self.menutext = "Open FEM examples" self.tooltip = "Open FEM examples" self.is_active = "always" @@ -370,7 +370,7 @@ class _MaterialEditor(CommandManager): def __init__(self): super(_MaterialEditor, self).__init__() self.pixmap = "Arch_Material_Group" - self.menuetext = "Material editor" + self.menutext = "Material editor" self.tooltip = "Opens the FreeCAD material editor" self.is_active = "always" @@ -384,7 +384,7 @@ class _MaterialFluid(CommandManager): def __init__(self): super(_MaterialFluid, self).__init__() - self.menuetext = "Material for fluid" + self.menutext = "Material for fluid" self.tooltip = "Creates a FEM material for fluid" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -395,7 +395,7 @@ class _MaterialMechanicalNonlinear(CommandManager): def __init__(self): super(_MaterialMechanicalNonlinear, self).__init__() - self.menuetext = "Nonlinear mechanical material" + self.menutext = "Nonlinear mechanical material" self.tooltip = "Creates a nonlinear mechanical material" self.is_active = "with_material_solid" @@ -459,7 +459,7 @@ class _MaterialReinforced(CommandManager): def __init__(self): super(_MaterialReinforced, self).__init__() - self.menuetext = "Reinforced material (concrete)" + self.menutext = "Reinforced material (concrete)" self.tooltip = "Creates a material for reinforced matrix material such as concrete" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -470,7 +470,7 @@ class _MaterialSolid(CommandManager): def __init__(self): super(_MaterialSolid, self).__init__() - self.menuetext = "Material for solid" + self.menutext = "Material for solid" self.accel = "M, S" self.tooltip = "Creates a FEM material for solid" self.is_active = "with_analysis" @@ -482,7 +482,7 @@ class _FEMMesh2Mesh(CommandManager): def __init__(self): super(_FEMMesh2Mesh, self).__init__() - self.menuetext = "FEM mesh to mesh" + self.menutext = "FEM mesh to mesh" self.tooltip = "Convert the surface of a FEM mesh to a mesh" self.is_active = "with_femmesh_andor_res" @@ -523,7 +523,7 @@ class _MeshBoundaryLayer(CommandManager): def __init__(self): super(_MeshBoundaryLayer, self).__init__() - self.menuetext = "FEM mesh boundary layer" + self.menutext = "FEM mesh boundary layer" self.tooltip = "Creates a FEM mesh boundary layer" self.is_active = "with_gmsh_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" @@ -534,7 +534,7 @@ class _MeshClear(CommandManager): def __init__(self): super(_MeshClear, self).__init__() - self.menuetext = "Clear FEM mesh" + self.menutext = "Clear FEM mesh" self.tooltip = "Clear the Mesh of a FEM mesh object" self.is_active = "with_femmesh" @@ -553,7 +553,7 @@ class _MeshDisplayInfo(CommandManager): def __init__(self): super(_MeshDisplayInfo, self).__init__() - self.menuetext = "Display FEM mesh info" + self.menutext = "Display FEM mesh info" self.tooltip = "Display FEM mesh info" self.is_active = "with_femmesh" @@ -576,7 +576,7 @@ class _MeshGmshFromShape(CommandManager): def __init__(self): super(_MeshGmshFromShape, self).__init__() - self.menuetext = "FEM mesh from shape by Gmsh" + self.menutext = "FEM mesh from shape by Gmsh" self.tooltip = "Create a FEM mesh from a shape by Gmsh mesher" self.is_active = "with_part_feature" @@ -615,7 +615,7 @@ class _MeshGroup(CommandManager): def __init__(self): super(_MeshGroup, self).__init__() - self.menuetext = "FEM mesh group" + self.menutext = "FEM mesh group" self.tooltip = "Creates a FEM mesh group" self.is_active = "with_gmsh_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" @@ -626,7 +626,7 @@ class _MeshNetgenFromShape(CommandManager): def __init__(self): super(_MeshNetgenFromShape, self).__init__() - self.menuetext = "FEM mesh from shape by Netgen" + self.menutext = "FEM mesh from shape by Netgen" self.tooltip = "Create a FEM mesh from a solid or face shape by Netgen internal mesher" self.is_active = "with_part_feature" @@ -665,7 +665,7 @@ class _MeshRegion(CommandManager): def __init__(self): super(_MeshRegion, self).__init__() - self.menuetext = "FEM mesh region" + self.menutext = "FEM mesh region" self.tooltip = "Creates a FEM mesh region" self.is_active = "with_gmsh_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" @@ -676,7 +676,7 @@ class _ResultShow(CommandManager): def __init__(self): super(_ResultShow, self).__init__() - self.menuetext = "Show result" + self.menutext = "Show result" self.accel = "R, S" self.tooltip = "Shows and visualizes selected result data" self.is_active = "with_selresult" @@ -690,7 +690,7 @@ class _ResultsPurge(CommandManager): def __init__(self): super(_ResultsPurge, self).__init__() - self.menuetext = "Purge results" + self.menutext = "Purge results" self.accel = "R, P" self.tooltip = "Purges all results from active analysis" self.is_active = "with_results" @@ -706,7 +706,7 @@ class _SolverCxxtools(CommandManager): def __init__(self): super(_SolverCxxtools, self).__init__() self.pixmap = "FEM_SolverStandard" - self.menuetext = "Solver CalculiX Standard" + self.menutext = "Solver CalculiX Standard" self.accel = "S, X" self.tooltip = "Creates a standard FEM solver CalculiX with ccx tools" self.is_active = "with_analysis" @@ -741,7 +741,7 @@ class _SolverCalculix(CommandManager): def __init__(self): super(_SolverCalculix, self).__init__() self.pixmap = "FEM_SolverStandard" - self.menuetext = "Solver CalculiX (new framework)" + self.menutext = "Solver CalculiX (new framework)" self.accel = "S, C" self.tooltip = "Creates a FEM solver CalculiX new framework (less result error handling)" self.is_active = "with_analysis" @@ -754,7 +754,7 @@ class _SolverControl(CommandManager): def __init__(self): super(_SolverControl, self).__init__() - self.menuetext = "Solver job control" + self.menutext = "Solver job control" self.accel = "S, T" self.tooltip = "Changes solver attributes and runs the calculations for the selected solver" self.is_active = "with_solver" @@ -768,7 +768,7 @@ class _SolverElmer(CommandManager): def __init__(self): super(_SolverElmer, self).__init__() - self.menuetext = "Solver Elmer" + self.menutext = "Solver Elmer" self.accel = "S, E" self.tooltip = "Creates a FEM solver Elmer" self.is_active = "with_analysis" @@ -781,7 +781,7 @@ class _SolverMystran(CommandManager): def __init__(self): super(_SolverMystran, self).__init__() self.pixmap = "FEM_SolverStandard" - self.menuetext = "Solver Mystran" + self.menutext = "Solver Mystran" self.accel = "S, M" self.tooltip = "Creates a FEM solver Mystran" self.is_active = "with_analysis" @@ -793,7 +793,7 @@ class _SolverRun(CommandManager): def __init__(self): super(_SolverRun, self).__init__() - self.menuetext = "Run solver calculations" + self.menutext = "Run solver calculations" self.accel = "S, R" self.tooltip = "Runs the calculations for the selected solver" self.is_active = "with_solver" @@ -810,7 +810,7 @@ class _SolverZ88(CommandManager): def __init__(self): super(_SolverZ88, self).__init__() - self.menuetext = "Solver Z88" + self.menutext = "Solver Z88" self.accel = "S, Z" self.tooltip = "Creates a FEM solver Z88" self.is_active = "with_analysis" diff --git a/src/Mod/Fem/femcommands/manager.py b/src/Mod/Fem/femcommands/manager.py index 508b251bc3..d13d8a95dc 100644 --- a/src/Mod/Fem/femcommands/manager.py +++ b/src/Mod/Fem/femcommands/manager.py @@ -46,9 +46,9 @@ class CommandManager(object): self.command = "FEM" + self.__class__.__name__ self.pixmap = self.command - self.menuetext = self.__class__.__name__.lstrip("_") + self.menutext = self.__class__.__name__.lstrip("_") self.accel = "" - self.tooltip = "Creates a {}".format(self.menuetext) + self.tooltip = "Creates a {}".format(self.menutext) self.resources = None self.is_active = None @@ -61,7 +61,7 @@ class CommandManager(object): if self.resources is None: self.resources = { "Pixmap": self.pixmap, - "MenuText": QtCore.QT_TRANSLATE_NOOP(self.command, self.menuetext), + "MenuText": QtCore.QT_TRANSLATE_NOOP(self.command, self.menutext), "Accel": self.accel, "ToolTip": QtCore.QT_TRANSLATE_NOOP(self.command, self.tooltip) } From 3867e41f4215a9c2ee455868f82114a32215c4fd Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 4 Aug 2021 07:26:26 -0400 Subject: [PATCH 037/101] Fix trivial typos --- src/Mod/Assembly/App/opendcm/core/property.hpp | 2 +- src/Mod/Fem/femcommands/commands.py | 2 +- src/Mod/Fem/feminout/exportNastranMesh.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Assembly/App/opendcm/core/property.hpp b/src/Mod/Assembly/App/opendcm/core/property.hpp index b0d9b35c7b..62dafc99a1 100644 --- a/src/Mod/Assembly/App/opendcm/core/property.hpp +++ b/src/Mod/Assembly/App/opendcm/core/property.hpp @@ -110,7 +110,7 @@ namespace dcm { * @{ */ /** - * @brief Exeption for property errors + * @brief Exception for property errors * * This exception is thrown when a property related error is detected, for example if a objects is ask for a * property which it does not own. This exceptions own the error-code range from 300-399. diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 5eb4472dc4..782fffc61f 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -119,7 +119,7 @@ class _ClippingPlaneAdd(CommandManager): class _ClippingPlaneRemoveAll(CommandManager): - "The FEM_ClippingPlaneemoveAll command definition" + "The FEM_ClippingPlaneRemoveAll command definition" def __init__(self): super(_ClippingPlaneRemoveAll, self).__init__() diff --git a/src/Mod/Fem/feminout/exportNastranMesh.py b/src/Mod/Fem/feminout/exportNastranMesh.py index 2da80c520e..ef1eb35450 100644 --- a/src/Mod/Fem/feminout/exportNastranMesh.py +++ b/src/Mod/Fem/feminout/exportNastranMesh.py @@ -91,7 +91,7 @@ def write( mesh_pynas_code += missing_code_pnynasmesh # pynas file - basefilename = filename[:len(filename) - 4] # TODO basename is more failsave + basefilename = filename[:len(filename) - 4] # TODO basename is more failsafe pynasf = open(basefilename + ".py", "w") pynasf.write("# written by FreeCAD\n\n\n") pynasf.write("from pyNastran.bdf.bdf import BDF\n") From 0b9d4db8149af4bb7374a01376e174995d93d623 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Wed, 6 Oct 2021 13:15:10 +0200 Subject: [PATCH 038/101] Draft: Draft_Text should be aligned toworking plane --- src/Mod/Draft/draftguitools/gui_texts.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_texts.py b/src/Mod/Draft/draftguitools/gui_texts.py index ef40496ffb..74efe4dab7 100644 --- a/src/Mod/Draft/draftguitools/gui_texts.py +++ b/src/Mod/Draft/draftguitools/gui_texts.py @@ -85,6 +85,9 @@ class Text(gui_base_original.Creator): def createObject(self): """Create the actual object in the current document.""" + rot, sup, pts, fil = self.getStrings() + base = pts[1:-1] + text_list = self.text text_list = [text.replace("\"","\\\"") for text in text_list] @@ -108,9 +111,12 @@ class Text(gui_base_original.Creator): _cmd = 'Draft.make_text' _cmd += '(' _cmd += string + ', ' - _cmd += 'placement=' + DraftVecUtils.toString(self.node[0]) + _cmd += 'placement=pl' _cmd += ')' - _cmd_list = ['_text_ = ' + _cmd, + _cmd_list = ['pl = FreeCAD.Placement()', + 'pl.Rotation.Q = ' + rot, + 'pl.Base = ' + base, + '_text_ = ' + _cmd, 'Draft.autogroup(_text_)', 'FreeCAD.ActiveDocument.recompute()'] self.commit(translate("draft", "Create Text"), From 521cfcfefdec0446d7790b1d2d25ca033af15d14 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Sat, 2 Oct 2021 22:36:07 +0200 Subject: [PATCH 039/101] Sketcher: user addSelections for group selection in SketcherTools --- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 75 ++++++++++++------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index beac215516..ce3c0aaea8 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -337,6 +337,7 @@ void CmdSketcherSelectConstraints::activated(int iMsg) getSelection().clearSelection(); + std::vector constraintSubNames; // go through the selected subelements for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) { // only handle edges @@ -349,13 +350,15 @@ void CmdSketcherSelectConstraints::activated(int iMsg) it != vals.end(); ++it,++i) { if ((*it)->First == GeoId || (*it)->Second == GeoId || (*it)->Third == GeoId) { - Gui::Selection().addSelection(doc_name.c_str(), - obj_name.c_str(), - Sketcher::PropertyConstraintList::getConstraintName(i).c_str()); + constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i)); } } } } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); + } bool CmdSketcherSelectConstraints::isActive(void) @@ -533,17 +536,20 @@ void CmdSketcherSelectRedundantConstraints::activated(int iMsg) getSelection().clearSelection(); // push the constraints + std::vector constraintSubNames; + int i = 0; for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) { for(std::vector< int >::const_iterator itc= solverredundant.begin();itc != solverredundant.end(); ++itc) { if ((*itc) - 1 == i) { - Gui::Selection().addSelection(doc_name.c_str(), - obj_name.c_str(), - Sketcher::PropertyConstraintList::getConstraintName(i).c_str()); + constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i)); break; } } } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); } bool CmdSketcherSelectRedundantConstraints::isActive(void) @@ -587,17 +593,19 @@ void CmdSketcherSelectMalformedConstraints::activated(int iMsg) getSelection().clearSelection(); // push the constraints + std::vector constraintSubNames; int i = 0; for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) { for(std::vector< int >::const_iterator itc= solvermalformed.begin();itc != solvermalformed.end(); ++itc) { if ((*itc) - 1 == i) { - Gui::Selection().addSelection(doc_name.c_str(), - obj_name.c_str(), - Sketcher::PropertyConstraintList::getConstraintName(i).c_str()); + constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i)); break; } } } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); } bool CmdSketcherSelectMalformedConstraints::isActive(void) @@ -641,17 +649,19 @@ void CmdSketcherSelectPartiallyRedundantConstraints::activated(int iMsg) getSelection().clearSelection(); // push the constraints + std::vector constraintSubNames; int i = 0; for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) { for(std::vector< int >::const_iterator itc= solverpartiallyredundant.begin();itc != solverpartiallyredundant.end(); ++itc) { if ((*itc) - 1 == i) { - Gui::Selection().addSelection(doc_name.c_str(), - obj_name.c_str(), - Sketcher::PropertyConstraintList::getConstraintName(i).c_str()); + constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i)); break; } } } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); } bool CmdSketcherSelectPartiallyRedundantConstraints::isActive(void) @@ -693,17 +703,19 @@ void CmdSketcherSelectConflictingConstraints::activated(int iMsg) getSelection().clearSelection(); // push the constraints + std::vector constraintSubNames; int i = 0; for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) { for (std::vector< int >::const_iterator itc= solverconflicting.begin();itc != solverconflicting.end(); ++itc) { if ((*itc) - 1 == i) { - Gui::Selection().addSelection(doc_name.c_str(), - obj_name.c_str(), - Sketcher::PropertyConstraintList::getConstraintName(i).c_str()); + constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i)); break; } } } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); } bool CmdSketcherSelectConflictingConstraints::isActive(void) @@ -747,8 +759,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg) std::string obj_name = Obj->getNameInDocument(); std::stringstream ss; - int selected = 0; - + std::vector elementSubNames; // go through the selected subelements for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) { // only handle constraints @@ -772,9 +783,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg) ss << "Vertex" << vertex + 1; break; } - - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); - selected++; + elementSubNames.push_back(ss.str()); } if(vals[ConstrId]->Second!=Constraint::GeoUndef){ @@ -794,8 +803,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg) break; } - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); - selected++; + elementSubNames.push_back(ss.str()); } if(vals[ConstrId]->Third!=Constraint::GeoUndef){ @@ -815,17 +823,20 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg) break; } - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); - selected++; + elementSubNames.push_back(ss.str()); } } } } - if (selected == 0) { + if (elementSubNames.empty()) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No constraint selected"), QObject::tr("At least one constraint must be selected")); } + else { + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames); + } + } bool CmdSketcherSelectElementsAssociatedWithConstraints::isActive(void) @@ -866,22 +877,24 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg) auto geos = Obj->getInternalGeometry(); - auto testselectvertex = [&Obj, &ss, &doc_name, &obj_name](int geoId, PointPos pos) { + std::vector elementSubNames; + + auto testselectvertex = [&Obj, &ss, &doc_name, &obj_name, &elementSubNames](int geoId, PointPos pos) { ss.str(std::string()); int vertex = Obj->getVertexIndexGeoPos(geoId, pos); if (vertex > -1) { ss << "Vertex" << vertex + 1; - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); + elementSubNames.push_back(ss.str()); } }; - auto testselectedge = [&ss, &doc_name, &obj_name](int geoId) { + auto testselectedge = [&ss, &doc_name, &obj_name, &elementSubNames](int geoId) { ss.str(std::string()); ss << "Edge" << geoId + 1; - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); + elementSubNames.push_back(ss.str()); }; int geoid = 0; @@ -911,6 +924,10 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg) geoid++; } + if (!elementSubNames.empty()) { + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames); + } + } bool CmdSketcherSelectElementsWithDoFs::isActive(void) From e333225a123e5d4f8238effa1deb38493a40b065 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Sat, 2 Oct 2021 23:33:16 +0200 Subject: [PATCH 040/101] Sketcher: use addSelections for group selecions in TaskSketcherElements --- src/Mod/Sketcher/Gui/TaskSketcherElements.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp index 4bd186264a..f19ffbd650 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp @@ -512,6 +512,8 @@ void TaskSketcherElements::on_listWidgetElements_itemSelectionChanged(void) bool block = this->blockConnection(true); // avoid to be notified by itself Gui::Selection().clearSelection(); + std::vector elementSubNames; + for (int i=0;ilistWidgetElements->count(); i++) { ElementItem * ite=static_cast(ui->listWidgetElements->item(i)); @@ -566,7 +568,7 @@ void TaskSketcherElements::on_listWidgetElements_itemSelectionChanged(void) if (ite->isLineSelected) { ss << "Edge" << ite->ElementNbr + 1; - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); + elementSubNames.push_back(ss.str()); } if (ite->isStartingPointSelected) { @@ -574,7 +576,7 @@ void TaskSketcherElements::on_listWidgetElements_itemSelectionChanged(void) vertex= ite->StartingVertex; if (vertex!=-1) { ss << "Vertex" << vertex + 1; - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); + elementSubNames.push_back(ss.str()); } } @@ -583,7 +585,7 @@ void TaskSketcherElements::on_listWidgetElements_itemSelectionChanged(void) vertex= ite->EndVertex; if (vertex!=-1) { ss << "Vertex" << vertex + 1; - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); + elementSubNames.push_back(ss.str()); } } @@ -592,11 +594,15 @@ void TaskSketcherElements::on_listWidgetElements_itemSelectionChanged(void) vertex= ite->MidVertex; if (vertex!=-1) { ss << "Vertex" << vertex + 1; - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); + elementSubNames.push_back(ss.str()); } } } + if (!elementSubNames.empty()) { + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames); + } + this->blockConnection(block); ui->listWidgetElements->blockSignals(false); From 1bd1d42fa87ff630f54caa0346991718bc50de34 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Sun, 3 Oct 2021 16:41:47 +0200 Subject: [PATCH 041/101] Sketcher: New constraint special filter, filter selection ========================================================= It filters the constraint list to the selected constraints. It observes selection changes and reacts to new selections. Forum: https://forum.freecadweb.org/viewtopic.php?p=537028#p537028 --- src/Mod/Sketcher/Gui/ConstraintFilters.h | 1 + .../Sketcher/Gui/TaskSketcherConstrains.cpp | 61 +++++++++++++++---- src/Mod/Sketcher/Gui/TaskSketcherConstrains.h | 6 +- .../Sketcher/Gui/TaskSketcherConstrains.ui | 5 ++ 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ConstraintFilters.h b/src/Mod/Sketcher/Gui/ConstraintFilters.h index 6f86e2e3f0..4c8a292948 100644 --- a/src/Mod/Sketcher/Gui/ConstraintFilters.h +++ b/src/Mod/Sketcher/Gui/ConstraintFilters.h @@ -60,6 +60,7 @@ namespace ConstraintFilter { enum SpecialFilterValue { Multiple = 24, + Selection = 25, NumSpecialFilterValue }; diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index 26c199e421..4add6a36ec 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -453,13 +453,18 @@ void ConstraintView::contextMenuEvent (QContextMenuEvent* event) // Sync the FreeCAD selection with the selection in the ConstraintView widget if (didRelease) { Gui::Selection().clearSelection(); + std::string doc_name = static_cast(item)->sketchView->getSketchObject()->getDocument()->getName(); + std::string obj_name = static_cast(item)->sketchView->getSketchObject()->getNameInDocument(); + + std::vector constraintSubNames; for (auto&& it : items) { auto ci = static_cast(it); std::string constraint_name = Sketcher::PropertyConstraintList::getConstraintName(ci->ConstraintNbr); - std::string doc_name = ci->sketchView->getSketchObject()->getDocument()->getName(); - std::string obj_name = ci->sketchView->getSketchObject()->getNameInDocument(); - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), constraint_name.c_str()); + constraintSubNames.push_back(constraint_name.c_str()); } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); } bool isQuantity = false; @@ -719,13 +724,15 @@ TaskSketcherConstrains::~TaskSketcherConstrains() connectionConstraintsChanged.disconnect(); } -void TaskSketcherConstrains::updateMultiFilter() +void TaskSketcherConstrains::updateSelectionFilter() { - int filterindex = ui->comboBoxFilter->currentIndex(); + // Snapshot current selection + auto items = ui->listWidgetConstraints->selectedItems(); - multiFilterStatus.reset(); + selectionFilter.clear(); - multiFilterStatus.set(filterindex); + for(const auto & item : items) + selectionFilter.push_back(static_cast(item)->ConstraintNbr); } void TaskSketcherConstrains::updateList() @@ -857,8 +864,16 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg std::string temp; if (msg.Type == Gui::SelectionChanges::ClrSelection) { ui->listWidgetConstraints->blockSignals(true); - ui->listWidgetConstraints->clearSelection (); + ui->listWidgetConstraints->clearSelection(); ui->listWidgetConstraints->blockSignals(false); + + if(isFilter(ConstraintFilter::SpecialFilterValue::Selection)) { + updateSelectionFilter(); + + bool block = this->blockConnection(true); // avoid to be notified by itself + updateList(); + this->blockConnection(block); + } } else if (msg.Type == Gui::SelectionChanges::AddSelection || msg.Type == Gui::SelectionChanges::RmvSelection) { @@ -885,6 +900,10 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg break; } } + updateSelectionFilter(); + bool block = this->blockConnection(true); // avoid to be notified by itself + updateList(); + this->blockConnection(block); } } } @@ -896,8 +915,14 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg } -void TaskSketcherConstrains::on_comboBoxFilter_currentIndexChanged(int) +void TaskSketcherConstrains::on_comboBoxFilter_currentIndexChanged(int filterindex) { + selectionFilter.clear(); // reset the stored selection filter + + if(filterindex == ConstraintFilter::SpecialFilterValue::Selection) { + updateSelectionFilter(); + } + updateList(); } @@ -932,12 +957,17 @@ void TaskSketcherConstrains::on_listWidgetConstraints_itemSelectionChanged(void) bool block = this->blockConnection(true); // avoid to be notified by itself Gui::Selection().clearSelection(); + + std::vector constraintSubNames; QList items = ui->listWidgetConstraints->selectedItems(); for (QList::iterator it = items.begin(); it != items.end(); ++it) { std::string constraint_name(Sketcher::PropertyConstraintList::getConstraintName(static_cast(*it)->ConstraintNbr)); - - Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), constraint_name.c_str()); + constraintSubNames.push_back(constraint_name); } + + if(!constraintSubNames.empty()) + Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); + this->blockConnection(block); } @@ -1210,6 +1240,10 @@ bool TaskSketcherConstrains::isConstraintFiltered(QListWidgetItem * item) break; } + // Constraint Type independent, selection filter + visible = visible || (Filter == SpecialFilterValue::Selection && + std::find(selectionFilter.begin(), selectionFilter.end(), it->ConstraintNbr) != selectionFilter.end()); + return !visible; } @@ -1274,6 +1308,11 @@ void TaskSketcherConstrains::changeEvent(QEvent *e) } } +template +bool TaskSketcherConstrains::isFilter(T filterValue) { + return (ui->comboBoxFilter->currentIndex() == filterValue); +} + #include "moc_TaskSketcherConstrains.cpp" diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h index e4bbebf5bf..f273b767ab 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h @@ -92,9 +92,12 @@ private: bool isConstraintFiltered(QListWidgetItem * item); void change3DViewVisibilityToTrackFilter(); void changeFilteredVisibility(bool show, ActionTarget target = ActionTarget::All); - void updateMultiFilter(); + void updateSelectionFilter(); void updateList(); + template + bool isFilter(T filterValue); + public Q_SLOTS: void on_comboBoxFilter_currentIndexChanged(int); void on_listWidgetConstraints_itemSelectionChanged(void); @@ -123,6 +126,7 @@ private: bool inEditMode; std::unique_ptr ui; std::bitset multiFilterStatus; + std::vector selectionFilter; }; } //namespace SketcherGui diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui index 5ede5770f6..e2e4d454b6 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui @@ -165,6 +165,11 @@ Multiple Filters + + + Selection Filter + + From 6c23e2be1c5b9f619ee2ae59e3aacc4154c62f6f Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 6 Oct 2021 17:19:38 +0200 Subject: [PATCH 042/101] Mesh: implement sub-element handling --- src/Mod/Mesh/App/AppMesh.cpp | 1 + src/Mod/Mesh/App/Mesh.cpp | 51 ++++++++++++++++++++++++-------- src/Mod/Mesh/App/Mesh.h | 18 ++++++++++- src/Mod/Mesh/App/MeshPy.xml | 7 ++++- src/Mod/Mesh/App/MeshPyImp.cpp | 21 +++++++++++++ src/Mod/Mesh/App/MeshTestsApp.py | 41 +++++++++++++++++++++++++ 6 files changed, 124 insertions(+), 15 deletions(-) diff --git a/src/Mod/Mesh/App/AppMesh.cpp b/src/Mod/Mesh/App/AppMesh.cpp index 7a6d759612..e179e90de6 100644 --- a/src/Mod/Mesh/App/AppMesh.cpp +++ b/src/Mod/Mesh/App/AppMesh.cpp @@ -76,6 +76,7 @@ PyMOD_INIT_FUNC(Mesh) Mesh::PropertyMeshKernel ::init(); Mesh::MeshObject ::init(); + Mesh::MeshSegment ::init(); Mesh::Feature ::init(); Mesh::FeatureCustom ::init(); diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index bc533ecaa5..f0427d8acd 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -62,6 +62,7 @@ using namespace Mesh; float MeshObject::Epsilon = 1.0e-5f; TYPESYSTEM_SOURCE(Mesh::MeshObject, Data::ComplexGeoData) +TYPESYSTEM_SOURCE(Mesh::MeshSegment, Data::Segment) MeshObject::MeshObject() { @@ -93,7 +94,7 @@ MeshObject::~MeshObject() std::vector MeshObject::getElementTypes() const { std::vector temp; - temp.push_back("Face"); // that's the mesh itself + temp.push_back("Mesh"); temp.push_back("Segment"); return temp; @@ -102,31 +103,47 @@ std::vector MeshObject::getElementTypes() const unsigned long MeshObject::countSubElements(const char* Type) const { std::string element(Type); - if (element == "Face") + if (element == "Mesh") return 1; else if (element == "Segment") return countSegments(); return 0; } -Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long /*n*/) const +Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long n) const { - //TODO std::string element(Type); - if (element == "Face") - return nullptr; - else if (element == "Segment") - return nullptr; + if (element == "Mesh" && n == 0) { + MeshSegment* segm = new MeshSegment(); + segm->mesh = new MeshObject(*this); + return segm; + } + else if (element == "Segment" && n < countSegments()) { + MeshSegment* segm = new MeshSegment(); + segm->mesh = new MeshObject(*this); + const Segment& faces = getSegment(n); + segm->segment.reset(new Segment(static_cast(segm->mesh), faces.getIndices(), false)); + return segm; + } + return nullptr; } -void MeshObject::getFacesFromSubelement(const Data::Segment* /*segm*/, - std::vector &Points, - std::vector &/*PointNormals*/, +void MeshObject::getFacesFromSubelement(const Data::Segment* element, + std::vector &points, + std::vector &/*pointNormals*/, std::vector &faces) const { - //TODO - this->getFaces(Points, faces, 0.0f); + if (element && element->getTypeId() == MeshSegment::getClassTypeId()) { + const MeshSegment* segm = static_cast(element); + if (segm->segment) { + Base::Reference submesh(segm->mesh->meshFromSegment(segm->segment->getIndices())); + submesh->getFaces(points, faces, 0.0f); + } + else { + segm->mesh->getFaces(points, faces, 0.0f); + } + } } void MeshObject::transformGeometry(const Base::Matrix4D &rclMat) @@ -161,6 +178,14 @@ Base::BoundBox3d MeshObject::getBoundBox()const return Bnd2; } +bool MeshObject::getCenterOfGravity(Base::Vector3d& center) const +{ + MeshCore::MeshAlgorithm alg(_kernel); + Base::Vector3f pnt = alg.GetGravityPoint(); + center = transformToOutside(pnt); + return true; +} + void MeshObject::copySegments(const MeshObject& mesh) { // After copying the segments the mesh pointers must be adjusted diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index 7b307b2e78..f6bfe262e3 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -60,6 +60,21 @@ class AbstractPolygonTriangulator; namespace Mesh { + +class MeshObject; +class MeshExport MeshSegment : public Data::Segment +{ + TYPESYSTEM_HEADER(); + +public: + virtual std::string getName() const { + return "MeshSegment"; + } + + Base::Reference mesh; + std::unique_ptr segment; +}; + /** * The MeshObject class provides an interface for the underlying MeshKernel class and * most of its algorithm on it. @@ -142,7 +157,8 @@ public: const MeshCore::MeshKernel& getKernel() const { return _kernel; } - virtual Base::BoundBox3d getBoundBox()const; + virtual Base::BoundBox3d getBoundBox() const; + virtual bool getCenterOfGravity(Base::Vector3d& center) const; /** @name I/O */ //@{ diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index b0f2992ad9..9cfacb9a84 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -184,7 +184,12 @@ lines = mesh.section(mesh2, [ConnectLines=True, MinDist=0.0001]) - + + + Add a list of facet indices that describes a segment to the mesh + + + Get the number of segments which may also be 0 diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 7f368488b7..30b1277b3c 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -845,6 +845,27 @@ PyObject* MeshPy::getPointNormals(PyObject *args) } PY_CATCH; } +PyObject* MeshPy::addSegment(PyObject *args) +{ + PyObject* pylist; + if (!PyArg_ParseTuple(args, "O", &pylist)) + return nullptr; + + Py::Sequence list(pylist); + std::vector segment; + unsigned long numFacets = getMeshObjectPtr()->countFacets(); + segment.reserve(list.size()); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + Py::Long value(*it); + Mesh::FacetIndex index = static_cast(value); + if (index < numFacets) + segment.push_back(index); + } + + getMeshObjectPtr()->addSegment(segment); + Py_Return; +} + PyObject* MeshPy::countSegments(PyObject *args) { if (!PyArg_ParseTuple(args, "")) diff --git a/src/Mod/Mesh/App/MeshTestsApp.py b/src/Mod/Mesh/App/MeshTestsApp.py index 9091e4d74e..cdad28c8e1 100644 --- a/src/Mod/Mesh/App/MeshTestsApp.py +++ b/src/Mod/Mesh/App/MeshTestsApp.py @@ -5,6 +5,7 @@ # LGPL import FreeCAD, os, sys, unittest, Mesh +from FreeCAD import Base import time, tempfile, math # http://python-kurs.eu/threads.php try: @@ -363,3 +364,43 @@ class NastranReader(unittest.TestCase): def tearDown(self): pass + +class MeshSubElement(unittest.TestCase): + def setUp(self): + self.mesh = Mesh.createBox(1.0, 1.0, 1.0) + + def testCenterOfGravity(self): + c = self.mesh.CenterOfGravity + self.assertEqual(c, Base.Vector(0.0, 0.0, 0.0)) + + def testSubElements(self): + types = self.mesh.getElementTypes() + self.assertIn("Mesh", types) + self.assertIn("Segment", types) + + def testCountSubElements(self): + self.assertEqual(self.mesh.countSubElements("Mesh"), 1) + self.assertEqual(self.mesh.countSubElements("Segment"), 0) + + def testFacesFromSubElement(self): + element = self.mesh.getFacesFromSubelement("Mesh", 0) + self.assertIsInstance(element, tuple) + self.assertEqual(len(element), 2) + self.assertEqual(len(element[0]), 8) + self.assertEqual(len(element[1]), 12) + + def testSegmentSubElement(self): + self.mesh.addSegment([0, 2, 4, 6, 8]) + self.assertEqual(self.mesh.countSegments(), 1) + self.assertEqual(self.mesh.countSubElements("Segment"), 1) + element = self.mesh.getFacesFromSubelement("Segment", 0) + self.assertIsInstance(element, tuple) + self.assertEqual(len(element), 2) + self.assertEqual(len(element[0]), 7) + self.assertEqual(len(element[1]), 5) + segment = self.mesh.meshFromSegment(self.mesh.getSegment(0)) + self.assertEqual(segment.CountPoints, 7) + self.assertEqual(segment.CountFacets, 5) + + def tearDown(self): + pass From eb742200c47c6b49b9bcd8d59f4c308f797bf9ad Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:46:25 +0200 Subject: [PATCH 043/101] Arch: InitGui draft_line_commands not used --- src/Mod/Arch/InitGui.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 99df49632b..ca778b1cee 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -154,7 +154,6 @@ class ArchWorkbench(FreeCADGui.Workbench): self.draft_modification_commands = it.get_draft_modification_commands() self.draft_utility_commands = it.get_draft_utility_commands_menu() self.draft_context_commands = it.get_draft_context_commands() - self.draft_line_commands = it.get_draft_line_commands() # Set up toolbars it.init_toolbar(self, From 8763810d81a77d348c7e6a33c57f3516d49da58e Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:54:30 +0200 Subject: [PATCH 044/101] Draft housekeeping: gui_rectangles.py should use make_rectangle --- src/Mod/Draft/draftguitools/gui_rectangles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftguitools/gui_rectangles.py b/src/Mod/Draft/draftguitools/gui_rectangles.py index 9831700112..3d9776fb1a 100644 --- a/src/Mod/Draft/draftguitools/gui_rectangles.py +++ b/src/Mod/Draft/draftguitools/gui_rectangles.py @@ -125,7 +125,7 @@ class Rectangle(gui_base_original.Creator): self.commit(translate("draft", "Create Plane"), _cmd_list) else: - _cmd = 'Draft.makeRectangle' + _cmd = 'Draft.make_rectangle' _cmd += '(' _cmd += 'length=' + str(length) + ', ' _cmd += 'height=' + str(height) + ', ' From 7b45d63bf208a281533f62b1f82ea1ec9911b518 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 6 Oct 2021 18:09:53 +0200 Subject: [PATCH 045/101] App: use consistent spelling of SubElement --- src/App/ComplexGeoData.cpp | 4 ++-- src/App/ComplexGeoData.h | 4 ++-- src/App/ComplexGeoDataPy.xml | 4 ++-- src/App/ComplexGeoDataPyImp.cpp | 8 ++++---- src/Gui/CommandView.cpp | 2 +- src/Mod/Mesh/App/Mesh.cpp | 2 +- src/Mod/Mesh/App/Mesh.h | 2 +- src/Mod/Mesh/App/MeshTestsApp.py | 4 ++-- src/Mod/Part/App/TopoShape.cpp | 4 ++-- src/Mod/Part/App/TopoShape.h | 4 ++-- src/Mod/Raytracing/App/PovTools.cpp | 2 +- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index 658fc67110..da6890b96b 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -97,7 +97,7 @@ Base::Placement ComplexGeoData::getPlacement() const Base::Rotation(mat)); } -void ComplexGeoData::getLinesFromSubelement(const Segment*, +void ComplexGeoData::getLinesFromSubElement(const Segment*, std::vector &Points, std::vector &lines) const { @@ -105,7 +105,7 @@ void ComplexGeoData::getLinesFromSubelement(const Segment*, (void)lines; } -void ComplexGeoData::getFacesFromSubelement(const Segment*, +void ComplexGeoData::getFacesFromSubElement(const Segment*, std::vector &Points, std::vector &PointNormals, std::vector &faces) const diff --git a/src/App/ComplexGeoData.h b/src/App/ComplexGeoData.h index 6244096900..06bbf206bd 100644 --- a/src/App/ComplexGeoData.h +++ b/src/App/ComplexGeoData.h @@ -85,12 +85,12 @@ public: /// get subelement by combined name virtual Segment* getSubElementByName(const char* Name) const; /** Get lines from segment */ - virtual void getLinesFromSubelement( + virtual void getLinesFromSubElement( const Segment*, std::vector &Points, std::vector &lines) const; /** Get faces from segment */ - virtual void getFacesFromSubelement( + virtual void getFacesFromSubElement( const Segment*, std::vector &Points, std::vector &PointNormals, diff --git a/src/App/ComplexGeoDataPy.xml b/src/App/ComplexGeoDataPy.xml index c38e89532f..2202ccf8d8 100644 --- a/src/App/ComplexGeoDataPy.xml +++ b/src/App/ComplexGeoDataPy.xml @@ -24,12 +24,12 @@ Return the number of elements of a type - + Return vertexes and faces from a sub-element - + Return vertexes and lines from a sub-element diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index a493df7187..867d3969c1 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -75,7 +75,7 @@ PyObject* ComplexGeoDataPy::countSubElements(PyObject *args) } } -PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) +PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject *args) { char *type; unsigned long index; @@ -87,7 +87,7 @@ PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) std::vector facets; try { std::unique_ptr segm(getComplexGeoDataPtr()->getSubElement(type, index)); - getComplexGeoDataPtr()->getFacesFromSubelement(segm.get(), points, normals, facets); + getComplexGeoDataPtr()->getFacesFromSubElement(segm.get(), points, normals, facets); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); @@ -113,7 +113,7 @@ PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) return Py::new_reference_to(tuple); } -PyObject* ComplexGeoDataPy::getLinesFromSubelement(PyObject *args) +PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject *args) { char *type; int index; @@ -124,7 +124,7 @@ PyObject* ComplexGeoDataPy::getLinesFromSubelement(PyObject *args) std::vector lines; try { std::unique_ptr segm(getComplexGeoDataPtr()->getSubElement(type, index)); - getComplexGeoDataPtr()->getLinesFromSubelement(segm.get(), points, lines); + getComplexGeoDataPtr()->getLinesFromSubElement(segm.get(), points, lines); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index e3a63ef978..8b725210fb 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -2824,7 +2824,7 @@ static std::vector getBoxSelection( continue; std::vector points; std::vector lines; - data->getLinesFromSubelement(segment.get(),points,lines); + data->getLinesFromSubElement(segment.get(),points,lines); if(lines.empty()) { if(points.empty()) continue; diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index f0427d8acd..e045a221cc 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -129,7 +129,7 @@ Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long n) cons return nullptr; } -void MeshObject::getFacesFromSubelement(const Data::Segment* element, +void MeshObject::getFacesFromSubElement(const Data::Segment* element, std::vector &points, std::vector &/*pointNormals*/, std::vector &faces) const diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index f6bfe262e3..b2fa4c1fda 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -112,7 +112,7 @@ public: /// get the subelement by type and number virtual Data::Segment* getSubElement(const char* Type, unsigned long) const; /** Get faces from segment */ - virtual void getFacesFromSubelement( + virtual void getFacesFromSubElement( const Data::Segment*, std::vector &Points, std::vector &PointNormals, diff --git a/src/Mod/Mesh/App/MeshTestsApp.py b/src/Mod/Mesh/App/MeshTestsApp.py index cdad28c8e1..29093823c8 100644 --- a/src/Mod/Mesh/App/MeshTestsApp.py +++ b/src/Mod/Mesh/App/MeshTestsApp.py @@ -383,7 +383,7 @@ class MeshSubElement(unittest.TestCase): self.assertEqual(self.mesh.countSubElements("Segment"), 0) def testFacesFromSubElement(self): - element = self.mesh.getFacesFromSubelement("Mesh", 0) + element = self.mesh.getFacesFromSubElement("Mesh", 0) self.assertIsInstance(element, tuple) self.assertEqual(len(element), 2) self.assertEqual(len(element[0]), 8) @@ -393,7 +393,7 @@ class MeshSubElement(unittest.TestCase): self.mesh.addSegment([0, 2, 4, 6, 8]) self.assertEqual(self.mesh.countSegments(), 1) self.assertEqual(self.mesh.countSubElements("Segment"), 1) - element = self.mesh.getFacesFromSubelement("Segment", 0) + element = self.mesh.getFacesFromSubElement("Segment", 0) self.assertIsInstance(element, tuple) self.assertEqual(len(element), 2) self.assertEqual(len(element[0]), 7) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 60183e64ca..614661594d 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -3845,7 +3845,7 @@ void TopoShape::getPoints(std::vector &Points, Normals.clear(); } -void TopoShape::getLinesFromSubelement(const Data::Segment* element, +void TopoShape::getLinesFromSubElement(const Data::Segment* element, std::vector &vertices, std::vector &lines) const { @@ -3940,7 +3940,7 @@ void TopoShape::getLinesFromSubelement(const Data::Segment* element, } } -void TopoShape::getFacesFromSubelement(const Data::Segment* element, +void TopoShape::getFacesFromSubElement(const Data::Segment* element, std::vector &points, std::vector &pointNormals, std::vector &faces) const diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index f720dae87d..9d50ec0da6 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -135,12 +135,12 @@ public: /// get the subelement by type and number virtual Data::Segment* getSubElement(const char* Type, unsigned long) const; /** Get lines from segment */ - virtual void getLinesFromSubelement( + virtual void getLinesFromSubElement( const Data::Segment*, std::vector &Points, std::vector &lines) const; /** Get faces from segment */ - virtual void getFacesFromSubelement( + virtual void getFacesFromSubElement( const Data::Segment*, std::vector &Points, std::vector &PointNormals, diff --git a/src/Mod/Raytracing/App/PovTools.cpp b/src/Mod/Raytracing/App/PovTools.cpp index 1402a68530..e2d7c1f4d7 100644 --- a/src/Mod/Raytracing/App/PovTools.cpp +++ b/src/Mod/Raytracing/App/PovTools.cpp @@ -158,7 +158,7 @@ void PovTools::writeData(const char *FileName, const char *PartName, std::vector normals; std::vector facets; Data::Segment* segm = data->getSubElement("Face", i); - data->getFacesFromSubelement(segm, points, normals, facets); + data->getFacesFromSubElement(segm, points, normals, facets); delete segm; // writing per face header From 5593b8499bd87d28ad53c09ef9d795b88dbb7409 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 6 Oct 2021 19:44:53 +0200 Subject: [PATCH 046/101] Part: add function Geometry.toShell --- src/Mod/Part/App/GeometrySurfacePy.xml | 5 +++ src/Mod/Part/App/GeometrySurfacePyImp.cpp | 48 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/Mod/Part/App/GeometrySurfacePy.xml b/src/Mod/Part/App/GeometrySurfacePy.xml index 339ad0eef2..ecf36059f7 100644 --- a/src/Mod/Part/App/GeometrySurfacePy.xml +++ b/src/Mod/Part/App/GeometrySurfacePy.xml @@ -22,6 +22,11 @@ Return the shape for the geometry. + + + Make a shell of the surface. + + Returns the point of given parameter diff --git a/src/Mod/Part/App/GeometrySurfacePyImp.cpp b/src/Mod/Part/App/GeometrySurfacePyImp.cpp index 67bfe22da1..a7dddde693 100644 --- a/src/Mod/Part/App/GeometrySurfacePyImp.cpp +++ b/src/Mod/Part/App/GeometrySurfacePyImp.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ # include +# include # include # include # include @@ -74,6 +75,7 @@ #include #include #include +#include namespace Part { const Py::Object makeTrimmedCurvePy(const Handle(Geom_Curve)& c, double f, double l) @@ -153,6 +155,52 @@ PyObject* GeometrySurfacePy::toShape(PyObject *args) return 0; } +PyObject* GeometrySurfacePy::toShell(PyObject *args, PyObject* kwds) +{ + PyObject* bound = nullptr; + PyObject* segm = nullptr; + static char *kwlist[] = {"Bounds", "Segment", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!O!", kwlist, + &PyTuple_Type, &bound, &PyBool_Type, &segm)) + return nullptr; + + Handle(Geom_Geometry) g = getGeometryPtr()->handle(); + Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(g); + try { + if (!s.IsNull()) { + if (segm) { + Standard_Boolean segment = PyObject_IsTrue(segm) ? Standard_True : Standard_False; + BRepBuilderAPI_MakeShell mkBuilder(s, segment); + TopoDS_Shape sh = mkBuilder.Shape(); + return new TopoShapeShellPy(new TopoShape(sh)); + } + else { + double u1,u2,v1,v2; + s->Bounds(u1,u2,v1,v2); + + if (bound) { + Py::Tuple tuple(bound); + u1 = double(Py::Float(tuple[0])); + u2 = double(Py::Float(tuple[1])); + v1 = double(Py::Float(tuple[2])); + v2 = double(Py::Float(tuple[3])); + } + + BRepBuilderAPI_MakeShell mkBuilder(s, u1, u2, v1, v2); + TopoDS_Shape sh = mkBuilder.Shape(); + return new TopoShapeShellPy(new TopoShape(sh)); + } + } + } + catch (Standard_Failure& e) { + PyErr_SetString(PartExceptionOCCError, e.GetMessageString()); + return nullptr; + } + + PyErr_SetString(PartExceptionOCCError, "Geometry is not a surface"); + return nullptr; +} + PyObject* GeometrySurfacePy::getD0(PyObject *args) { Handle(Geom_Geometry) g = getGeometryPtr()->handle(); From df23ab444134e2ea9e0537f7da1db74697b28850 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 6 Oct 2021 19:46:57 +0200 Subject: [PATCH 047/101] Sketcher: [skip ci] fix -Wunused-lambda-capture --- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index ce3c0aaea8..d0db2dfb97 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -879,7 +879,7 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg) std::vector elementSubNames; - auto testselectvertex = [&Obj, &ss, &doc_name, &obj_name, &elementSubNames](int geoId, PointPos pos) { + auto testselectvertex = [&Obj, &ss, &elementSubNames](int geoId, PointPos pos) { ss.str(std::string()); int vertex = Obj->getVertexIndexGeoPos(geoId, pos); @@ -890,7 +890,7 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg) } }; - auto testselectedge = [&ss, &doc_name, &obj_name, &elementSubNames](int geoId) { + auto testselectedge = [&ss, &elementSubNames](int geoId) { ss.str(std::string()); ss << "Edge" << geoId + 1; From 5235af1d47fb88aa334f66f7630f5b948b70bb14 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 6 Oct 2021 21:58:37 +0200 Subject: [PATCH 048/101] Mesh: [skip ci] add unit test for corrupted facets --- src/Mod/Mesh/App/MeshTestsApp.py | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/Mod/Mesh/App/MeshTestsApp.py b/src/Mod/Mesh/App/MeshTestsApp.py index 29093823c8..a43f982e79 100644 --- a/src/Mod/Mesh/App/MeshTestsApp.py +++ b/src/Mod/Mesh/App/MeshTestsApp.py @@ -47,6 +47,43 @@ class MeshTopoTestCases(unittest.TestCase): planarMeshObject = Mesh.Mesh(self.planarMesh) planarMeshObject.collapseFacets(range(18)) + def testCorruptedFacet(self): + v = FreeCAD.Vector + mesh = Mesh.Mesh() + mesh.addFacet( + v(1.0e1, -1.0e1, 1.0e1), + v(1.0e1, +1.0e1, 1.0e1), + v(0.0e0, 0.0e0, 1.0e1)) + + mesh.addFacet( + v(-1.0e1, -1.0e1, 1.0e1), + v(-1.0e1, +1.0e1, 1.0e1), + v(0e0, 0.0e0, 1.0e1)) + + mesh.addFacet( + v(+1.0e1, +1.0e1, 1.0e1), + v(-1.0e1, +1.0e1, 1.0e1), + v(.0e0, 0.0e0, 1.0e1)) + + mesh.addFacet( + v(+1.0e1, -1.0e1, 1.0e1), + v(-1.0e1, -1.0e1, 1.0e1), + v(.0e0, 0.0e0, 1.0e1)) + + mesh.addFacet( + v(-1.0e1, +1.0e1, 1.0e1), + v(+1.0e1, +1.0e1, 1.0e1), + v(+1.0e1, +1.0e1, 1.0e1)) + + mesh.addFacet( + v(+1.0e1, +1.0e1, 1.0e1), + v(+1.0e1, 00.0e1, 1.0e1), + v(+1.0e1, -1.0e1, 1.0e1)) + + self.assertEqual(mesh.CountFacets, 6) + mesh.fixIndices() + self.assertEqual(mesh.CountFacets, 5) + class MeshSplitTestCases(unittest.TestCase): def setUp(self): From f1d1778a73fb939263c3265e5591d19c6043955e Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 30 Sep 2021 16:18:34 +0200 Subject: [PATCH 049/101] Mesh: fix WildMagic4 build on Darwin AArch64 (Apple M1) A previous fix from 2012 excluded the x86_64 platfrom from using 32-bit Carbon APIs. - https://tracker.freecadweb.org/view.php?id=656 (WildMagic4 doesn't build on 64-bit Mac OS) Apply the same fix for AArch64 to ensure that the Mesh module can be built on Apple M1. --- src/Mod/Mesh/App/WildMagic4/Wm4System.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4System.cpp b/src/Mod/Mesh/App/WildMagic4/Wm4System.cpp index c68f78c959..0f5fd76c5f 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4System.cpp +++ b/src/Mod/Mesh/App/WildMagic4/Wm4System.cpp @@ -569,7 +569,7 @@ int System::Write8be (FILE* pkFile, int iQuantity, const void* pvData) const char* System::GetPath (const char* acDirectory, const char* acFilename) { // #0000656: WildMagic4 doesn't build on 64-bit Mac OS -#if defined(__APPLE__) && !defined(__x86_64__) +#if defined(__APPLE__) && !defined(__aarch64__) && !defined(__x86_64__) // An application-relative path is needed for the applications to be able // to find the input data sets. Unfortunately, there is no exact way to // predict which directory the application is run from, since this depends From bb108cff95dc13d73ce80c932e5ef04dd92e0d0c Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 6 Oct 2021 18:11:25 -0400 Subject: [PATCH 050/101] Fix user facing typos [skip ci] Typos in Draft and OpenSCAD code. --- src/Mod/Draft/draftutils/init_tools.py | 2 +- src/Mod/OpenSCAD/Resources/ui/openscadprefs-base.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index 520e54a72c..5851a91315 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -208,7 +208,7 @@ def init_menu(workbench, menu_list, cmd_list): The workbench. The commands from cmd_list must be available. menu_list: list of strings - The main and optional submenu(s). The commands, and additonal + The main and optional submenu(s). The commands, and additional submenus (if any), are added to the last (sub)menu in the list. cmd_list: list of strings or list of strings and tuples diff --git a/src/Mod/OpenSCAD/Resources/ui/openscadprefs-base.ui b/src/Mod/OpenSCAD/Resources/ui/openscadprefs-base.ui index 93912ea157..9c3f770d31 100644 --- a/src/Mod/OpenSCAD/Resources/ui/openscadprefs-base.ui +++ b/src/Mod/OpenSCAD/Resources/ui/openscadprefs-base.ui @@ -237,7 +237,7 @@ - The path to the directory for transfering files to and from OpenSCAD + The path to the directory for transferring files to and from OpenSCAD transferdirectory From 1bac25de44a3b023e0122ec498656ffd4dedd4aa Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 6 Oct 2021 18:15:37 -0400 Subject: [PATCH 051/101] Tools: fix updatecrowdin.py variable typo [skip ci] --- src/Tools/updatecrowdin.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Tools/updatecrowdin.py b/src/Tools/updatecrowdin.py index 30d69deaaf..5a06c0d725 100755 --- a/src/Tools/updatecrowdin.py +++ b/src/Tools/updatecrowdin.py @@ -115,7 +115,7 @@ locations = [["AddonManager","../Mod/AddonManager/Resources/translations","../Mo ["TechDraw","../Mod/TechDraw/Gui/Resources/translations","../Mod/TechDraw/Gui/Resources/TechDraw.qrc"], ] -TRESHOLD = 25 # how many % must be translated for the translation to be included in FreeCAD +THRESHOLD = 25 # how many % must be translated for the translation to be included in FreeCAD class CrowdinUpdater: @@ -406,7 +406,7 @@ if __name__ == "__main__": if command == "status": status = updater.status() status = sorted(status,key=lambda item: item['translationProgress'],reverse=True) - print(len([item for item in status if item['translationProgress'] > TRESHOLD])," languages with status > "+str(TRESHOLD)+"%:") + print(len([item for item in status if item['translationProgress'] > THRESHOLD])," languages with status > "+str(THRESHOLD)+"%:") print(" ") sep = False prefix = "" @@ -416,7 +416,7 @@ if __name__ == "__main__": suffix = "\033[0m" for item in status: if item['translationProgress'] > 0: - if (item['translationProgress'] < TRESHOLD) and (not sep): + if (item['translationProgress'] < THRESHOLD) and (not sep): print(" ") print("Other languages:") print(" ") @@ -464,7 +464,7 @@ if __name__ == "__main__": print("retrieving list of languages...") status = updater.status() status = sorted(status,key=lambda item: item['translationProgress'],reverse=True) - languages = [item['languageId'] for item in status if item['translationProgress'] > TRESHOLD] + languages = [item['languageId'] for item in status if item['translationProgress'] > THRESHOLD] applyTranslations(languages) print("Updating Translator.cpp...") for ln in languages: @@ -474,7 +474,7 @@ if __name__ == "__main__": print("retrieving list of languages...") status = updater.status() status = sorted(status,key=lambda item: item['translationProgress'],reverse=True) - languages = [item['languageId'] for item in status if item['translationProgress'] > TRESHOLD] + languages = [item['languageId'] for item in status if item['translationProgress'] > THRESHOLD] print("Updating Translator.cpp...") for ln in languages: updateTranslatorCpp(ln) From 5bb00636d53732e2026d2096889c86f18ac590cb Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 7 Oct 2021 10:19:49 +0200 Subject: [PATCH 052/101] Part: [skip ci] fix build failure when using PCH --- src/Mod/Part/App/OpenCascadeAll.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Part/App/OpenCascadeAll.h b/src/Mod/Part/App/OpenCascadeAll.h index 0bdd759f57..c4967fb54f 100644 --- a/src/Mod/Part/App/OpenCascadeAll.h +++ b/src/Mod/Part/App/OpenCascadeAll.h @@ -216,6 +216,7 @@ #include #include #include +#include #include #include #include From 77b198048a63f1e9ca15eef64c8042d599a14cf3 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 7 Oct 2021 11:10:12 +0200 Subject: [PATCH 053/101] SMESH: [skip ci] do not undefine the guard of a header file --- src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp b/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp index 24dc2d00a6..8e78712f4a 100644 --- a/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp +++ b/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp @@ -64,7 +64,7 @@ #include -#undef _Precision_HeaderFile +//#undef _Precision_HeaderFile #include #include #include From c19e1398f260fcd519cb75da4350108cecee0fdb Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 7 Oct 2021 14:23:46 +0800 Subject: [PATCH 054/101] Import: fix STEP color problem caused by OCC 7.5 Fixes #0004744 --- src/Mod/Import/App/ExportOCAF.cpp | 14 +++++++--- src/Mod/Import/App/ImportOCAF2.cpp | 43 ++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/Mod/Import/App/ExportOCAF.cpp b/src/Mod/Import/App/ExportOCAF.cpp index 2baa95e2f4..bce4ff03b8 100644 --- a/src/Mod/Import/App/ExportOCAF.cpp +++ b/src/Mod/Import/App/ExportOCAF.cpp @@ -95,6 +95,12 @@ #include #include +#if OCC_VERSION_HEX >= 0x070500 +// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware +# define OCC_COLOR_SPACE Quantity_TOC_sRGB +#else +# define OCC_COLOR_SPACE Quantity_TOC_RGB +#endif using namespace Import; @@ -321,7 +327,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } @@ -334,7 +340,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); aColorTool->SetColor(shapeLabel, col, XCAFDoc_ColorGen); } @@ -437,7 +443,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } @@ -451,7 +457,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); aColorTool->SetColor(label, col, XCAFDoc_ColorGen); } } diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index 4de3b10adb..d3684e747e 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -71,12 +71,31 @@ #include #include +#if OCC_VERSION_HEX >= 0x070500 +// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware +# define OCC_COLOR_SPACE Quantity_TOC_sRGB +#else +# define OCC_COLOR_SPACE Quantity_TOC_RGB +#endif + FC_LOG_LEVEL_INIT("Import",true,true) using namespace Import; ///////////////////////////////////////////////////////////////////// +static inline App::Color convertColor(const Quantity_Color &c) +{ + Standard_Real r, g, b; + c.Values(r, g, b, OCC_COLOR_SPACE); + return App::Color(static_cast(r), static_cast(g), static_cast(b)); +} + +static inline Quantity_Color convertColor(const App::Color &c) +{ + return Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE); +} + static std::string labelName(TDF_Label label) { std::string txt; Handle(TDataStd_Name) name; @@ -229,12 +248,11 @@ void ImportOCAF2::setObjectName(Info &info, TDF_Label label) { } } - bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bool noDefault) { bool ret = false; Quantity_Color aColor; if(aColorTool->GetColor(shape, XCAFDoc_ColorSurf, aColor)) { - App::Color c(aColor.Red(),aColor.Green(),aColor.Blue()); + App::Color c = convertColor(aColor); if(!check || info.faceColor!=c) { info.faceColor = c; info.hasFaceColor = true; @@ -242,7 +260,7 @@ bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bo } } if(!noDefault && !info.hasFaceColor && aColorTool->GetColor(shape, XCAFDoc_ColorGen, aColor)) { - App::Color c(aColor.Red(),aColor.Green(),aColor.Blue()); + App::Color c = convertColor(aColor); if(!check || info.faceColor!=c) { info.faceColor = c; info.hasFaceColor = true; @@ -250,7 +268,7 @@ bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bo } } if(aColorTool->GetColor(shape, XCAFDoc_ColorCurv, aColor)) { - App::Color c(aColor.Red(),aColor.Green(),aColor.Blue()); + App::Color c = convertColor(aColor); // Some STEP include a curve color with the same value of the face // color. And this will look weird in FC. So for shape with face // we'll ignore the curve color, if it is the same as the face color. @@ -369,11 +387,11 @@ bool ImportOCAF2::createObject(App::Document *doc, TDF_Label label, if(aColorTool->GetColor(l, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(l, XCAFDoc_ColorGen, aColor)) { - faceColor = App::Color(aColor.Red(),aColor.Green(),aColor.Blue()); + faceColor = convertColor(aColor); foundFaceColor = true; } if(aColorTool->GetColor(l, XCAFDoc_ColorCurv, aColor)) { - edgeColor = App::Color(aColor.Red(),aColor.Green(),aColor.Blue()); + edgeColor = convertColor(aColor); foundEdgeColor = true; if(j==0 && foundFaceColor && faceColors.size() && edgeColor==faceColor) { // Do not set edge the same color as face @@ -652,7 +670,7 @@ void ImportOCAF2::getSHUOColors(TDF_Label label, if(aColorTool->GetColor(slabel, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(slabel, XCAFDoc_ColorGen, aColor)) { - colors.emplace(subname,App::Color(aColor.Red(),aColor.Green(),aColor.Blue())); + colors.emplace(subname,convertColor(aColor)); } } } @@ -784,10 +802,7 @@ bool ImportOCAF2::createAssembly(App::Document *_doc, childInfo.plas.emplace_back(Part::TopoShape::convert(childShape.Location().Transformation())); Quantity_Color aColor; if (aColorTool->GetColor(childShape, XCAFDoc_ColorSurf, aColor)) { - auto &color = childInfo.colors[childInfo.plas.size()-1]; - color.r = (float)aColor.Red(); - color.g = (float)aColor.Green(); - color.b = (float)aColor.Blue(); + childInfo.colors[childInfo.plas.size()-1] = convertColor(aColor); } } assert(visibilities.size() == children.size()); @@ -1036,7 +1051,7 @@ void ExportOCAF2::setupObject(TDF_Label label, App::DocumentObject *obj, continue; } const App::Color& c = vv.second; - Quantity_Color color(c.r,c.g,c.b,Quantity_TOC_RGB); + Quantity_Color color = convertColor(c); auto colorType = vv.first[0]=='F'?XCAFDoc_ColorSurf:XCAFDoc_ColorCurv; if(vv.first=="Face" || vv.first=="Edge") { aColorTool->SetColor(nodeLabel, color, colorType); @@ -1277,7 +1292,7 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, // Work around OCCT bug. If no color setting here, it will crash. // The culprit is at STEPCAFControl_Writer::1093 as shown below // - // surfColor = Styles.EncodeColor(Quantity_Color(1,1,1,Quantity_TOC_RGB),DPDCs,ColRGBs); + // surfColor = Styles.EncodeColor(Quantity_Color(1,1,1,OCC_COLOR_SPACE),DPDCs,ColRGBs); // PSA = Styles.MakeColorPSA ( item, surfColor, curvColor, isComponent ); // if ( isComponent ) // setDefaultInstanceColor( override, PSA); @@ -1293,7 +1308,7 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, !aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorCurv,col)) { auto &c = defaultColor; - aColorTool->SetColor(childLabel, Quantity_Color(c.r,c.g,c.b,Quantity_TOC_RGB), XCAFDoc_ColorGen); + aColorTool->SetColor(childLabel, convertColor(c), XCAFDoc_ColorGen); FC_WARN(labelName(childLabel) << " set default color"); } aColorTool->SetVisibility(childLabel,Standard_False); From c3e3ff3c8b35bc8763bc460f4683cddc167dbb9f Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 7 Oct 2021 15:46:14 +0800 Subject: [PATCH 055/101] Part: set transparency in ViewProviderExt::DiffuseColor For single color shape --- src/Mod/Part/Gui/ViewProviderExt.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index ba197f1811..c43bb64fad 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -443,7 +443,9 @@ void ViewProviderPartExt::onChanged(const App::Property* prop) else if (prop == &ShapeMaterial || prop == &ShapeColor) { pcFaceBind->value = SoMaterialBinding::OVERALL; ViewProviderGeometryObject::onChanged(prop); - DiffuseColor.setValue(ShapeColor.getValue()); + App::Color c = ShapeColor.getValue(); + c.a = Transparency.getValue()/100.0f; + DiffuseColor.setValue(c); } else if (prop == &Transparency) { const App::Material& Mat = ShapeMaterial.getValue(); @@ -795,6 +797,7 @@ std::map ViewProviderPartExt::getElementColors(const cha } if(size && singleColor) { color = DiffuseColor[0]; + color.a = Transparency.getValue()/100.0f; ret.clear(); } ret["Face"] = color; From b9a76cc8e4e3c89863693ddee3fe1322d21c5433 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 7 Oct 2021 15:47:01 +0800 Subject: [PATCH 056/101] Import: support transparency for STEP import and export --- src/Mod/Import/App/ImportOCAF2.cpp | 35 +++++++++++++++------------ src/Mod/Import/Gui/AppImportGuiPy.cpp | 5 ++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index d3684e747e..b68f82c0f5 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -41,7 +41,7 @@ # include # include # include -# include +# include # include # include # include @@ -84,16 +84,19 @@ using namespace Import; ///////////////////////////////////////////////////////////////////// -static inline App::Color convertColor(const Quantity_Color &c) +static inline App::Color convertColor(const Quantity_ColorRGBA &c) { Standard_Real r, g, b; - c.Values(r, g, b, OCC_COLOR_SPACE); - return App::Color(static_cast(r), static_cast(g), static_cast(b)); + c.GetRGB().Values(r, g, b, OCC_COLOR_SPACE); + return App::Color(static_cast(r), + static_cast(g), + static_cast(b), + static_cast(c.Alpha())); } -static inline Quantity_Color convertColor(const App::Color &c) +static inline Quantity_ColorRGBA convertColor(const App::Color &c) { - return Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE); + return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), c.a); } static std::string labelName(TDF_Label label) { @@ -135,13 +138,13 @@ static void printLabel(TDF_Label label, Handle(XCAFDoc_ShapeTool) aShapeTool, ss << ", " << Part::TopoShape::shapeName(shape.ShapeType(),true); } if(aShapeTool->IsShape(label)) { - Quantity_Color c; + Quantity_ColorRGBA c; if(aColorTool->GetColor(label,XCAFDoc_ColorGen,c)) - ss << ", gc: " << c.StringName(c.Name()); + ss << ", gc: " << c.ColorToHex(c); if(aColorTool->GetColor(label,XCAFDoc_ColorSurf,c)) - ss << ", sc: " << c.StringName(c.Name()); + ss << ", sc: " << c.ColorToHex(c); if(aColorTool->GetColor(label,XCAFDoc_ColorCurv,c)) - ss << ", cc: " << c.StringName(c.Name()); + ss << ", cc: " << c.ColorToHex(c); } ss << std::endl; @@ -250,7 +253,7 @@ void ImportOCAF2::setObjectName(Info &info, TDF_Label label) { bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bool noDefault) { bool ret = false; - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if(aColorTool->GetColor(shape, XCAFDoc_ColorSurf, aColor)) { App::Color c = convertColor(aColor); if(!check || info.faceColor!=c) { @@ -383,7 +386,7 @@ bool ImportOCAF2::createObject(App::Document *doc, TDF_Label label, bool foundFaceColor=false,foundEdgeColor=false; App::Color faceColor,edgeColor; - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if(aColorTool->GetColor(l, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(l, XCAFDoc_ColorGen, aColor)) { @@ -666,7 +669,7 @@ void ImportOCAF2::getSHUOColors(TDF_Label label, subname += App::DocumentObject::hiddenMarker(); colors.emplace(subname,App::Color()); } else { - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if(aColorTool->GetColor(slabel, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(slabel, XCAFDoc_ColorGen, aColor)) { @@ -800,7 +803,7 @@ bool ImportOCAF2::createAssembly(App::Document *_doc, childInfo.vis.push_back(vis); childInfo.labels.push_back(childLabel); childInfo.plas.emplace_back(Part::TopoShape::convert(childShape.Location().Transformation())); - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if (aColorTool->GetColor(childShape, XCAFDoc_ColorSurf, aColor)) { childInfo.colors[childInfo.plas.size()-1] = convertColor(aColor); } @@ -1051,7 +1054,7 @@ void ExportOCAF2::setupObject(TDF_Label label, App::DocumentObject *obj, continue; } const App::Color& c = vv.second; - Quantity_Color color = convertColor(c); + Quantity_ColorRGBA color = convertColor(c); auto colorType = vv.first[0]=='F'?XCAFDoc_ColorSurf:XCAFDoc_ColorCurv; if(vv.first=="Face" || vv.first=="Edge") { aColorTool->SetColor(nodeLabel, color, colorType); @@ -1302,7 +1305,7 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, // setDefaultInstanceColor( override, PSA); // auto childShape = aShapeTool->GetShape(childLabel); - Quantity_Color col; + Quantity_ColorRGBA col; if(!aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorGen,col) && !aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorSurf,col) && !aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorCurv,col)) diff --git a/src/Mod/Import/Gui/AppImportGuiPy.cpp b/src/Mod/Import/Gui/AppImportGuiPy.cpp index 6601973cc2..72e5de3417 100644 --- a/src/Mod/Import/Gui/AppImportGuiPy.cpp +++ b/src/Mod/Import/Gui/AppImportGuiPy.cpp @@ -322,9 +322,10 @@ private: return; } // vp->MapFaceColor.setValue(false); - if(colors.size() == 1) + if(colors.size() == 1) { vp->ShapeColor.setValue(colors.front()); - else + vp->Transparency.setValue(100 * colors.front().a); + } else vp->DiffuseColor.setValues(colors); } virtual void applyEdgeColors(Part::Feature* part, const std::vector& colors) override { From 329a682a8e42bc4bfd433e92c8e7bc3e41ff20f2 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 7 Oct 2021 18:08:00 +0800 Subject: [PATCH 057/101] Import: fix STEP color and add transparency in legacy importer/exporter --- src/Mod/Import/App/ExportOCAF.cpp | 35 ++++++++++----------------- src/Mod/Import/App/ImportOCAF.cpp | 39 +++++++++++++++++++------------ src/Mod/Import/App/ImportOCAF.h | 4 ++-- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/Mod/Import/App/ExportOCAF.cpp b/src/Mod/Import/App/ExportOCAF.cpp index bce4ff03b8..9ba1a4d0ae 100644 --- a/src/Mod/Import/App/ExportOCAF.cpp +++ b/src/Mod/Import/App/ExportOCAF.cpp @@ -58,7 +58,7 @@ # include # include # include -# include +# include # include # include # include @@ -102,6 +102,11 @@ # define OCC_COLOR_SPACE Quantity_TOC_RGB #endif +static inline Quantity_ColorRGBA convertColor(const App::Color &c) +{ + return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), c.a); +} + using namespace Import; @@ -290,7 +295,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co */ // Add color information - Quantity_Color col; + Quantity_ColorRGBA col; std::set face_index; TopTools_IndexedMapOfShape faces; @@ -323,11 +328,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co if (!faceLabel.IsNull()) { const App::Color& color = colors[index-1]; - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); + col = convertColor(color); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } @@ -336,11 +337,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co } else if (!colors.empty()) { App::Color color = colors.front(); - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); + col = convertColor(color); aColorTool->SetColor(shapeLabel, col, XCAFDoc_ColorGen); } @@ -406,7 +403,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch TopoDS_Shape baseShape = part->Shape.getValue(); // Add color information - Quantity_Color col; + Quantity_ColorRGBA col; std::set face_index; TopTools_IndexedMapOfShape faces; @@ -439,11 +436,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch if (!faceLabel.IsNull()) { const App::Color& color = colors[index-1]; - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); + col = convertColor(color); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } @@ -453,11 +446,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch } else if (!colors.empty()) { App::Color color = colors.front(); - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],OCC_COLOR_SPACE); + col = convertColor(color); aColorTool->SetColor(label, col, XCAFDoc_ColorGen); } } diff --git a/src/Mod/Import/App/ImportOCAF.cpp b/src/Mod/Import/App/ImportOCAF.cpp index 17cc74f906..f92e7300b3 100644 --- a/src/Mod/Import/App/ImportOCAF.cpp +++ b/src/Mod/Import/App/ImportOCAF.cpp @@ -60,7 +60,7 @@ # include # include # include -# include +# include # include # include # include @@ -108,6 +108,23 @@ using namespace Import; +#if OCC_VERSION_HEX >= 0x070500 +// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware +# define OCC_COLOR_SPACE Quantity_TOC_sRGB +#else +# define OCC_COLOR_SPACE Quantity_TOC_RGB +#endif + +static inline App::Color convertColor(const Quantity_ColorRGBA &c) +{ + Standard_Real r, g, b; + c.GetRGB().Values(r, g, b, OCC_COLOR_SPACE); + return App::Color(static_cast(r), + static_cast(g), + static_cast(b), + static_cast(c.Alpha())); +} + #define OCAF_KEEP_PLACEMENT ImportOCAF::ImportOCAF(Handle(TDocStd_Document) h, App::Document* d, const std::string& name) @@ -439,14 +456,12 @@ void ImportOCAF::createShape(const TopoDS_Shape& aShape, const TopLoc_Location& void ImportOCAF::loadColors(Part::Feature* part, const TopoDS_Shape& aShape) { - Quantity_Color aColor; + Quantity_ColorRGBA aColor; App::Color color(0.8f,0.8f,0.8f); if (aColorTool->GetColor(aShape, XCAFDoc_ColorGen, aColor) || aColorTool->GetColor(aShape, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(aShape, XCAFDoc_ColorCurv, aColor)) { - color.r = (float)aColor.Red(); - color.g = (float)aColor.Green(); - color.b = (float)aColor.Blue(); + color = convertColor(aColor); std::vector colors; colors.push_back(color); applyColors(part, colors); @@ -468,9 +483,7 @@ void ImportOCAF::loadColors(Part::Feature* part, const TopoDS_Shape& aShape) aColorTool->GetColor(xp.Current(), XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(xp.Current(), XCAFDoc_ColorCurv, aColor)) { int index = faces.FindIndex(xp.Current()); - color.r = (float)aColor.Red(); - color.g = (float)aColor.Green(); - color.b = (float)aColor.Blue(); + color = convertColor(aColor); faceColors[index-1] = color; found_face_color = true; } @@ -551,7 +564,7 @@ void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setna part = static_cast(doc->addObject("Part::Feature", default_name.c_str())); part->Label.setValue(default_name); part->Shape.setValue(shape); - std::map::const_iterator jt; + std::map::const_iterator jt; jt = myColorMap.find(shape.HashCode(INT_MAX)); App::Color partColor(0.8f,0.8f,0.8f); @@ -596,11 +609,7 @@ void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setna jt = myColorMap.find(xp.Current().HashCode(INT_MAX)); if (jt != myColorMap.end()) { int index = faces.FindIndex(xp.Current()); - App::Color color; - color.r = (float)jt->second.Red(); - color.g = (float)jt->second.Green(); - color.b = (float)jt->second.Blue(); - faceColors[index-1] = color; + faceColors[index-1] = convertColor(jt->second); found_face_color = true; } xp.Next(); @@ -653,7 +662,7 @@ void ImportXCAF::loadShapes(const TDF_Label& label) } // getting color - Quantity_Color col; + Quantity_ColorRGBA col; if (hColors->GetColor(label, XCAFDoc_ColorGen, col) || hColors->GetColor(label, XCAFDoc_ColorSurf, col) || hColors->GetColor(label, XCAFDoc_ColorCurv, col)) { diff --git a/src/Mod/Import/App/ImportOCAF.h b/src/Mod/Import/App/ImportOCAF.h index 8c4d609265..4f30d921a9 100644 --- a/src/Mod/Import/App/ImportOCAF.h +++ b/src/Mod/Import/App/ImportOCAF.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -117,7 +117,7 @@ private: std::map myShells; std::map myCompds; std::map myShapes; - std::map myColorMap; + std::map myColorMap; std::map myNameMap; }; From 48761f4e7da714fd701424955d0069c6d7c47045 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 7 Oct 2021 15:07:12 +0200 Subject: [PATCH 058/101] Draft_Hatch_ViewProvider -> ViewProviderDraftHatch --- src/Mod/Draft/Draft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 7dcef93c70..992fb7c418 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -425,6 +425,6 @@ if App.GuiUp: from draftobjects.hatch import (Hatch) from draftmake.make_hatch import (make_hatch) if App.GuiUp: - from draftviewproviders.view_hatch import (Draft_Hatch_ViewProvider) + from draftviewproviders.view_hatch import (ViewProviderDraftHatch) ## @} From 059b3d46aa2620715dde4f33f1777706d6200189 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 7 Oct 2021 15:08:06 +0200 Subject: [PATCH 059/101] Draft_Hatch_ViewProvider -> ViewProviderDraftHatch --- src/Mod/Draft/draftmake/make_hatch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftmake/make_hatch.py b/src/Mod/Draft/draftmake/make_hatch.py index fc3021e8ef..004082dd4a 100644 --- a/src/Mod/Draft/draftmake/make_hatch.py +++ b/src/Mod/Draft/draftmake/make_hatch.py @@ -24,7 +24,7 @@ import FreeCAD from draftobjects.hatch import Hatch -from draftviewproviders.view_hatch import Draft_Hatch_ViewProvider +from draftviewproviders.view_hatch import ViewProviderDraftHatch def make_hatch(baseobject, filename, pattern, scale, rotation): @@ -43,4 +43,4 @@ def make_hatch(baseobject, filename, pattern, scale, rotation): obj.Scale = scale obj.Rotation = rotation if FreeCAD.GuiUp: - Draft_Hatch_ViewProvider(obj.ViewObject) + ViewProviderDraftHatch(obj.ViewObject) From b6ec36fc3f10323dfd21da9dd86c43cfd99ff8f3 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 7 Oct 2021 15:08:53 +0200 Subject: [PATCH 060/101] Draft_Hatch_ViewProvider -> ViewProviderDraftHatch --- src/Mod/Draft/draftviewproviders/view_hatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftviewproviders/view_hatch.py b/src/Mod/Draft/draftviewproviders/view_hatch.py index 374cc06f3d..aa002cea04 100644 --- a/src/Mod/Draft/draftviewproviders/view_hatch.py +++ b/src/Mod/Draft/draftviewproviders/view_hatch.py @@ -27,7 +27,7 @@ import os import FreeCAD from draftguitools.gui_hatch import Draft_Hatch_TaskPanel -class Draft_Hatch_ViewProvider: +class ViewProviderDraftHatch: def __init__(self,vobj): From 709181d9091ff7ee22153576c0af994ec8e74a6e Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Fri, 8 Oct 2021 07:51:00 +0800 Subject: [PATCH 061/101] Import: avoid using Quantity_ColorRGBA::ColorToHex() For using older OCCT --- src/Mod/Import/App/ImportOCAF2.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index b68f82c0f5..f997187f36 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -50,6 +50,7 @@ #include +#include #include #include #include @@ -99,6 +100,12 @@ static inline Quantity_ColorRGBA convertColor(const App::Color &c) return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), c.a); } +static inline std::ostream& operator<<(std::ostream& os, const Quantity_ColorRGBA &c) { + App::Color color = convertColor(c); + auto toHex = [](float v) {return boost::format("%02X") % static_cast(v*255);}; + return os << "#" << toHex(color.r) << toHex(color.g) << toHex(color.b) << toHex(color.a); +} + static std::string labelName(TDF_Label label) { std::string txt; Handle(TDataStd_Name) name; @@ -140,11 +147,11 @@ static void printLabel(TDF_Label label, Handle(XCAFDoc_ShapeTool) aShapeTool, if(aShapeTool->IsShape(label)) { Quantity_ColorRGBA c; if(aColorTool->GetColor(label,XCAFDoc_ColorGen,c)) - ss << ", gc: " << c.ColorToHex(c); + ss << ", gc: " << c; if(aColorTool->GetColor(label,XCAFDoc_ColorSurf,c)) - ss << ", sc: " << c.ColorToHex(c); + ss << ", sc: " << c; if(aColorTool->GetColor(label,XCAFDoc_ColorCurv,c)) - ss << ", cc: " << c.ColorToHex(c); + ss << ", cc: " << c; } ss << std::endl; From c9d17ebde2400f83d1e1e799bdb0a7f85a0da96d Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 12:41:07 +0200 Subject: [PATCH 062/101] Part: add convenience functions to retrieve triangulation of a face or edge --- src/Mod/Part/App/Tools.cpp | 170 ++++++++++++++++++++++++++++++++++++- src/Mod/Part/App/Tools.h | 31 ++++++- 2 files changed, 198 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index b02c056045..c0e5944508 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -25,25 +25,31 @@ # 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 +# if OCC_VERSION_HEX < 0x070600 +# include +# include +# endif #endif #include @@ -138,6 +144,20 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries, assert (0); Standard_ConstructionError::Raise ("Tools::makeSurface()"); } +#if OCC_VERSION_HEX >= 0x070600 + else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_CurveOnSurface))) { + //G1 constraint + Handle(Adaptor3d_CurveOnSurface) aHCOS (Handle(Adaptor3d_CurveOnSurface)::DownCast (aCur)); + Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHCOS, 1 /*GeomAbs_G1*/,aNbPnts, aTol3d, anAngTol, aCurvTol); + aPlateBuilder.Add (aConst); + } + else if (aCur->IsKind (STANDARD_TYPE (GeomAdaptor_Curve))) { + //G0 constraint + Handle(GeomAdaptor_Curve) aHC (Handle(GeomAdaptor_Curve)::DownCast (aCur)); + Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 /*GeomAbs_G0*/, aNbPnts, aTol3d); + aPlateBuilder.Add (aConst); + } +#else else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_HCurveOnSurface))) { //G1 constraint Handle(Adaptor3d_HCurveOnSurface) aHCOS (Handle(Adaptor3d_HCurveOnSurface)::DownCast (aCur)); @@ -150,6 +170,7 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries, Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 /*GeomAbs_G0*/, aNbPnts, aTol3d); aPlateBuilder.Add (aConst); } +#endif else if (aCur->IsKind (STANDARD_TYPE (Geom_Point))) { //Point constraint Handle(Geom_Point) aGP (Handle(Geom_Point)::DownCast (aCur)); @@ -190,3 +211,148 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries, return aRes; } + +bool Part::Tools::getTriangulation(const TopoDS_Face& face, std::vector& points, std::vector& facets) +{ + TopLoc_Location loc; + Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc); + if (hTria.IsNull()) + return false; + + // getting the transformation of the face + gp_Trsf transf; + bool identity = true; + if (!loc.IsIdentity()) { + identity = false; + transf = loc.Transformation(); + } + + // check orientation + TopAbs_Orientation orient = face.Orientation(); + + Standard_Integer nbNodes = hTria->NbNodes(); + Standard_Integer nbTriangles = hTria->NbTriangles(); +#if OCC_VERSION_HEX < 0x070600 + const TColgp_Array1OfPnt& nodes = hTria->Nodes(); + const Poly_Array1OfTriangle& triangles = hTria->Triangles(); +#endif + + points.reserve(nbNodes); + facets.reserve(nbTriangles); + + // cycling through the poly mesh + // + for (int i = 1; i <= nbNodes; i++) { +#if OCC_VERSION_HEX < 0x070600 + gp_Pnt p = nodes(i); +#else + gp_Pnt p = hTria->Node(i); +#endif + + // transform the vertices to the location of the face + if (!identity) { + p.Transform(transf); + } + + points.push_back(p); + } + + for (int i = 1; i <= nbTriangles; i++) { + // Get the triangle + Standard_Integer n1,n2,n3; +#if OCC_VERSION_HEX < 0x070600 + triangles(i).Get(n1, n2, n3); +#else + hTria->Triangle(i).Get(n1, n2, n3); +#endif + --n1; --n2; --n3; + + // change orientation of the triangles + if (orient != TopAbs_FORWARD) { + std::swap(n1, n2); + } + + facets.emplace_back(n1, n2, n3); + } + + return true; +} + +bool Part::Tools::getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector& points) +{ + TopLoc_Location loc; + Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc); + if (hTria.IsNull()) + return false; + + // this holds the indices of the edge's triangulation to the actual points + Handle(Poly_PolygonOnTriangulation) hPoly = BRep_Tool::PolygonOnTriangulation(edge, hTria, loc); + if (hPoly.IsNull()) + return false; + + // getting the transformation of the edge + gp_Trsf transf; + bool identity = true; + if (!loc.IsIdentity()) { + identity = false; + transf = loc.Transformation(); + } + + // getting size and create the array + Standard_Integer nbNodes = hPoly->NbNodes(); + points.reserve(nbNodes); + const TColStd_Array1OfInteger& indices = hPoly->Nodes(); +#if OCC_VERSION_HEX < 0x070600 + const TColgp_Array1OfPnt& Nodes = hTria->Nodes(); +#endif + + // go through the index array + for (Standard_Integer i = indices.Lower(); i <= indices.Upper(); i++) { +#if OCC_VERSION_HEX < 0x070600 + gp_Pnt p = Nodes(indices(i)); +#else + gp_Pnt p = hTria->Node(indices(i)); +#endif + if (!identity) { + p.Transform(transf); + } + + points.push_back(p); + } + + return true; +} + +bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector& points) +{ + TopLoc_Location loc; + Handle(Poly_Polygon3D) hPoly = BRep_Tool::Polygon3D(edge, loc); + if (hPoly.IsNull()) + return false; + + // getting the transformation of the edge + gp_Trsf transf; + bool identity = true; + if (!loc.IsIdentity()) { + identity = false; + transf = loc.Transformation(); + } + + // getting size and create the array + Standard_Integer nbNodes = hPoly->NbNodes(); + points.reserve(nbNodes); + const TColgp_Array1OfPnt& nodes = hPoly->Nodes(); + + for (int i = 1; i <= nbNodes; i++) { + gp_Pnt p = nodes(i); + + // transform the vertices to the location of the face + if (!identity) { + p.Transform(transf); + } + + points.push_back(p); + } + + return true; +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index a936c352c6..19ecf937fd 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -30,7 +30,11 @@ #include #include #include +#include #include +#include +#include +#include class gp_Lin; class gp_Pln; @@ -104,7 +108,32 @@ public: const Standard_Integer theNbPnts, const Standard_Integer theNbIter, const Standard_Integer theMaxDeg); - + /*! + * @brief getTriangulation + * The indexes of the triangles are adjusted to the points vector. + * @param face + * @param points + * @param facets + * @return true if a triangulation exists or false otherwise + */ + static bool getTriangulation(const TopoDS_Face& face, std::vector& points, std::vector& facets); + /*! + * \brief getPolygonOnTriangulation + * Get the polygon of edge. + * \note \a edge must belong to face. + * \param edge + * \param face + * \param points + * \return true if a triangulation exists or false otherwise + */ + static bool getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector& points); + /*! + * \brief getPolygon3D + * \param edge + * \param points + * \return true if a polygon exists or false otherwise + */ + static bool getPolygon3D(const TopoDS_Edge& edge, std::vector& points); }; } //namespace Part From 8e6dab209ee59be61d83a0ff249283a8809fa917 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 12:43:06 +0200 Subject: [PATCH 063/101] Part: change TopoShape::exportFaceSet and TopoShape::exportLineSet to use the functions of the Tools class --- src/Mod/Part/App/TopoShape.cpp | 141 +++++++-------------------------- 1 file changed, 29 insertions(+), 112 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 614661594d..09cfab45bb 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1097,65 +1097,27 @@ void TopoShape::exportFaceSet(double dev, double ca, for (ex.Init(this->_Shape, TopAbs_FACE); ex.More(); ex.Next(), index++) { // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - Standard_Integer nbNodesInFace,nbTriInFace; + std::vector points; + std::vector facets; + if (!Tools::getTriangulation(aFace, points, facets)) + continue; + std::vector vertices; std::vector indices; + vertices.resize(points.size()); + indices.resize(4 * facets.size()); - // doing the meshing and checking the result - TopLoc_Location aLoc; - Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); - if (aPoly.IsNull()) continue; - - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); + for (std::size_t i = 0; i < points.size(); i++) { + vertices[i] = Base::convertTo(points[i]); } - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - nbTriInFace = aPoly->NbTriangles(); - vertices.resize(nbNodesInFace); - indices.resize(4*nbTriInFace); - - // check orientation - TopAbs_Orientation orient = aFace.Orientation(); - - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = aPoly->Triangles(); - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - for (int i=1;i<=nbTriInFace;i++) { - // Get the triangle - Standard_Integer N1,N2,N3; - Triangles(i).Get(N1,N2,N3); - - // change orientation of the triangles - if (orient != TopAbs_FORWARD) { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - gp_Pnt V1 = Nodes(N1); - gp_Pnt V2 = Nodes(N2); - gp_Pnt V3 = Nodes(N3); - - // transform the vertices to the place of the face - if (!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - } - - vertices[N1-1].Set((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); - vertices[N2-1].Set((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); - vertices[N3-1].Set((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); - - int j = i - 1; - N1--; N2--; N3--; - indices[4*j] = N1; indices[4*j+1] = N2; indices[4*j+2] = N3; indices[4*j+3] = -1; + for (std::size_t i = 0; i < facets.size(); i++) { + Standard_Integer n1,n2,n3; + facets[i].Get(n1, n2, n3); + indices[4 * i ] = n1; + indices[4 * i + 1] = n2; + indices[4 * i + 2] = n3; + indices[4 * i + 3] = -1; } builder.beginSeparator(); @@ -1170,7 +1132,7 @@ void TopoShape::exportFaceSet(double dev, double ca, builder.endPoints(); builder.addIndexedFaceSet(indices); builder.endSeparator(); - } // end of face loop + } } void TopoShape::exportLineSet(std::ostream& str) const @@ -1183,72 +1145,27 @@ void TopoShape::exportLineSet(std::ostream& str) const // build up map edge->face TopTools_IndexedDataMapOfShapeListOfShape edge2Face; TopExp::MapShapesAndAncestors(this->_Shape, TopAbs_EDGE, TopAbs_FACE, edge2Face); - for (int i=0; i points; - // try to triangulate the edge - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); - - std::vector vertices; - Standard_Integer nbNodesInFace; - - // triangulation succeeded? - if (!aPoly.IsNull()) { - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - nbNodesInFace = aPoly->NbNodes(); - vertices.resize(nbNodesInFace); - - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - - gp_Pnt V; - for (Standard_Integer i=0;i < nbNodesInFace;i++) { - V = Nodes(i+1); - V.Transform(myTransf); - vertices[i].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z())); - } - } - else { + if (!Tools::getPolygon3D(aEdge, points)) { // the edge has not its own triangulation, but then a face the edge is attached to // must provide this triangulation // Look for one face in our map (it doesn't care which one we take) const TopoDS_Face& aFace = TopoDS::Face(edge2Face.FindFromKey(aEdge).First()); - - // take the face's triangulation instead - Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc); - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - - if (aPolyTria.IsNull()) break; - - // this holds the indices of the edge's triangulation to the actual points - Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc); - if (aPoly.IsNull()) - continue; // polygon does not exist - - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - vertices.resize(nbNodesInFace); - - const TColStd_Array1OfInteger& indices = aPoly->Nodes(); - const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes(); - - gp_Pnt V; - int pos = 0; - // go through the index array - for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { - V = Nodes(indices(i)); - V.Transform(myTransf); - vertices[pos++].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z())); - } + if (!Tools::getPolygonOnTriangulation(aEdge, aFace, points)) + continue; } + std::vector vertices; + vertices.reserve(points.size()); + std::for_each(points.begin(), points.end(), [&vertices](const gp_Pnt& p) { + vertices.push_back(Base::convertTo(p)); + }); + builder.addLineSet(vertices, 2, 0, 0, 0); } } From 08d46b5f882420c8d4066427fcc8dab5b1882097 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:28:22 +0200 Subject: [PATCH 064/101] Part: add methods to get the point normals of the triangulation or surface --- src/Mod/Part/App/Tools.cpp | 58 ++++++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 17 +++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index c0e5944508..41284befed 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -29,6 +29,7 @@ # include # include # include +# include # include # include # include @@ -356,3 +357,60 @@ bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector& poi return true; } + +void Part::Tools::getPointNormals(const std::vector& points, const std::vector& facets, std::vector& vertexnormals) +{ + vertexnormals.resize(points.size()); + + for (const auto& it : facets) { + // Get the triangle + Standard_Integer n1,n2,n3; + it.Get(n1,n2,n3); + + // Calculate triangle normal + gp_Vec v1(points[n1].XYZ()); + gp_Vec v2(points[n2].XYZ()); + gp_Vec v3(points[n3].XYZ()); + gp_Vec n = (v2 - v1) ^ (v3 - v1); + + // add the triangle normal to the vertex normal for all points of this triangle + vertexnormals[n1] += n; + vertexnormals[n2] += n; + vertexnormals[n3] += n; + } + + for (auto& it : vertexnormals) + it.Normalize(); +} + +void Part::Tools::getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals) +{ + if (points.size() != vertexnormals.size()) + return; + + Handle(Geom_Surface) hSurface = BRep_Tool::Surface(face); + if (hSurface.IsNull()) + return; + + // normalize all vertex normals + for (std::size_t i = 0; i < points.size(); i++) { + try { + GeomAPI_ProjectPointOnSurf ProPntSrf(points[i], hSurface); + Standard_Real u, v; + ProPntSrf.Parameters(1, u, v); + + GeomLProp_SLProps propOfFace(hSurface, u, v, 2, gp::Resolution()); + + gp_Dir normal = propOfFace.Normal(); + gp_Vec temp = normal; + if (temp * vertexnormals[i] < 0.0) + temp = -temp; + vertexnormals[i] = temp; + + } + catch (...) { + } + + vertexnormals[i].Normalize(); + } +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 19ecf937fd..a487530a7d 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -134,6 +134,23 @@ public: * \return true if a polygon exists or false otherwise */ static bool getPolygon3D(const TopoDS_Edge& edge, std::vector& points); + /*! + * \brief getPointNormals + * Calculate the point normals of the given triangulation. + * \param points + * \param facets + * \param normals + */ + static void getPointNormals(const std::vector& points, const std::vector& facets, std::vector& vertexnormals); + /*! + * \brief getPointNormals + * Computes the more accurate surface normals for the points. If the calculation for a point fails then the precomputed + * point normal of the triangulation is used. + * \param points + * \param face + * \param vertexnormals + */ + static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); }; } //namespace Part From 0f3b5d275070477b7cd2bbfa2dc930135448fb0c Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:29:36 +0200 Subject: [PATCH 065/101] Raytracing: in PovTools/LuxTools use functions of Tools class --- src/Mod/Raytracing/App/LuxTools.cpp | 34 ++--- src/Mod/Raytracing/App/PovTools.cpp | 226 ++++++---------------------- src/Mod/Raytracing/App/PovTools.h | 3 - 3 files changed, 65 insertions(+), 198 deletions(-) diff --git a/src/Mod/Raytracing/App/LuxTools.cpp b/src/Mod/Raytracing/App/LuxTools.cpp index 881317f137..86db2ee16f 100644 --- a/src/Mod/Raytracing/App/LuxTools.cpp +++ b/src/Mod/Raytracing/App/LuxTools.cpp @@ -44,6 +44,7 @@ #include "PovTools.h" #include "LuxTools.h" +#include using Base::Console; @@ -95,35 +96,34 @@ void LuxTools::writeShape(std::ostream &out, const char *PartName, const TopoDS_ // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - // this block mesh the face and transfers it in a C array of vertices and face indexes - Standard_Integer nbNodesInFace,nbTriInFace; - gp_Vec* vertices=0; - gp_Vec* vertexnormals=0; - long* cons=0; + std::vector points; + std::vector vertexnormals; + std::vector facets; + if (!Part::Tools::getTriangulation(aFace, points, facets)) { + break; + } - PovTools::transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); + Part::Tools::getPointNormals(points, facets, vertexnormals); + Part::Tools::getPointNormals(points, aFace, vertexnormals); - if (!vertices) break; // writing vertices - for (int i=0; i < nbNodesInFace; i++) { - P << vertices[i].X() << " " << vertices[i].Y() << " " << vertices[i].Z() << " "; + for (std::size_t i=0; i < points.size(); i++) { + P << points[i].X() << " " << points[i].Y() << " " << points[i].Z() << " "; } // writing per vertex normals - for (int j=0; j < nbNodesInFace; j++) { + for (std::size_t j=0; j < vertexnormals.size(); j++) { N << vertexnormals[j].X() << " " << vertexnormals[j].Y() << " " << vertexnormals[j].Z() << " "; } // writing triangle indices - for (int k=0; k < nbTriInFace; k++) { - triindices << cons[3*k]+vi << " " << cons[3*k+2]+vi << " " << cons[3*k+1]+vi << " "; + for (std::size_t k=0; k < facets.size(); k++) { + Standard_Integer n1, n2, n3; + facets[k].Get(n1, n2, n3); + triindices << n1 + vi << " " << n3 + vi << " " << n2 + vi << " "; } - vi = vi + nbNodesInFace; - - delete [] vertexnormals; - delete [] vertices; - delete [] cons; + vi = vi + points.size(); seq.next(); diff --git a/src/Mod/Raytracing/App/PovTools.cpp b/src/Mod/Raytracing/App/PovTools.cpp index e2d7c1f4d7..049308c8b9 100644 --- a/src/Mod/Raytracing/App/PovTools.cpp +++ b/src/Mod/Raytracing/App/PovTools.cpp @@ -41,6 +41,7 @@ #include "PovTools.h" +#include using Base::Console; @@ -242,53 +243,53 @@ void PovTools::writeShape(std::ostream &out, const char *PartName, // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - // this block mesh the face and transfers it in a C array of vertices and face indexes - Standard_Integer nbNodesInFace,nbTriInFace; - gp_Vec* vertices=0; - gp_Vec* vertexnormals=0; - long* cons=0; + std::vector points; + std::vector vertexnormals; + std::vector facets; + if (!Part::Tools::getTriangulation(aFace, points, facets)) { + break; + } + Part::Tools::getPointNormals(points, facets, vertexnormals); + Part::Tools::getPointNormals(points, aFace, vertexnormals); - transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); - - if (!vertices) break; // writing per face header out << "// face number" << l << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << "#declare " << PartName << l << " = mesh2{" << endl << " vertex_vectors {" << endl - << " " << nbNodesInFace << "," << endl; + << " " << points.size() << "," << endl; // writing vertices - for (int i=0; i < nbNodesInFace; i++) { - out << " <" << vertices[i].X() << "," - << vertices[i].Z() << "," - << vertices[i].Y() << ">," - << endl; + for (std::size_t i=0; i < points.size(); i++) { + out << " <" + << points[i].X() << "," + << points[i].Z() << "," + << points[i].Y() << ">," + << endl; } out << " }" << endl // writing per vertex normals << " normal_vectors {" << endl - << " " << nbNodesInFace << "," << endl; - for (int j=0; j < nbNodesInFace; j++) { - out << " <" << vertexnormals[j].X() << "," - << vertexnormals[j].Z() << "," - << vertexnormals[j].Y() << ">," - << endl; + << " " << vertexnormals.size() << "," << endl; + for (std::size_t j=0; j < vertexnormals.size(); j++) { + out << " <" + << vertexnormals[j].X() << "," + << vertexnormals[j].Z() << "," + << vertexnormals[j].Y() << ">," + << endl; } out << " }" << endl // writing triangle indices << " face_indices {" << endl - << " " << nbTriInFace << "," << endl; - for (int k=0; k < nbTriInFace; k++) { - out << " <" << cons[3*k] << ","<< cons[3*k+2] << ","<< cons[3*k+1] << ">," << endl; + << " " << facets.size() << "," << endl; + for (std::size_t k=0; k < facets.size(); k++) { + Standard_Integer n1, n2, n3; + facets[k].Get(n1, n2, n3); + out << " <" << n1 << ","<< n3 << "," << n2 << ">," << endl; } // end of face out << " }" << endl << "} // end of Face"<< l << endl << endl; - delete [] vertexnormals; - delete [] vertices; - delete [] cons; - seq.next(); } // end of face loop @@ -323,36 +324,32 @@ void PovTools::writeShapeCSV(const char *FileName, Base::SequencerLauncher seq("Writing file", l); // write the file - l = 1; - for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) { + for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next()) { // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - // this block mesh the face and transfers it in a C array of vertices and face indexes - Standard_Integer nbNodesInFace,nbTriInFace; - gp_Vec* vertices=0; - gp_Vec* vertexnormals=0; - long* cons=0; - - transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); - - if (!vertices) break; - // writing per face header - // writing vertices - for (int i=0; i < nbNodesInFace; i++) { - fout << vertices[i].X() << cSeperator - << vertices[i].Z() << cSeperator - << vertices[i].Y() << cSeperator - << vertexnormals[i].X() * fLength < points; + std::vector vertexnormals; + std::vector facets; + if (!Part::Tools::getTriangulation(aFace, points, facets)) { + break; } - delete [] vertexnormals; - delete [] vertices; - delete [] cons; + Part::Tools::getPointNormals(points, facets, vertexnormals); + Part::Tools::getPointNormals(points, aFace, vertexnormals); + + // writing per face header + // writing vertices + for (std::size_t i=0; i < points.size(); i++) { + fout << points[i].X() << cSeperator + << points[i].Z() << cSeperator + << points[i].Y() << cSeperator + << vertexnormals[i].X() * fLength << cSeperator + << vertexnormals[i].Z() * fLength << cSeperator + << vertexnormals[i].Y() * fLength << cSeperator + << endl; + } seq.next(); @@ -360,130 +357,3 @@ void PovTools::writeShapeCSV(const char *FileName, fout.close(); } - -void PovTools::transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace ) -{ - TopLoc_Location aLoc; - - // doing the meshing and checking the result - //BRepMesh_IncrementalMesh MESH(aFace,fDeflection); - Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); - if (aPoly.IsNull()) { - Base::Console().Log("Empty face triangulation\n"); - nbNodesInFace =0; - nbTriInFace = 0; - vertices = 0l; - cons = 0l; - return; - } - - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); - } - - Standard_Integer i; - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - nbTriInFace = aPoly->NbTriangles(); - *vertices = new gp_Vec[nbNodesInFace]; - *vertexnormals = new gp_Vec[nbNodesInFace]; - for (i=0; i < nbNodesInFace; i++) { - (*vertexnormals)[i]= gp_Vec(0.0,0.0,0.0); - } - - *cons = new long[3*(nbTriInFace)+1]; - - // check orientation - TopAbs_Orientation orient = aFace.Orientation(); - - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = aPoly->Triangles(); - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - for (i=1; i<=nbTriInFace; i++) { - // Get the triangle - Standard_Integer N1,N2,N3; - Triangles(i).Get(N1,N2,N3); - - // change orientation of the triangles - if ( orient != TopAbs_FORWARD ) - { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - gp_Pnt V1 = Nodes(N1); - gp_Pnt V2 = Nodes(N2); - gp_Pnt V3 = Nodes(N3); - - // transform the vertices to the place of the face - if (!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - } - - // Calculate triangle normal - gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); - gp_Vec Normal = (v2-v1)^(v3-v1); - - //Standard_Real Area = 0.5 * Normal.Magnitude(); - - // add the triangle normal to the vertex normal for all points of this triangle - (*vertexnormals)[N1-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); - (*vertexnormals)[N2-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); - (*vertexnormals)[N3-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); - - (*vertices)[N1-1].SetX((float)(V1.X())); - (*vertices)[N1-1].SetY((float)(V1.Y())); - (*vertices)[N1-1].SetZ((float)(V1.Z())); - (*vertices)[N2-1].SetX((float)(V2.X())); - (*vertices)[N2-1].SetY((float)(V2.Y())); - (*vertices)[N2-1].SetZ((float)(V2.Z())); - (*vertices)[N3-1].SetX((float)(V3.X())); - (*vertices)[N3-1].SetY((float)(V3.Y())); - (*vertices)[N3-1].SetZ((float)(V3.Z())); - - int j = i - 1; - N1--; - N2--; - N3--; - (*cons)[3*j] = N1; - (*cons)[3*j+1] = N2; - (*cons)[3*j+2] = N3; - } - - // normalize all vertex normals - for (i=0; i < nbNodesInFace; i++) { - - gp_Dir clNormal; - - try { - Handle(Geom_Surface) Surface = BRep_Tool::Surface(aFace); - - gp_Pnt vertex((*vertices)[i].XYZ()); -// gp_Pnt vertex((*vertices)[i][0], (*vertices)[i][1], (*vertices)[i][2]); - GeomAPI_ProjectPointOnSurf ProPntSrf(vertex, Surface); - Standard_Real fU, fV; - ProPntSrf.Parameters(1, fU, fV); - - GeomLProp_SLProps clPropOfFace(Surface, fU, fV, 2, gp::Resolution()); - - clNormal = clPropOfFace.Normal(); - gp_Vec temp = clNormal; - //Base::Console().Log("unterschied:%.2f",temp.dot((*vertexnormals)[i])); - if ( temp * (*vertexnormals)[i] < 0 ) - temp = -temp; - (*vertexnormals)[i] = temp; - - } - catch (...) { - } - - (*vertexnormals)[i].Normalize(); - } -} diff --git a/src/Mod/Raytracing/App/PovTools.h b/src/Mod/Raytracing/App/PovTools.h index d499e003a0..09088c5755 100644 --- a/src/Mod/Raytracing/App/PovTools.h +++ b/src/Mod/Raytracing/App/PovTools.h @@ -110,9 +110,6 @@ public: const TopoDS_Shape& Shape, float fMeshDeviation, float fLength); - - - static void transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace ); }; From 442c8d52a1989da8f17d60fafea5b81d79cbf0ab Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:32:19 +0200 Subject: [PATCH 066/101] Part: in TopoShape::getDomains use functions of Tools class --- src/Mod/Part/App/TopoShape.cpp | 58 +++++++++++++++------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 09cfab45bb..05341de3d6 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -3360,46 +3360,40 @@ void TopoShape::getDomains(std::vector& domains) const for (TopExp_Explorer xp(this->_Shape, TopAbs_FACE); xp.More(); xp.Next()) { TopoDS_Face face = TopoDS::Face(xp.Current()); - TopLoc_Location loc; - Handle(Poly_Triangulation) theTriangulation = BRep_Tool::Triangulation(face, loc); - if (theTriangulation.IsNull()) { + std::vector points; + std::vector facets; + if (!Tools::getTriangulation(face, points, facets)) { // For a face that cannot be meshed append an empty domain. // It's important for some algorithms (e.g. color mapping) that the numbers of // faces and domains match Domain domain; domains.push_back(domain); - continue; } + else { + Domain domain; + // copy the points + domain.points.reserve(points.size()); + for (const auto& it : points) { + Standard_Real X, Y, Z; + it.Coord (X, Y, Z); + domain.points.emplace_back(X, Y, Z); + } - Domain domain; - // copy the points - const TColgp_Array1OfPnt& points = theTriangulation->Nodes(); - domain.points.reserve(points.Length()); - for (int i = 1; i <= points.Length(); i++) { - gp_Pnt p = points(i); - p.Transform(loc.Transformation()); - Standard_Real X, Y, Z; - p.Coord (X, Y, Z); - domain.points.emplace_back(X, Y, Z); + // copy the triangles + domain.facets.reserve(facets.size()); + for (const auto& it : facets) { + Standard_Integer N1, N2, N3; + it.Get(N1, N2, N3); + + Facet tria; + tria.I1 = N1; + tria.I2 = N2; + tria.I3 = N3; + domain.facets.push_back(tria); + } + + domains.push_back(domain); } - - // copy the triangles - const TopAbs_Orientation anOrientation = face.Orientation(); - bool flip = (anOrientation == TopAbs_REVERSED); - const Poly_Array1OfTriangle& faces = theTriangulation->Triangles(); - domain.facets.reserve(faces.Length()); - for (int i = 1; i <= faces.Length(); i++) { - Standard_Integer N1, N2, N3; - faces(i).Get(N1, N2, N3); - - Facet tria; - tria.I1 = N1-1; tria.I2 = N2-1; tria.I3 = N3-1; - if (flip) - std::swap(tria.I1, tria.I2); - domain.facets.push_back(tria); - } - - domains.push_back(domain); } } From 9b4db7e06472bf5550d0b7627b28b425bfcc8470 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:32:41 +0200 Subject: [PATCH 067/101] Part: in Part.getFacets() use functions of Tools class --- src/Mod/Part/App/AppPartPy.cpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 08e3e9fd47..f16ae7e221 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -134,6 +134,7 @@ #include "PartFeature.h" #include "PartPyCXX.h" #include "modelRefine.h" +#include "Tools.h" #ifdef FCUseFreeType # include "FT2FC.h" @@ -804,33 +805,24 @@ private: auto theShape = static_cast(shape)->getTopoShapePtr()->getShape(); for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) { TopoDS_Face currentFace = TopoDS::Face(ex.Current()); - TopLoc_Location loc; - Handle(Poly_Triangulation) facets = BRep_Tool::Triangulation(currentFace, loc); - const TopAbs_Orientation anOrientation = currentFace.Orientation(); - bool flip = (anOrientation == TopAbs_REVERSED); - if (!facets.IsNull()) { - const TColgp_Array1OfPnt& nodes = facets->Nodes(); - const Poly_Array1OfTriangle& triangles = facets->Triangles(); - for (int i = 1; i <= triangles.Length(); i++) { + + std::vector points; + std::vector facets; + if (Tools::getTriangulation(currentFace, points, facets)) { + for (const auto& it : facets) { Standard_Integer n1,n2,n3; - triangles(i).Get(n1, n2, n3); - gp_Pnt p1 = nodes(n1); - gp_Pnt p2 = nodes(n2); - gp_Pnt p3 = nodes(n3); - p1.Transform(loc.Transformation()); - p2.Transform(loc.Transformation()); - p3.Transform(loc.Transformation()); + it.Get(n1, n2, n3); + + gp_Pnt p1 = points[n1]; + gp_Pnt p2 = points[n2]; + gp_Pnt p3 = points[n3]; + // TODO: verify if tolerance should be hard coded if (!p1.IsEqual(p2, 0.01) && !p2.IsEqual(p3, 0.01) && !p3.IsEqual(p1, 0.01)) { PyObject *t1 = PyTuple_Pack(3, PyFloat_FromDouble(p1.X()), PyFloat_FromDouble(p1.Y()), PyFloat_FromDouble(p1.Z())); PyObject *t2 = PyTuple_Pack(3, PyFloat_FromDouble(p2.X()), PyFloat_FromDouble(p2.Y()), PyFloat_FromDouble(p2.Z())); PyObject *t3 = PyTuple_Pack(3, PyFloat_FromDouble(p3.X()), PyFloat_FromDouble(p3.Y()), PyFloat_FromDouble(p3.Z())); - if (flip) { - list.append(Py::asObject(PyTuple_Pack(3, t2, t1, t3))); - } - else { - list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3))); - } + list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3))); } } } From f43226f1f665bcf32c7dea72377718fba6bbf537 Mon Sep 17 00:00:00 2001 From: Tomas Pavlicek Date: Fri, 8 Oct 2021 16:12:01 +0200 Subject: [PATCH 068/101] TechDraw - Balloon updates - review based changes --- src/Mod/TechDraw/Gui/Command.cpp | 15 ++++++++++++--- src/Mod/TechDraw/Gui/QGVPage.cpp | 28 ++++++++++++++-------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index 2002008728..e512a96e1a 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -87,16 +87,17 @@ #include #include "DrawGuiUtil.h" -#include "PreferencesGui.h" #include "MDIViewPage.h" +#include "PreferencesGui.h" +#include "QGIViewPart.h" +#include "Rez.h" #include "TaskProjGroup.h" #include "TaskSectionView.h" #include "TaskActiveView.h" #include "TaskDetail.h" #include "ViewProviderPage.h" #include "ViewProviderViewPart.h" -#include "QGIViewPart.h" -#include "Rez.h" + class Vertex; using namespace TechDrawGui; @@ -807,7 +808,15 @@ bool _checkDrawViewPartBalloon(Gui::Command* cmd) { bool _checkDirectPlacement(const QGIViewPart *viewPart, const std::vector &subNames, QPointF &placement) { + // Let's see, if we can help speed up the placement of the balloon: + // As of now we support: + // Single selected vertex: place the ballon tip end here + // Single selected edge: place the ballon tip at its midpoint (suggested placement for e.g. chamfer dimensions) + // + // Single selected faces are currently not supported, but maybe we could in this case use the center of mass? + if (subNames.size() != 1) { + // If nothing or more than one subjects are selected, let the user decide, where to place the balloon return false; } diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index 81654e5d04..a977ae0589 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -489,14 +489,11 @@ void QGVPage::createBalloon(QPointF origin, DrawViewPart *parent) std::string featName = getDrawPage()->getDocument()->getUniqueObjectName("Balloon"); std::string pageName = getDrawPage()->getNameInDocument(); - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon")); - TechDraw::DrawViewBalloon *balloon = 0; - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon")); Command::doCommand(Command::Doc, "App.activeDocument().addObject('TechDraw::DrawViewBalloon','%s')", featName.c_str()); Command::doCommand(Command::Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", pageName.c_str(), featName.c_str()); - balloon = dynamic_cast(getDrawPage()->getDocument()->getObject(featName.c_str())); + TechDraw::DrawViewBalloon *balloon = dynamic_cast(getDrawPage()->getDocument()->getObject(featName.c_str())); if (!balloon) { throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n"); } @@ -506,8 +503,8 @@ void QGVPage::createBalloon(QPointF origin, DrawViewPart *parent) Gui::Command::commitCommand(); - balloon->recomputeFeature(); parent->touch(true); + Gui::Command::updateActive(); } QGIView * QGVPage::addViewDimension(TechDraw::DrawViewDimension *dim) @@ -1264,21 +1261,24 @@ double QGVPage::getDevicePixelRatio() const { } QPixmap QGVPage::prepareCursorPixmap(const char *iconName, QPoint &hotspot) { - double cursorSize = 64.0; + double pixelRatio = getDevicePixelRatio(); - if (pixelRatio != 1.0) { - cursorSize = 32.0*pixelRatio; - } - + // Due to impossibility to query cursor size via Qt API, we stick to (32x32)*device_pixel_ratio + // as FreeCAD Wiki suggests - see https://wiki.freecadweb.org/HiDPI_support#Custom_cursor_size + double cursorSize = 32.0*pixelRatio; + QPixmap pixmap = Gui::BitmapFactory().pixmapFromSvg(iconName, QSizeF(cursorSize, cursorSize)); - if (pixelRatio == 1.0) { - pixmap = pixmap.scaled(32, 32); - hotspot /= 2; - } pixmap.setDevicePixelRatio(pixelRatio); + // The default (and here expected) SVG cursor graphics size is 64x64 pixels, thus we must adjust + // the 64x64 based hotspot position for our 32x32 based cursor pixmaps accordingly + hotspot /= 2; + #if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) + // On XCB platform, the pixmap device pixel ratio is not taken into account for cursor hot spot, + // therefore we must take care of the transformation ourselves... + // Refer to QTBUG-68571 - https://bugreports.qt.io/browse/QTBUG-68571 if (qGuiApp->platformName() == QLatin1String("xcb")) { hotspot *= pixelRatio; } From 302568d177ddde171c28eaca89e8b4a49466974f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 16:55:09 +0200 Subject: [PATCH 069/101] Part: copy ViewProviderPartExt::getNormals to Tools class --- src/Mod/Part/App/PreCompiled.h | 1 + src/Mod/Part/App/Tools.cpp | 87 ++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 3 ++ 3 files changed, 91 insertions(+) diff --git a/src/Mod/Part/App/PreCompiled.h b/src/Mod/Part/App/PreCompiled.h index bb9b1cb04f..636b5ea3cb 100644 --- a/src/Mod/Part/App/PreCompiled.h +++ b/src/Mod/Part/App/PreCompiled.h @@ -94,6 +94,7 @@ #include "OpenCascadeAll.h" #include #include +#include #elif defined(FC_OS_WIN32) #define WIN32_LEAN_AND_MEAN diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 41284befed..74664dfa50 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -33,11 +33,13 @@ # include # include # include +# include # include # include # include # include # include +# include # include # include # include @@ -47,6 +49,7 @@ # include # include # include +# include # if OCC_VERSION_HEX < 0x070600 # include # include @@ -414,3 +417,87 @@ void Part::Tools::getPointNormals(const std::vector& points, const TopoD vertexnormals[i].Normalize(); } } + +void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals) +{ + const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); + + if(aPolyTri->HasNormals()) + { + // normals pre-computed in triangulation structure + const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals(); + const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower())); + + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); + const gp_Dir aNorm(aNormArr[anId + 0], + aNormArr[anId + 1], + aNormArr[anId + 2]); + theNormals(aNodeIter) = aNorm; + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } + else { + // take in face the surface location + Poly_Connect thePolyConnect(aPolyTri); + const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3); + const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles(); + const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull() + ? &aPolyTri->UVNodes() + : nullptr; + Standard_Integer aTri[3]; + + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if (!aNodesUV || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan(0.0, 0.0, 0.0); + + for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord()); + const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + + if(aMod >= aTol) + { + eqPlan += vv / aMod; + } + } + + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); + } + + const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3; + aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X()); + aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y()); + aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z()); + } + + aPolyTri->SetNormals(aNormals); + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index a487530a7d..43a01123b7 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -151,6 +153,7 @@ public: * \param vertexnormals */ static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); + static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, TColgp_Array1OfDir& normals); }; } //namespace Part From f411390d33e9ab9b7eeb09736abb0cc36b4cbdc1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 17:45:59 +0200 Subject: [PATCH 070/101] PD: do not set ReferenceAxis when no profile is used to pad a face --- src/Mod/PartDesign/Gui/Command.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 83b13b9874..8a52a037c7 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -1257,7 +1258,10 @@ void CmdPartDesignPad::activated(int iMsg) Part::Part2DObject* sketch = dynamic_cast(profile); - FCMD_OBJ_CMD(Feat, "ReferenceAxis = (" << getObjectCmd(sketch) << ",['N_Axis'])"); + if (sketch) { + std::ostringstream str; + Gui::cmdAppObject(Feat, str << "ReferenceAxis = (" << getObjectCmd(sketch) << ",['N_Axis'])"); + } finishProfileBased(cmd, sketch, Feat); cmd->adjustCameraPosition(); From 0503f06930713345bf03dcda161ae0c23f681595 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 18:21:42 +0200 Subject: [PATCH 071/101] PD: do not enforce a reference axis when no profile is used to pad a face --- src/Mod/PartDesign/Gui/TaskPadParameters.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index e20d1b8624..fc4d95354c 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -775,7 +775,10 @@ void TaskPadParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector< int num = ui->directionCB->currentIndex(); const App::PropertyLinkSub& lnk = *(axesInList[num]); if (lnk.getValue() == 0) { - throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet"); + // Note: Is is possible that a face of an object is directly padded without defining a profile shape + obj = nullptr; + sub.clear(); + //throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet"); } else { PartDesign::ProfileBased* pcDirection = static_cast(vp->getObject()); From c2c5ae1bf0c571270ecacf257a51e9b064fc609a Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 19:34:48 +0200 Subject: [PATCH 072/101] Part: remove ViewProviderPartExt::getNormals --- src/Mod/Part/Gui/ViewProviderExt.cpp | 91 +------------------ src/Mod/Part/Gui/ViewProviderExt.h | 2 - src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp | 5 +- 3 files changed, 5 insertions(+), 93 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index ba197f1811..77cefbe3e0 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -125,6 +125,7 @@ #include #include +#include FC_LOG_LEVEL_INIT("Part", true, true) @@ -133,94 +134,6 @@ using namespace PartGui; PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject) -void ViewProviderPartExt::getNormals(const TopoDS_Face& theFace, - const Handle(Poly_Triangulation)& aPolyTri, - TColgp_Array1OfDir& theNormals) -{ - const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); - - if(aPolyTri->HasNormals()) - { - // normals pre-computed in triangulation structure - const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals(); - const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower())); - - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); - const gp_Dir aNorm(aNormArr[anId + 0], - aNormArr[anId + 1], - aNormArr[anId + 2]); - theNormals(aNodeIter) = aNorm; - } - - if(theFace.Orientation() == TopAbs_REVERSED) - { - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - theNormals.ChangeValue(aNodeIter).Reverse(); - } - } - - return; - } - - // take in face the surface location - Poly_Connect thePolyConnect(aPolyTri); - const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); - Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); - const Standard_Real aTol = Precision::Confusion(); - Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3); - const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles(); - const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull() - ? &aPolyTri->UVNodes() - : NULL; - Standard_Integer aTri[3]; - - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - // try to retrieve normal from real surface first, when UV coordinates are available - if(aNodesUV == NULL - || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1) - { - // compute flat normals - gp_XYZ eqPlan(0.0, 0.0, 0.0); - - for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) - { - aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); - const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord()); - const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord()); - const gp_XYZ vv = v1 ^ v2; - const Standard_Real aMod = vv.Modulus(); - - if(aMod >= aTol) - { - eqPlan += vv / aMod; - } - } - - const Standard_Real aModMax = eqPlan.Modulus(); - theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); - } - - const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3; - aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X()); - aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y()); - aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z()); - } - - aPolyTri->SetNormals(aNormals); - - if(theFace.Orientation() == TopAbs_REVERSED) - { - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - theNormals.ChangeValue(aNodeIter).Reverse(); - } - } -} - //************************************************************************** // Construction/Destruction @@ -1174,7 +1087,7 @@ void ViewProviderPartExt::updateVisual() const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); if (NormalsFromUV) - getNormals(actFace, mesh, Normals); + Part::Tools::getPointNormals(actFace, mesh, Normals); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index d890e9a716..2cb55c1873 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -158,8 +158,6 @@ protected: virtual void onChanged(const App::Property* prop) override; bool loadParameter(); void updateVisual(); - void getNormals(const TopoDS_Face& theFace, const Handle(Poly_Triangulation)& aPolyTri, - TColgp_Array1OfDir& theNormals); // nodes for the data representation SoMaterialBinding * pcFaceBind; diff --git a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp index 85bcf6e551..642eb9dc76 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp @@ -40,7 +40,8 @@ #endif #include "ViewProviderAddSub.h" -#include "Mod/Part/Gui/SoBrepFaceSet.h" +#include +#include #include #include #include @@ -196,7 +197,7 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); - getNormals(actFace, mesh, Normals); + Part::Tools::getPointNormals(actFace, mesh, Normals); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle From 5b4c246944c72459016efff6ae903ac66c090991 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 22:32:26 +0200 Subject: [PATCH 073/101] PD: simplify code to display rejected shape and move it to its own function --- .../Gui/ViewProviderTransformed.cpp | 280 ++++++++---------- .../PartDesign/Gui/ViewProviderTransformed.h | 3 + 2 files changed, 128 insertions(+), 155 deletions(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp index 0d402d0b71..0e3b7f0b06 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -198,162 +199,131 @@ void ViewProviderTransformed::recomputeFeature(bool recompute) } // Display the rejected transformations in red - if (rejected > 0) { - try { - // calculating the deflection value - Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; - { - Bnd_Box bounds; - BRepBndLib::Add(cShape, bounds); - bounds.SetGap(0.0); - bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - } - Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); - - // create or use the mesh on the data structure - // Note: This DOES have an effect on cShape -#if OCC_VERSION_HEX >= 0x060600 - Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; - BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, - AngDeflectionRads,Standard_True); -#else - BRepMesh_IncrementalMesh(cShape,deflection); -#endif - // We must reset the location here because the transformation data - // are set in the placement property - TopLoc_Location aLoc; - cShape.Location(aLoc); - - // count triangles and nodes in the mesh - int nbrTriangles=0, nbrNodes=0; - TopExp_Explorer Ex; - for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { - Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); - // Note: we must also count empty faces - if (!mesh.IsNull()) { - nbrTriangles += mesh->NbTriangles(); - nbrNodes += mesh->NbNodes(); - } - } - - // create memory for the nodes and indexes - SoCoordinate3* rejectedCoords = new SoCoordinate3(); - rejectedCoords ->point .setNum(nbrNodes); - SoNormal* rejectedNorms = new SoNormal(); - rejectedNorms ->vector .setNum(nbrNodes); - SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet(); - rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); - - // get the raw memory for fast fill up - SbVec3f* verts = rejectedCoords ->point .startEditing(); - SbVec3f* norms = rejectedNorms ->vector .startEditing(); - int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); - - // preset the normal vector with null vector - for (int i=0; i < nbrNodes; i++) - norms[i]= SbVec3f(0.0,0.0,0.0); - - int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; - for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { - TopLoc_Location aLoc; - const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); - // get the mesh of the shape - Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); - if (mesh.IsNull()) continue; - - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); - } - - // getting size of node and triangle array of this face - int nbNodesInFace = mesh->NbNodes(); - int nbTriInFace = mesh->NbTriangles(); - // check orientation - TopAbs_Orientation orient = actFace.Orientation(); - - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); - const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); - for (int g=1; g <= nbTriInFace; g++) { - // Get the triangle - Standard_Integer N1,N2,N3; - Triangles(g).Get(N1,N2,N3); - - // change orientation of the triangle if the face is reversed - if ( orient != TopAbs_FORWARD ) { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - // get the 3 points of this triangle - gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); - - // transform the vertices to the place of the face - if (!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - } - - // calculating per vertex normals - // Calculate triangle normal - gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); - gp_Vec Normal = (v2-v1)^(v3-v1); - - // add the triangle normal to the vertex normal for all points of this triangle - norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - - // set the vertices - verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); - verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); - verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); - - // set the index vector with the 3 point indexes and the end delimiter - index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; - index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; - index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; - index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; - } - - // counting up the per Face offsets - FaceNodeOffset += nbNodesInFace; - FaceTriaOffset += nbTriInFace; - - - // normalize all normals - for (int i=0; i < nbrNodes; i++) - norms[i].normalize(); - - // end the editing of the nodes - rejectedCoords ->point .finishEditing(); - rejectedNorms ->vector .finishEditing(); - rejectedFaceSet ->coordIndex .finishEditing(); - - // fill in the transformation matrices - SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); - - - rejectedTrfms->matrix.finishEditing(); - rejectedTrfms->addChild(rejectedFaceSet); - SoSeparator* sep = new SoSeparator(); - sep->addChild(rejectedCoords); - sep->addChild(rejectedNorms); - sep->addChild(rejectedTrfms); - pcRejectedRoot->addChild(sep); - } - } - catch (...) { - Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", - pcTransformed->getNameInDocument()); - } + showRejectedShape(cShape); } } +void ViewProviderTransformed::showRejectedShape(TopoDS_Shape shape) +{ + try { + // calculating the deflection value + Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; + { + Bnd_Box bounds; + BRepBndLib::Add(shape, bounds); + bounds.SetGap(0.0); + bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); + } + Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); + + // create or use the mesh on the data structure + // Note: This DOES have an effect on shape +#if OCC_VERSION_HEX >= 0x060600 + Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; + BRepMesh_IncrementalMesh(shape, deflection, Standard_False, AngDeflectionRads, Standard_True); +#else + BRepMesh_IncrementalMesh(shape, deflection); +#endif + // We must reset the location here because the transformation data + // are set in the placement property + TopLoc_Location aLoc; + shape.Location(aLoc); + + // count triangles and nodes in the mesh + int nbrTriangles=0, nbrNodes=0; + TopExp_Explorer Ex; + for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next()) { + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); + // Note: we must also count empty faces + if (!mesh.IsNull()) { + nbrTriangles += mesh->NbTriangles(); + nbrNodes += mesh->NbNodes(); + } + } + + // create memory for the nodes and indexes + SoCoordinate3* rejectedCoords = new SoCoordinate3(); + rejectedCoords ->point .setNum(nbrNodes); + SoNormal* rejectedNorms = new SoNormal(); + rejectedNorms ->vector .setNum(nbrNodes); + SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet(); + rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); + + // get the raw memory for fast fill up + SbVec3f* verts = rejectedCoords ->point .startEditing(); + SbVec3f* norms = rejectedNorms ->vector .startEditing(); + int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); + + // preset the normal vector with null vector + for (int i=0; i < nbrNodes; i++) + norms[i]= SbVec3f(0.0,0.0,0.0); + + int FaceNodeOffset=0,FaceTriaOffset=0; + for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next()) { + const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); + + // get triangulation + std::vector points; + std::vector facets; + if (!Part::Tools::getTriangulation(actFace, points, facets)) + continue; + + // get normal per vertex + std::vector vertexnormals; + Part::Tools::getPointNormals(points, facets, vertexnormals); + + // getting size of node and triangle array of this face + std::size_t nbNodesInFace = points.size(); + std::size_t nbTriInFace = facets.size(); + + for (std::size_t i = 0; i < points.size(); i++) { + verts[FaceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z()); + } + + for (std::size_t i = 0; i < vertexnormals.size(); i++) { + norms[FaceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z()); + } + + // cycling through the poly mesh + for (std::size_t g=0; g < nbTriInFace; g++) { + // Get the triangle + Standard_Integer N1,N2,N3; + facets[g].Get(N1,N2,N3); + + // set the index vector with the 3 point indexes and the end delimiter + index[FaceTriaOffset*4+4*g] = FaceNodeOffset+N1; + index[FaceTriaOffset*4+4*g+1] = FaceNodeOffset+N2; + index[FaceTriaOffset*4+4*g+2] = FaceNodeOffset+N3; + index[FaceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX; + } + + // counting up the per Face offsets + FaceNodeOffset += nbNodesInFace; + FaceTriaOffset += nbTriInFace; + + // normalize all normals + for (int i=0; i < nbrNodes; i++) + norms[i].normalize(); + + // end the editing of the nodes + rejectedCoords ->point .finishEditing(); + rejectedNorms ->vector .finishEditing(); + rejectedFaceSet ->coordIndex .finishEditing(); + + // fill in the transformation matrices + SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); + rejectedTrfms->matrix.finishEditing(); + rejectedTrfms->addChild(rejectedFaceSet); + SoSeparator* sep = new SoSeparator(); + sep->addChild(rejectedCoords); + sep->addChild(rejectedNorms); + sep->addChild(rejectedTrfms); + pcRejectedRoot->addChild(sep); + } + } + catch (...) { + Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", + getObject()->getNameInDocument()); + } +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h index 50a72ca1ae..ec4b8e1226 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h @@ -68,6 +68,9 @@ protected: public: void recomputeFeature(bool recompute=true); QString getMessage() const {return diagMessage;} + +private: + void showRejectedShape(TopoDS_Shape shape); }; From b485155c33bb81f743053b300f88dddc2df534c4 Mon Sep 17 00:00:00 2001 From: Tomas Pavlicek Date: Sat, 9 Oct 2021 00:30:28 +0200 Subject: [PATCH 074/101] TechDraw - Balloon updates - improve hospot calculation --- src/Mod/TechDraw/Gui/QGVPage.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index a977ae0589..903f9354fc 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -1262,6 +1262,7 @@ double QGVPage::getDevicePixelRatio() const { QPixmap QGVPage::prepareCursorPixmap(const char *iconName, QPoint &hotspot) { + QPointF floatHotspot(hotspot); double pixelRatio = getDevicePixelRatio(); // Due to impossibility to query cursor size via Qt API, we stick to (32x32)*device_pixel_ratio @@ -1273,17 +1274,18 @@ QPixmap QGVPage::prepareCursorPixmap(const char *iconName, QPoint &hotspot) { // The default (and here expected) SVG cursor graphics size is 64x64 pixels, thus we must adjust // the 64x64 based hotspot position for our 32x32 based cursor pixmaps accordingly - hotspot /= 2; + floatHotspot *= 0.5; #if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) // On XCB platform, the pixmap device pixel ratio is not taken into account for cursor hot spot, // therefore we must take care of the transformation ourselves... // Refer to QTBUG-68571 - https://bugreports.qt.io/browse/QTBUG-68571 if (qGuiApp->platformName() == QLatin1String("xcb")) { - hotspot *= pixelRatio; + floatHotspot *= pixelRatio; } #endif + hotspot = floatHotspot.toPoint(); return pixmap; } From beea1d364477424e4f24d9411f9ba36f61f849af Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Sat, 9 Oct 2021 15:53:51 +0800 Subject: [PATCH 075/101] Import: fix single shape STEP export with per face color --- src/Mod/Import/App/ImportOCAF2.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index f997187f36..3b0d6ea49a 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -1244,8 +1244,17 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, // not call setupObject() on a non-located baseshape like above, // because OCCT does not respect shape style sharing when not // exporting assembly - if(!keepPlacement) + if(!keepPlacement || shape.getPlacement() == Base::Placement()) shape.setShape(shape.getShape().Located(TopLoc_Location())); + else { + Base::Matrix4D mat = shape.getTransform(); + shape.setShape(shape.getShape().Located(TopLoc_Location())); + // Transform with copy to conceal the transformation + shape.transformShape(mat, true); + // Even if the shape has no transformation, TopoShape still sets + // a TopLoc_Location, so we need to clear it again. + shape.setShape(shape.getShape().Located(TopLoc_Location())); + } label = aShapeTool->AddShape(shape.getShape(),Standard_False, Standard_False); auto o = name?parentObj:obj; if(o!=linked) From f271aa9ff6af562d62da56bcd2e5685dc5a1f926 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 9 Oct 2021 10:17:07 +0200 Subject: [PATCH 076/101] Draft: make_ellipse default value face should be None --- src/Mod/Draft/draftmake/make_ellipse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftmake/make_ellipse.py b/src/Mod/Draft/draftmake/make_ellipse.py index bb169f24ee..3a277dcd38 100644 --- a/src/Mod/Draft/draftmake/make_ellipse.py +++ b/src/Mod/Draft/draftmake/make_ellipse.py @@ -36,7 +36,7 @@ if App.GuiUp: from draftviewproviders.view_base import ViewProviderDraft -def make_ellipse(majradius, minradius, placement=None, face=True, support=None): +def make_ellipse(majradius, minradius, placement=None, face=None, support=None): """make_ellipse(majradius, minradius, [placement], [face], [support]) Makes an ellipse with the given major and minor radius, and optionally From 4cce7b4236756bae3c77ab740b76ed2141b228eb Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 9 Oct 2021 10:25:11 +0200 Subject: [PATCH 077/101] Draft: Tweak gridShowHuman tooltip --- src/Mod/Draft/Resources/ui/preferences-draftsnap.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui b/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui index 983afad5ac..b4c44cd836 100644 --- a/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui +++ b/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui @@ -335,7 +335,7 @@ - <html><head/><body><p>If checked, a human figure silhouette is displayed at the grid center. This option is only effective if the BIM workbench is installed and if &quot;Show grid border&quot; option is enabled.</p></body></html> + <html><head/><body><p>If checked, the outline of a human figure is displayed at the bottom left corner of the grid. This option is only effective if the BIM workbench is installed and if &quot;Show grid border&quot; option is enabled.</p></body></html> Show human figure From 66d3dd897f63c2e4f8ffd6eced730c6a3372ad51 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 11:37:18 +0200 Subject: [PATCH 078/101] Part: add convenience function to convert TColgp_Array1OfDir to std::vector --- src/Mod/Part/App/Tools.cpp | 88 ++++++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 23 ++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 74664dfa50..0a85e0c6df 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -420,6 +420,7 @@ void Part::Tools::getPointNormals(const std::vector& points, const TopoD void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals) { +#if OCC_VERSION_HEX < 0x070600 const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); if(aPolyTri->HasNormals()) @@ -500,4 +501,91 @@ void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triang } } } +#else + Standard_Integer numNodes = aPolyTri->NbNodes(); + + if(aPolyTri->HasNormals()) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals(aNodeIter) = aPolyTri->Normal(aNodeIter); + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } + else { + // take in face the surface location + Poly_Connect thePolyConnect(aPolyTri); + const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull(); + Standard_Integer aTri[3]; + + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if (!hasNodesUV || GeomLib::NormEstim(aSurf, aPolyTri->UVNode(aNodeIter), aTol, theNormals(aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan(0.0, 0.0, 0.0); + + for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aPolyTri->Triangle(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1(aPolyTri->Node(aTri[1]).Coord() - aPolyTri->Node(aTri[0]).Coord()); + const gp_XYZ v2(aPolyTri->Node(aTri[2]).Coord() - aPolyTri->Node(aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + + if(aMod >= aTol) + { + eqPlan += vv / aMod; + } + } + + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); + } + + aPolyTri->SetNormal(aNodeIter, theNormals(aNodeIter)); + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } +#endif +} + +void Part::Tools::getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector& normals) +{ + TColgp_Array1OfDir dirs (1, aPoly->NbNodes()); + getPointNormals(face, aPoly, dirs); + normals.reserve(aPoly->NbNodes()); + + for (int i = dirs.Lower(); i <= dirs.Upper(); ++i) { + normals.emplace_back(dirs(i).XYZ()); + } +} + +void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals) +{ + if (!loc.IsIdentity()) { + gp_Trsf myTransf = loc.Transformation(); + + for (auto& it : normals) { + it.Transform(myTransf); + } + } } diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 43a01123b7..425032a12d 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,29 @@ public: * \param vertexnormals */ static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); + /*! + * \brief getPointNormals + * Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes. + * \param face + * \param aPoly + * \param vertexnormals + */ static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, TColgp_Array1OfDir& normals); + /*! + * \brief getPointNormals + * Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes. + * \param face + * \param aPoly + * \param vertexnormals + */ + static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector& normals); + /*! + * \brief applyTransformationOnNormals + * Apply the transformation to the vectors + * \param loc + * \param normals + */ + static void applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals); }; } //namespace Part From f628050732cc5d1d49fc18282ed508ca3061bb10 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 11:38:25 +0200 Subject: [PATCH 079/101] PD: simplify code to display add/sub shape --- src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp | 109 ++++++------------ 1 file changed, 38 insertions(+), 71 deletions(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp index 642eb9dc76..2e2d2a55e5 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp @@ -116,9 +116,6 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { return; } - int numTriangles=0,numNodes=0,numNorms=0,numFaces=0; - std::set faceEdges; - try { // calculating the deflection value Bnd_Box bounds; @@ -126,16 +123,14 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * - Deviation.getValue(); + Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure #if OCC_VERSION_HEX >= 0x060600 Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; - BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, - AngDeflectionRads,Standard_True); + BRepMesh_IncrementalMesh(cShape, deflection, Standard_False, AngDeflectionRads, Standard_True); #else - BRepMesh_IncrementalMesh(cShape,deflection); + BRepMesh_IncrementalMesh(cShape, deflection); #endif // We must reset the location here because the transformation data // are set in the placement property @@ -143,6 +138,7 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { cShape.Location(aLoc); // count triangles and nodes in the mesh + int numTriangles=0,numNodes=0,numNorms=0,numFaces=0; TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); @@ -160,11 +156,12 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { previewNorm ->vector .setNum(numNorms); previewFaceSet ->coordIndex .setNum(numTriangles*4); previewFaceSet ->partIndex .setNum(numFaces); + // get the raw memory for fast fill up - SbVec3f* verts = previewCoords ->point .startEditing(); - SbVec3f* previewNorms = previewNorm ->vector .startEditing(); - int32_t* index = previewFaceSet ->coordIndex .startEditing(); - int32_t* parts = previewFaceSet ->partIndex .startEditing(); + SbVec3f* verts = previewCoords ->point .startEditing(); + SbVec3f* previewNorms = previewNorm ->vector .startEditing(); + int32_t* index = previewFaceSet ->coordIndex .startEditing(); + int32_t* parts = previewFaceSet ->partIndex .startEditing(); // preset the previewNormal vector with null vector for (int i=0;i < numNorms;i++) @@ -172,76 +169,46 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { int ii = 0,faceNodeOffset=0,faceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { - TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); - // get the mesh of the shape - Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); - if (mesh.IsNull()) continue; - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); - } + TopLoc_Location loc; + Handle(Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace, loc); + if (mesh.IsNull()) + continue; + + // get triangulation + std::vector points; + std::vector facets; + Part::Tools::getTriangulation(actFace, points, facets); + + // get normal per vertex + std::vector vertexnormals; + Part::Tools::getPointNormals(actFace, mesh, vertexnormals); + Part::Tools::applyTransformationOnNormals(loc, vertexnormals); // getting size of node and triangle array of this face - int nbNodesInFace = mesh->NbNodes(); - int nbTriInFace = mesh->NbTriangles(); - // check orientation - TopAbs_Orientation orient = actFace.Orientation(); + std::size_t nbNodesInFace = points.size(); + std::size_t nbTriInFace = facets.size(); + for (std::size_t i = 0; i < points.size(); i++) { + verts[faceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z()); + } + + for (std::size_t i = 0; i < vertexnormals.size(); i++) { + previewNorms[faceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z()); + } // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); - const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); - TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); - Part::Tools::getPointNormals(actFace, mesh, Normals); - - for (int g=1;g<=nbTriInFace;g++) { + for (std::size_t g=0; g < nbTriInFace; g++) { // Get the triangle Standard_Integer N1,N2,N3; - Triangles(g).Get(N1,N2,N3); - - // change orientation of the triangle if the face is reversed - if ( orient != TopAbs_FORWARD ) { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - // get the 3 points of this triangle - gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); - - // get the 3 previewNormals of this triangle - gp_Dir NV1(Normals(N1)), NV2(Normals(N2)), NV3(Normals(N3)); - - // transform the vertices and previewNormals to the place of the face - if(!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - NV1.Transform(myTransf); - NV2.Transform(myTransf); - NV3.Transform(myTransf); - } - - // add the previewNormals for all points of this triangle - previewNorms[faceNodeOffset+N1-1] += SbVec3f(NV1.X(),NV1.Y(),NV1.Z()); - previewNorms[faceNodeOffset+N2-1] += SbVec3f(NV2.X(),NV2.Y(),NV2.Z()); - previewNorms[faceNodeOffset+N3-1] += SbVec3f(NV3.X(),NV3.Y(),NV3.Z()); - - // set the vertices - verts[faceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); - verts[faceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); - verts[faceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); + facets[g].Get(N1,N2,N3); // set the index vector with the 3 point indexes and the end delimiter - index[faceTriaOffset*4+4*(g-1)] = faceNodeOffset+N1-1; - index[faceTriaOffset*4+4*(g-1)+1] = faceNodeOffset+N2-1; - index[faceTriaOffset*4+4*(g-1)+2] = faceNodeOffset+N3-1; - index[faceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; + index[faceTriaOffset*4+4*g] = faceNodeOffset+N1; + index[faceTriaOffset*4+4*g+1] = faceNodeOffset+N2; + index[faceTriaOffset*4+4*g+2] = faceNodeOffset+N3; + index[faceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX; } parts[ii] = nbTriInFace; // new part From 74639da997d5f2e53f001d9f256be86ceee901f5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 13:49:02 +0200 Subject: [PATCH 080/101] OCCT: port FreeCAD sources to version 7.6 SMESH is not yet ported Although FreeCAD code compiles with OCCT 7.6 it doesn't work at the moment --- src/Mod/Drawing/App/DrawingExport.cpp | 11 ++- src/Mod/Drawing/App/ProjectionAlgos.cpp | 3 - src/Mod/Import/App/ImpExpDxf.cpp | 9 +- .../App/GeomPlate/CurveConstraintPyImp.cpp | 41 +++++++++- src/Mod/Part/App/Geometry.cpp | 7 +- src/Mod/Part/App/PartFeatures.cpp | 22 ++--- src/Mod/Part/App/TopoShape.cpp | 82 ++++++------------- src/Mod/Part/App/TopoShapeFacePyImp.cpp | 10 +++ src/Mod/Part/App/TopoShapeWirePyImp.cpp | 6 +- src/Mod/Part/Gui/TaskCheckGeometry.cpp | 6 +- src/Mod/Part/Gui/ViewProviderExt.cpp | 17 ++++ src/Mod/Path/App/AppPathPy.cpp | 5 +- src/Mod/TechDraw/App/Geometry.cpp | 12 ++- 13 files changed, 138 insertions(+), 93 deletions(-) diff --git a/src/Mod/Drawing/App/DrawingExport.cpp b/src/Mod/Drawing/App/DrawingExport.cpp index b87891ed50..7572be417c 100644 --- a/src/Mod/Drawing/App/DrawingExport.cpp +++ b/src/Mod/Drawing/App/DrawingExport.cpp @@ -64,10 +64,7 @@ #include #include -#include #include -#include -#include #include #include #include @@ -75,11 +72,19 @@ #include #include #include +#include +#if OCC_VERSION_HEX < 0x070600 +#include +#endif #include "DrawingExport.h" #include #include +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + using namespace Drawing; using namespace std; diff --git a/src/Mod/Drawing/App/ProjectionAlgos.cpp b/src/Mod/Drawing/App/ProjectionAlgos.cpp index 9afae7e9c0..da03d49057 100644 --- a/src/Mod/Drawing/App/ProjectionAlgos.cpp +++ b/src/Mod/Drawing/App/ProjectionAlgos.cpp @@ -61,10 +61,7 @@ #include #include #include -#include #include -#include -#include #include #include #include diff --git a/src/Mod/Import/App/ImpExpDxf.cpp b/src/Mod/Import/App/ImpExpDxf.cpp index 09827bd928..dcd88ef138 100644 --- a/src/Mod/Import/App/ImpExpDxf.cpp +++ b/src/Mod/Import/App/ImpExpDxf.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +55,9 @@ #include #include #include +#if OCC_VERSION_HEX < 0x070600 +#include +#endif #include #include @@ -68,6 +71,10 @@ using namespace Import; +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + //****************************************************************************** // reading diff --git a/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp b/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp index 3271f3651a..b63227d537 100644 --- a/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp +++ b/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp @@ -24,10 +24,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include -# include # include -# include # include +# include +# if OCC_VERSION_HEX < 0x070600 +# include +# include +# endif #endif #include "GeomPlate/CurveConstraintPy.h" @@ -76,6 +79,16 @@ int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds) return -1; } +#if OCC_VERSION_HEX >= 0x070600 + Handle(Adaptor3d_Curve) hCurve; + if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) { + GeomTrimmedCurve* trim = static_cast(curve); + hCurve = new GeomAdaptor_Curve(handle, trim->getFirstParameter(), trim->getLastParameter()); + } + else { + hCurve = new GeomAdaptor_Curve(handle); + } +#else Handle(Adaptor3d_HCurve) hCurve; if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) { GeomTrimmedCurve* trim = static_cast(curve); @@ -86,6 +99,7 @@ int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds) GeomAdaptor_Curve adapt(handle); hCurve = new GeomAdaptor_HCurve(adapt); } +#endif ptr.reset(new GeomPlate_CurveConstraint(hCurve, order, nbPts, tolDist, tolAng, tolCurv)); } @@ -212,11 +226,15 @@ PyObject* CurveConstraintPy::curve3d(PyObject *args) return nullptr; try { - Handle(Adaptor3d_HCurve) hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d(); + auto hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d(); if (hAdapt.IsNull()) Py_Return; +#if OCC_VERSION_HEX >= 0x070600 + const Adaptor3d_Curve& a3d = *hAdapt; +#else const Adaptor3d_Curve& a3d = hAdapt->Curve(); +#endif std::unique_ptr ptr(Part::makeFromCurveAdaptor(a3d)); return ptr->getPyObject(); } @@ -282,6 +300,16 @@ PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args) return nullptr; } +#if OCC_VERSION_HEX >= 0x070600 + Handle(Adaptor2d_Curve2d) hCurve; + if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { + Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle)); + hCurve = new Geom2dAdaptor_Curve(handle, aTC->FirstParameter(), aTC->LastParameter()); + } + else { + hCurve = new Geom2dAdaptor_Curve(handle); + } +#else Handle(Adaptor2d_HCurve2d) hCurve; if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle)); @@ -292,6 +320,7 @@ PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args) Geom2dAdaptor_Curve adapt(handle); hCurve = new Geom2dAdaptor_HCurve(adapt); } +#endif getGeomPlate_CurveConstraintPtr()->SetProjectedCurve(hCurve, tolU, tolV); Py_Return; @@ -308,11 +337,15 @@ PyObject* CurveConstraintPy::projectedCurve(PyObject *args) return nullptr; try { - Handle(Adaptor2d_HCurve2d) hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve(); + auto hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve(); if (hAdapt.IsNull()) Py_Return; +#if OCC_VERSION_HEX >= 0x070600 + const Adaptor2d_Curve2d& a2d = *hAdapt; +#else const Adaptor2d_Curve2d& a2d = hAdapt->Curve2d(); +#endif std::unique_ptr ptr(Part::makeFromCurveAdaptor2d(a2d)); return ptr->getPyObject(); } diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index e6d6396ca9..1d1d67d4f0 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -51,7 +51,6 @@ # include # include # include -# include # include # include # include @@ -101,6 +100,9 @@ # include # include # include +# if OCC_VERSION_HEX < 0x070600 +# include +# endif # include # include @@ -144,6 +146,9 @@ #include "Geometry.h" +#if OCC_VERSION_HEX >= 0x070600 +using GeomAdaptor_HCurve = GeomAdaptor_Curve; +#endif using namespace Part; diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index 2dc503bdf2..4d9e1fc0f9 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -25,9 +25,7 @@ #ifndef _PreComp_ # include # include -# include # include -# include # include # include # include @@ -43,7 +41,7 @@ # include # include # include -# include +# include #endif @@ -170,22 +168,18 @@ App::DocumentObjectExecReturn *RuledSurface::execute(void) if (Orientation.getValue() == 0) { // Automatic - Handle(Adaptor3d_HCurve) a1; - Handle(Adaptor3d_HCurve) a2; + std::unique_ptr a1; + std::unique_ptr a2; if (!isWire) { - BRepAdaptor_Curve adapt1(TopoDS::Edge(S1)); - BRepAdaptor_Curve adapt2(TopoDS::Edge(S2)); - a1 = new BRepAdaptor_HCurve(adapt1); - a2 = new BRepAdaptor_HCurve(adapt2); + a1 = std::make_unique(TopoDS::Edge(S1)); + a2 = std::make_unique(TopoDS::Edge(S2)); } else { - BRepAdaptor_CompCurve adapt1(TopoDS::Wire(S1)); - BRepAdaptor_CompCurve adapt2(TopoDS::Wire(S2)); - a1 = new BRepAdaptor_HCompCurve(adapt1); - a2 = new BRepAdaptor_HCompCurve(adapt2); + a1 = std::make_unique(TopoDS::Wire(S1)); + a2 = std::make_unique(TopoDS::Wire(S2)); } - if (!a1.IsNull() && !a2.IsNull()) { + if (a1 && a2) { // get end points of 1st curve Standard_Real first, last; first = a1->FirstParameter(); diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 05341de3d6..b7617a3943 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -38,8 +38,6 @@ # include # include # include -# include -# include # include # include # include @@ -186,6 +184,12 @@ #if OCC_VERSION_HEX >= 0x070300 # include #endif + +#if OCC_VERSION_HEX < 0x070600 +# include +# include +#endif + #endif // _PreComp_ #include @@ -2133,12 +2137,20 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdeg if (this->_Shape.IsNull()) Standard_Failure::Raise("Cannot sweep along empty spine"); +#if OCC_VERSION_HEX >= 0x070600 + Handle(Adaptor3d_Curve) myPath; + if (this->_Shape.ShapeType() == TopAbs_EDGE) { + const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); + myPath = new BRepAdaptor_Curve(path_edge); + } +#else Handle(Adaptor3d_HCurve) myPath; if (this->_Shape.ShapeType() == TopAbs_EDGE) { const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); BRepAdaptor_Curve path_adapt(path_edge); myPath = new BRepAdaptor_HCurve(path_adapt); } +#endif //else if (this->_Shape.ShapeType() == TopAbs_WIRE) { // const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape); // BRepAdaptor_CompCurve path_adapt(path_wire); @@ -3777,72 +3789,32 @@ void TopoShape::getLinesFromSubElement(const Data::Segment* element, for(TopExp_Explorer exp(shape,TopAbs_EDGE);exp.More();exp.Next()) { TopoDS_Edge aEdge = TopoDS::Edge(exp.Current()); - TopLoc_Location aLoc; - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); + std::vector points; - gp_Trsf myTransf; - Standard_Integer nbNodesInFace; - - auto line_start = vertices.size(); - - // triangulation succeeded? - if (!aPoly.IsNull()) { - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - nbNodesInFace = aPoly->NbNodes(); - - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - - gp_Pnt V; - for (Standard_Integer i=0;i < nbNodesInFace;i++) { - V = Nodes(i+1); - V.Transform(myTransf); - vertices.emplace_back(V.X(),V.Y(),V.Z()); - } - } - else { + if (!Tools::getPolygon3D(aEdge, points)) { // the edge has not its own triangulation, but then a face the edge is attached to // must provide this triangulation // Look for one face in our map (it doesn't care which one we take) int index = edge2Face.FindIndex(aEdge); - if(!index) + if (index < 1) continue; const auto &faces = edge2Face.FindFromIndex(index); - if(!faces.Extent()) + if (faces.Extent() == 0) continue; const TopoDS_Face& aFace = TopoDS::Face(faces.First()); - // take the face's triangulation instead - Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc); - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - - if (aPolyTria.IsNull()) break; - - // this holds the indices of the edge's triangulation to the actual points - Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc); - if (aPoly.IsNull()) - continue; // polygon does not exist - - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - - const TColStd_Array1OfInteger& indices = aPoly->Nodes(); - const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes(); - - gp_Pnt V; - // go through the index array - for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { - V = Nodes(indices(i)); - V.Transform(myTransf); - vertices.emplace_back(V.X(),V.Y(),V.Z()); - } + if (!Part::Tools::getPolygonOnTriangulation(aEdge, aFace, points)) + continue; } - if(line_start+1 < vertices.size()) { + auto line_start = vertices.size(); + vertices.reserve(vertices.size() + points.size()); + std::for_each(points.begin(), points.end(), [&vertices](const gp_Pnt& p) { + vertices.push_back(Base::convertTo(p)); + }); + + if (line_start+1 < vertices.size()) { lines.emplace_back(); lines.back().I1 = line_start; lines.back().I2 = vertices.size()-1; diff --git a/src/Mod/Part/App/TopoShapeFacePyImp.cpp b/src/Mod/Part/App/TopoShapeFacePyImp.cpp index ea6cd98bdf..63e8bead74 100644 --- a/src/Mod/Part/App/TopoShapeFacePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeFacePyImp.cpp @@ -493,6 +493,15 @@ PyObject* TopoShapeFacePy::getUVNodes(PyObject *args) return Py::new_reference_to(list); } +#if OCC_VERSION_HEX >= 0x070600 + for (int i=1; i<=mesh->NbNodes(); i++) { + gp_Pnt2d pt2d = mesh->UVNode(i); + Py::Tuple uv(2); + uv.setItem(0, Py::Float(pt2d.X())); + uv.setItem(1, Py::Float(pt2d.Y())); + list.append(uv); + } +#else const TColgp_Array1OfPnt2d& aNodesUV = mesh->UVNodes(); for (int i=aNodesUV.Lower(); i<=aNodesUV.Upper(); i++) { gp_Pnt2d pt2d = aNodesUV(i); @@ -501,6 +510,7 @@ PyObject* TopoShapeFacePy::getUVNodes(PyObject *args) uv.setItem(1, Py::Float(pt2d.Y())); list.append(uv); } +#endif return Py::new_reference_to(list); } diff --git a/src/Mod/Part/App/TopoShapeWirePyImp.cpp b/src/Mod/Part/App/TopoShapeWirePyImp.cpp index 95c1aff681..a1f32d6d03 100644 --- a/src/Mod/Part/App/TopoShapeWirePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeWirePyImp.cpp @@ -344,9 +344,9 @@ PyObject* TopoShapeWirePy::approximate(PyObject *args, PyObject *kwds) return 0; try { BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->getShape())); - Handle(Adaptor3d_HCurve) hcurve = adapt.Trim(adapt.FirstParameter(), - adapt.LastParameter(), - tol2d); + auto hcurve = adapt.Trim(adapt.FirstParameter(), + adapt.LastParameter(), + tol2d); Approx_Curve3d approx(hcurve, tol3d, GeomAbs_C0, maxseg, maxdeg); if (approx.IsDone()) { return new BSplineCurvePy(new GeomBSplineCurve(approx.Curve())); diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.cpp b/src/Mod/Part/Gui/TaskCheckGeometry.cpp index 5de7c16920..aaef13d9d0 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.cpp +++ b/src/Mod/Part/Gui/TaskCheckGeometry.cpp @@ -711,8 +711,10 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu #if OCC_VERSION_HEX >= 0x060900 #if OCC_VERSION_HEX < 0x070500 BOPCheck.SetProgressIndicator(theProgress); -#else +#elif OCC_VERSION_HEX < 0x070600 BOPCheck.SetProgressIndicator(theScope); +#else + Q_UNUSED(theScope) #endif // 0x070500 #else Q_UNUSED(theProgress); @@ -740,7 +742,7 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu Base::TimeInfo start_time; #endif -BOPCheck.Perform(); + BOPCheck.Perform(); #ifdef FC_DEBUG float bopAlgoTime = Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo()); diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 77cefbe3e0..8a52f1701b 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -1083,16 +1083,25 @@ void ViewProviderPartExt::updateVisual() // cycling through the poly mesh +#if OCC_VERSION_HEX < 0x070600 const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); +#else + int numNodes = mesh->NbNodes(); + TColgp_Array1OfDir Normals (1, numNodes); +#endif if (NormalsFromUV) Part::Tools::getPointNormals(actFace, mesh, Normals); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle Standard_Integer N1,N2,N3; +#if OCC_VERSION_HEX < 0x070600 Triangles(g).Get(N1,N2,N3); +#else + mesh->Triangle(g).Get(N1,N2,N3); +#endif // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { @@ -1102,7 +1111,11 @@ void ViewProviderPartExt::updateVisual() } // get the 3 points of this triangle +#if OCC_VERSION_HEX < 0x070600 gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); +#else + gp_Pnt V1(mesh->Node(N1)), V2(mesh->Node(N2)), V3(mesh->Node(N3)); +#endif // get the 3 normals of this triangle gp_Vec NV1, NV2, NV3; @@ -1179,7 +1192,11 @@ void ViewProviderPartExt::updateVisual() // rare cases where some points are only referenced by the polygon // but not by any triangle. Thus, we must apply the coordinates to // make sure that everything is properly set. +#if OCC_VERSION_HEX < 0x070600 gp_Pnt p(Nodes(nodeIndex)); +#else + gp_Pnt p(mesh->Node(nodeIndex)); +#endif if (!identity) p.Transform(myTransf); verts[index].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z())); diff --git a/src/Mod/Path/App/AppPathPy.cpp b/src/Mod/Path/App/AppPathPy.cpp index 6e0c72d2f5..ce912b4474 100644 --- a/src/Mod/Path/App/AppPathPy.cpp +++ b/src/Mod/Path/App/AppPathPy.cpp @@ -49,10 +49,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "CommandPy.h" #include "PathPy.h" diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index b6c3637137..59a92d7e51 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -28,13 +28,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -58,14 +58,16 @@ #include #include #include +#include #include #include #include #include #include #include -#include - +#if OCC_VERSION_HEX < 0x070600 +#include +#endif #include #endif // #ifndef _PreComp_ @@ -86,6 +88,10 @@ using namespace TechDraw; using namespace std; +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + #define GEOMETRYEDGE 0 #define COSMETICEDGE 1 #define CENTERLINE 2 From 03be15cc6b460ab62548142287eb9f677f463a44 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 14:34:04 +0200 Subject: [PATCH 081/101] Part: fix bug in Part::Tools::getPointNormals for OCCT 7.6 --- src/Mod/Part/App/Tools.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 0a85e0c6df..d95e49eaf4 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -528,6 +528,7 @@ void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triang Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull(); Standard_Integer aTri[3]; + aPolyTri->AddNormals(); for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) { // try to retrieve normal from real surface first, when UV coordinates are available From c01878c174ad7548996a4ec78f67d96bf3836263 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Sat, 9 Oct 2021 20:43:24 +0800 Subject: [PATCH 082/101] Import: fix transparency STEP export/import App::Color::a in FreeCAD is actually interpreted as transparency instead of alpha. --- src/Mod/Import/App/ExportOCAF.cpp | 2 +- src/Mod/Import/App/ImportOCAF.cpp | 2 +- src/Mod/Import/App/ImportOCAF2.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Mod/Import/App/ExportOCAF.cpp b/src/Mod/Import/App/ExportOCAF.cpp index 9ba1a4d0ae..3a76769b42 100644 --- a/src/Mod/Import/App/ExportOCAF.cpp +++ b/src/Mod/Import/App/ExportOCAF.cpp @@ -104,7 +104,7 @@ static inline Quantity_ColorRGBA convertColor(const App::Color &c) { - return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), c.a); + return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), 1.0 - c.a); } using namespace Import; diff --git a/src/Mod/Import/App/ImportOCAF.cpp b/src/Mod/Import/App/ImportOCAF.cpp index f92e7300b3..a6c392f0b7 100644 --- a/src/Mod/Import/App/ImportOCAF.cpp +++ b/src/Mod/Import/App/ImportOCAF.cpp @@ -122,7 +122,7 @@ static inline App::Color convertColor(const Quantity_ColorRGBA &c) return App::Color(static_cast(r), static_cast(g), static_cast(b), - static_cast(c.Alpha())); + 1.0f - static_cast(c.Alpha())); } #define OCAF_KEEP_PLACEMENT diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index 3b0d6ea49a..1c803be05c 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -92,12 +92,12 @@ static inline App::Color convertColor(const Quantity_ColorRGBA &c) return App::Color(static_cast(r), static_cast(g), static_cast(b), - static_cast(c.Alpha())); + 1.0f - static_cast(c.Alpha())); } static inline Quantity_ColorRGBA convertColor(const App::Color &c) { - return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), c.a); + return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), 1.0f - c.a); } static inline std::ostream& operator<<(std::ostream& os, const Quantity_ColorRGBA &c) { From b1c3982391e00ef7f943ae023f8cbad6f4a6ec4c Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 15:17:24 +0200 Subject: [PATCH 083/101] Gui: [skip ci] reformat code --- src/Gui/MainWindow.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 05801cbeb5..488175861a 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -633,24 +633,27 @@ bool MainWindow::closeAllDocuments (bool close) auto docs = App::GetApplication().getDocuments(); try { docs = App::Document::getDependentDocuments(docs, true); - }catch(Base::Exception &e) { + } + catch(Base::Exception &e) { e.ReportException(); } + bool checkModify = true; bool saveAll = false; int failedSaves = 0; - for(auto doc : docs) { + + for (auto doc : docs) { auto gdoc = Application::Instance->getDocument(doc); - if(!gdoc) + if (!gdoc) continue; - if(!gdoc->canClose(false)) + if (!gdoc->canClose(false)) return false; - if(!gdoc->isModified() + if (!gdoc->isModified() || doc->testStatus(App::Document::PartialDoc) || doc->testStatus(App::Document::TempDoc)) continue; bool save = saveAll; - if(!save && checkModify) { + if (!save && checkModify) { int res = confirmSave(doc->Label.getStrValue().c_str(), this, docs.size()>1); switch (res) { @@ -666,7 +669,7 @@ bool MainWindow::closeAllDocuments (bool close) } } - if(save && !gdoc->save()) + if (save && !gdoc->save()) failedSaves++; } @@ -681,9 +684,9 @@ bool MainWindow::closeAllDocuments (bool close) return false; } - if(close) + if (close) App::GetApplication().closeAllDocuments(); - // d->mdiArea->closeAllSubWindows(); + return true; } From 52269f0c88f41812fd2b05200488ea24c280191a Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 15:18:06 +0200 Subject: [PATCH 084/101] Gui: [skip ci] fix gcc warning -Wimplicit-fallthrough= --- src/Gui/MainWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 488175861a..35a335e9c3 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -661,6 +661,7 @@ bool MainWindow::closeAllDocuments (bool close) return false; case ConfirmSaveResult::SaveAll: saveAll = true; + /* FALLTHRU */ case ConfirmSaveResult::Save: save = true; break; From 67ebeeaad091063d8bc2746bc6258348190858de Mon Sep 17 00:00:00 2001 From: donovaly Date: Sat, 9 Oct 2021 18:56:35 +0200 Subject: [PATCH 085/101] [Doc] update weblink to Coin3D * Coin3D is no loner available via bitbucket, therefore update the new dead links * change a weblink so that it is the same in all our code --- src/Doc/ThirdPartyLibraries.html | 2 +- src/Gui/Splashscreen.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Doc/ThirdPartyLibraries.html b/src/Doc/ThirdPartyLibraries.html index c83ba73957..833edfa871 100644 --- a/src/Doc/ThirdPartyLibraries.html +++ b/src/Doc/ThirdPartyLibraries.html @@ -56,7 +56,7 @@ DEALINGS IN THE SOFTWARE.

Coin3D

-

Web site: https://bitbucket.org/Coin3D/coin/

+

Web site: https://coin3d.github.io

Copyright: Coin is copyright (C) 1998-2013 Kongsberg Oil & Gas Technologies AS

License: BSD-3-clause

diff --git a/src/Gui/Splashscreen.cpp b/src/Gui/Splashscreen.cpp
index dbcd3cbd96..4b8e5b53fd 100644
--- a/src/Gui/Splashscreen.cpp
+++ b/src/Gui/Splashscreen.cpp
@@ -505,14 +505,14 @@ void AboutDialog::showLibraryInformation()
     // Coin3D
     li.name = QLatin1String("Coin3D");
     li.href = baseurl + QLatin1String("#_TocCoin3D");
-    li.url = QLatin1String("https://bitbucket.org/Coin3D/coin/");
+    li.url = QLatin1String("https://coin3d.github.io");
     li.version = QLatin1String(COIN_VERSION);
     libInfo << li;
 
     // Eigen3
     li.name = QLatin1String("Eigen3");
     li.href = baseurl + QLatin1String("#_TocEigen3");
-    li.url = QLatin1String("http://eigen.tuxfamily.org/");
+    li.url = QLatin1String("http://eigen.tuxfamily.org");
     li.version = QString::fromLatin1(FC_EIGEN3_VERSION);
     libInfo << li;
 

From 498b40800e308e895fbb0e783d2558c79da68512 Mon Sep 17 00:00:00 2001
From: "Zheng, Lei" 
Date: Sun, 10 Oct 2021 22:01:25 +0800
Subject: [PATCH 086/101] Part: sync ViewProviderExt::DiffuseColor on
 Transparency change

---
 src/Mod/Part/Gui/ViewProviderExt.cpp | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp
index c43bb64fad..47257f6958 100644
--- a/src/Mod/Part/Gui/ViewProviderExt.cpp
+++ b/src/Mod/Part/Gui/ViewProviderExt.cpp
@@ -452,17 +452,10 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
         long value = (long)(100*Mat.transparency);
         if (value != Transparency.getValue()) {
             float trans = Transparency.getValue()/100.0f;
-            if (pcFaceBind->value.getValue() == SoMaterialBinding::PER_PART) {
-                int cnt = pcShapeMaterial->diffuseColor.getNum();
-                pcShapeMaterial->transparency.setNum(cnt);
-                float *t = pcShapeMaterial->transparency.startEditing();
-                for (int i=0; itransparency.finishEditing();
-            }
-            else {
-                pcShapeMaterial->transparency = trans;
-            }
+            auto colors = DiffuseColor.getValues();
+            for (auto &c : colors)
+                c.a = Transparency.getValue()/100.0f;
+            DiffuseColor.setValues(colors);
 
             App::PropertyContainer* parent = ShapeMaterial.getContainer();
             ShapeMaterial.setContainer(0);
@@ -731,7 +724,7 @@ void ViewProviderPartExt::setHighlightedFaces(const std::vector& col
     else if (colors.size() == 1) {
         pcFaceBind->value = SoMaterialBinding::OVERALL;
         pcShapeMaterial->diffuseColor.setValue(colors[0].r, colors[0].g, colors[0].b);
-        //pcShapeMaterial->transparency = colors[0].a; do not get transparency from DiffuseColor in this case
+        pcShapeMaterial->transparency = Transparency.getValue()/100.f;
     }
 }
 

From 7237495d79b543724dacbad737309255d169cf3b Mon Sep 17 00:00:00 2001
From: Chris Hennes 
Date: Sat, 9 Oct 2021 22:52:41 -0500
Subject: [PATCH 087/101] [Gui] Migrate UrlLabel to use QDesktopServices

UrlLabel predates QDesktopServices' ability to ask the host OS to launch
a URL, and resorted to a Python workaround that on Windows resulted in
launchin Internet Explorer regardless of the default system browser.
---
 src/Gui/Widgets.cpp | 49 +++++++++------------------------------------
 src/Gui/Widgets.h   |  2 --
 2 files changed, 10 insertions(+), 41 deletions(-)

diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp
index a310905d3a..2c850c95b0 100644
--- a/src/Gui/Widgets.cpp
+++ b/src/Gui/Widgets.cpp
@@ -26,6 +26,7 @@
 # include 
 # include 
 # include 
+# include 
 # include 
 # include 
 # include 
@@ -812,53 +813,23 @@ void ColorButton::onRejected()
 
 // ------------------------------------------------------------------------------
 
-UrlLabel::UrlLabel(QWidget * parent, Qt::WindowFlags f)
-  : QLabel(parent, f)
+UrlLabel::UrlLabel(QWidget* parent, Qt::WindowFlags f)
+    : QLabel(parent, f)
+    , _url (QStringLiteral("http://localhost"))
 {
-    _url = QString::fromLatin1("http://localhost");
-    setToolTip(this->_url);
-
-    if (qApp->styleSheet().isEmpty()) {
-        setStyleSheet(QString::fromLatin1("Gui--UrlLabel {color: #0000FF;text-decoration: underline;}"));
-    }
+    setToolTip(this->_url);    
+    setCursor(Qt::PointingHandCursor);
+    if (qApp->styleSheet().isEmpty())
+        setStyleSheet(QStringLiteral("Gui--UrlLabel {color: #0000FF;text-decoration: underline;}"));
 }
 
 UrlLabel::~UrlLabel()
 {
 }
 
-void UrlLabel::enterEvent ( QEvent * )
+void UrlLabel::mouseReleaseEvent(QMouseEvent*)
 {
-    setCursor(Qt::PointingHandCursor);
-}
-
-void UrlLabel::leaveEvent ( QEvent * )
-{
-    setCursor(Qt::ArrowCursor);
-}
-
-void UrlLabel::mouseReleaseEvent (QMouseEvent *)
-{
-    // The webbrowser Python module allows to start the system browser in an OS-independent way
-    Base::PyGILStateLocker lock;
-    PyObject* module = PyImport_ImportModule("webbrowser");
-    if (module) {
-        // get the methods dictionary and search for the 'open' method
-        PyObject* dict = PyModule_GetDict(module);
-        PyObject* func = PyDict_GetItemString(dict, "open");
-        if (func) {
-            PyObject* args = Py_BuildValue("(s)", (const char*)this->_url.toLatin1());
-#if PY_VERSION_HEX < 0x03090000
-            PyObject* result = PyEval_CallObject(func,args);
-#else
-            PyObject* result = PyObject_CallObject(func,args);
-#endif
-            // decrement the args and module reference
-            Py_XDECREF(result);
-            Py_DECREF(args);
-            Py_DECREF(module);
-        }
-    }
+    QDesktopServices::openUrl(this->_url);
 }
 
 QString UrlLabel::url() const
diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h
index 86baff6a51..f472a59966 100644
--- a/src/Gui/Widgets.h
+++ b/src/Gui/Widgets.h
@@ -265,8 +265,6 @@ public Q_SLOTS:
   void setUrl( const QString &u );
 
 protected:
-  void enterEvent ( QEvent * );
-  void leaveEvent ( QEvent * );
   void mouseReleaseEvent ( QMouseEvent * );
 
 private:

From 277e164657b34af97b6c4b0da4efe2ad2ca44844 Mon Sep 17 00:00:00 2001
From: luz paz 
Date: Sun, 10 Oct 2021 12:51:00 -0400
Subject: [PATCH 088/101] Fix various typos

Found via `codespell -q 3 -L aci,ake,aline,alle,alledges,alocation,als,ang,anid,apoints,ba,beginn,behaviour,bloaded,bottome,byteorder,calculater,cancelled,cancelling,cas,cascade,centimetre,childs,colour,colours,commen,connexion,currenty,dof,doubleclick,dum,eiter,elemente,ende,feld,finde,findf,freez,hist,iff,indicies,initialisation,initialise,initialised,initialises,initialisiert,inout,ist,kilometre,lod,mantatory,methode,metres,millimetre,modell,nd,noe,normale,normaly,nto,numer,oder,ontop,orgin,orginx,orginy,ot,pard,parms,pres,programm,que,recurrance,rougly,seperator,serie,sinc,strack,substraction,te,thist,thru,tread,uint,unter,vertexes,wallthickness,whitespaces -S ./.git,*.po,*.ts,./ChangeLog.txt,./src/3rdParty,./src/Mod/Assembly/App/opendcm,./src/CXX,./src/zipios++,./src/Base/swig*,./src/Mod/Robot/App/kdl_cp,./src/Mod/Import/App/SCL,./src/WindowsInstaller,./src/Doc/FreeCAD.uml,./build/doc/SourceDocu`
---
 BUILD_OSX.md                                |  2 +-
 src/Mod/Fem/femsolver/settings.py           |  2 +-
 src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 14 +++++++-------
 src/Mod/Surface/Gui/TaskFilling.cpp         |  2 +-
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/BUILD_OSX.md b/BUILD_OSX.md
index 76778d5088..9b38665969 100644
--- a/BUILD_OSX.md
+++ b/BUILD_OSX.md
@@ -7,7 +7,7 @@
   - [Install Xcode Command line tools](#install-xcode-cli-tools)
   - [Install Conda](#install-conda)
   - [Run the shell script](#run-the-shell-script)
-- [Building FreeCAD on macOS using homebrew packages with & without formual file](#homebrew-build-fc-on-macos)
+- [Building FreeCAD on macOS using homebrew packages with & without formula file](#homebrew-build-fc-on-macos)
 - [Requirements](#homebrew-requirements)
   - [Install required FreeCAD dependencies](#homebrew-install-required-deps)
 - [Limitations of using freecad formula file](#homebrew-limits-of-formula-file)
diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py
index 7590b97a06..36e43ec149 100644
--- a/src/Mod/Fem/femsolver/settings.py
+++ b/src/Mod/Fem/femsolver/settings.py
@@ -195,7 +195,7 @@ class _SolverDlg(object):
 
         # set the binary path to the FreeCAD defaults
         # ATM pure unix shell commands without path names are used as standard
-        # TODO the binaries provieded with the FreeCAD distribution should be found
+        # TODO the binaries provided with the FreeCAD distribution should be found
         # without any additional user input
         # see ccxttols, it works for Windows and Linux there
         binary = self.default
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
index 3459526a49..8bd535ee63 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
@@ -4429,7 +4429,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
             SoSeparator *sep = new SoSeparator();
             sep->ref();
-            // no caching for fluctuand data structures
+            // no caching for fluctuant data structures
             sep->renderCaching = SoSeparator::OFF;
 
             // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4482,7 +4482,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
             SoSeparator *sep = new SoSeparator();
             sep->ref();
-            // no caching for fluctuand data structures
+            // no caching for fluctuant data structures
             sep->renderCaching = SoSeparator::OFF;
 
             // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4612,7 +4612,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
             SoSeparator *sep = new SoSeparator();
             sep->ref();
-            // no caching for fluctuand data structures
+            // no caching for fluctuant data structures
             sep->renderCaching = SoSeparator::OFF;
 
             // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4706,7 +4706,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
                 SoSeparator *sep = new SoSeparator();
                 sep->ref();
-                // no caching for fluctuand data structures
+                // no caching for fluctuant data structures
                 sep->renderCaching = SoSeparator::OFF;
 
                 // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4775,7 +4775,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
                 SoSeparator* sep = new SoSeparator();
                 sep->ref();
-                // no caching for fluctuand data structures
+                // no caching for fluctuant data structures
                 sep->renderCaching = SoSeparator::OFF;
 
                 // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -5970,7 +5970,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
         // root separator for one constraint
         SoSeparator *sep = new SoSeparator();
         sep->ref();
-        // no caching for fluctuand data structures
+        // no caching for fluctuant data structures
         sep->renderCaching = SoSeparator::OFF;
 
         // every constrained visual node gets its own material for preselection and selection
@@ -6808,7 +6808,7 @@ void ViewProviderSketch::createEditInventorNodes(void)
     ps->style.setValue(SoPickStyle::UNPICKABLE);
     Coordsep->addChild(ps);
     Coordsep->setName("CoordSeparator");
-    // no caching for fluctuand data structures
+    // no caching for fluctuant data structures
     Coordsep->renderCaching = SoSeparator::OFF;
 
     SoMaterial *CoordTextMaterials = new SoMaterial;
diff --git a/src/Mod/Surface/Gui/TaskFilling.cpp b/src/Mod/Surface/Gui/TaskFilling.cpp
index 3b07bee830..bc25c3a0b7 100644
--- a/src/Mod/Surface/Gui/TaskFilling.cpp
+++ b/src/Mod/Surface/Gui/TaskFilling.cpp
@@ -548,7 +548,7 @@ void FillingPanel::on_listBoundary_itemDoubleClicked(QListWidgetItem* item)
                         ui->comboBoxFaces->addItem(text, text.toLatin1());
                     }
 
-                    // activste face and continuity
+                    // activate face and continuity
                     if (data.size() == 5) {
                         int index = ui->comboBoxFaces->findData(data[3]);
                         ui->comboBoxFaces->setCurrentIndex(index);

From 4adfa1fe3841fd58a73f3075b7806ce2e30a0545 Mon Sep 17 00:00:00 2001
From: luz paz 
Date: Sun, 10 Oct 2021 14:57:39 -0400
Subject: [PATCH 089/101] Added requested revisions

---
 src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
index 8bd535ee63..3bbd7da645 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
@@ -4429,7 +4429,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
             SoSeparator *sep = new SoSeparator();
             sep->ref();
-            // no caching for fluctuant data structures
+            // no caching for frequently-changing data structures
             sep->renderCaching = SoSeparator::OFF;
 
             // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4482,7 +4482,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
             SoSeparator *sep = new SoSeparator();
             sep->ref();
-            // no caching for fluctuant data structures
+            // no caching for frequently-changing data structures
             sep->renderCaching = SoSeparator::OFF;
 
             // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4612,7 +4612,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
             SoSeparator *sep = new SoSeparator();
             sep->ref();
-            // no caching for fluctuant data structures
+            // no caching for frequently-changing data structures
             sep->renderCaching = SoSeparator::OFF;
 
             // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4706,7 +4706,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
                 SoSeparator *sep = new SoSeparator();
                 sep->ref();
-                // no caching for fluctuant data structures
+                // no caching for frequently-changing data structures
                 sep->renderCaching = SoSeparator::OFF;
 
                 // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -4775,7 +4775,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
 
                 SoSeparator* sep = new SoSeparator();
                 sep->ref();
-                // no caching for fluctuant data structures
+                // no caching for frequently-changing data structures
                 sep->renderCaching = SoSeparator::OFF;
 
                 // every information visual node gets its own material for to-be-implemented preselection and selection
@@ -5970,7 +5970,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
         // root separator for one constraint
         SoSeparator *sep = new SoSeparator();
         sep->ref();
-        // no caching for fluctuant data structures
+        // no caching for frequently-changing data structures
         sep->renderCaching = SoSeparator::OFF;
 
         // every constrained visual node gets its own material for preselection and selection
@@ -6808,7 +6808,7 @@ void ViewProviderSketch::createEditInventorNodes(void)
     ps->style.setValue(SoPickStyle::UNPICKABLE);
     Coordsep->addChild(ps);
     Coordsep->setName("CoordSeparator");
-    // no caching for fluctuant data structures
+    // no caching for frequently-changing data structures
     Coordsep->renderCaching = SoSeparator::OFF;
 
     SoMaterial *CoordTextMaterials = new SoMaterial;

From 45d06607277dcebe7e6edbcc88ad0a2ee3ff6c1d Mon Sep 17 00:00:00 2001
From: "Zheng, Lei" 
Date: Mon, 11 Oct 2021 06:02:54 +0800
Subject: [PATCH 090/101] Part: minor change on transparency setting

---
 src/Mod/Part/Gui/ViewProviderExt.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp
index 47257f6958..dd0cf77a53 100644
--- a/src/Mod/Part/Gui/ViewProviderExt.cpp
+++ b/src/Mod/Part/Gui/ViewProviderExt.cpp
@@ -454,7 +454,7 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
             float trans = Transparency.getValue()/100.0f;
             auto colors = DiffuseColor.getValues();
             for (auto &c : colors)
-                c.a = Transparency.getValue()/100.0f;
+                c.a = trans;
             DiffuseColor.setValues(colors);
 
             App::PropertyContainer* parent = ShapeMaterial.getContainer();

From 51e4366085e59a9b511f7160d66493e9b3dfc7d8 Mon Sep 17 00:00:00 2001
From: wmayer 
Date: Mon, 11 Oct 2021 00:28:12 +0200
Subject: [PATCH 091/101] OCCT: port FreeCAD sources to version 7.6

---
 src/Mod/Fem/App/FemConstraint.cpp      | 12 ++++++++++--
 src/Mod/Fem/App/FemConstraintFixed.cpp |  2 --
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/Mod/Fem/App/FemConstraint.cpp b/src/Mod/Fem/App/FemConstraint.cpp
index 18f72e87d2..8003fd6d79 100644
--- a/src/Mod/Fem/App/FemConstraint.cpp
+++ b/src/Mod/Fem/App/FemConstraint.cpp
@@ -36,8 +36,6 @@
 # include 
 # include 
 # include 
-# include 
-# include 
 # include 
 # include 
 # include 
@@ -51,6 +49,11 @@
 # include 
 # include 
 # include 
+# include 
+# if OCC_VERSION_HEX < 0x070600
+# include 
+# include 
+# endif
 #endif
 
 #include "FemConstraint.h"
@@ -74,6 +77,11 @@ double round(double r) {
 }
 #endif
 
+#if OCC_VERSION_HEX >= 0x070600
+using Adaptor3d_HSurface = Adaptor3d_Surface;
+using BRepAdaptor_HSurface = BRepAdaptor_Surface;
+#endif
+
 PROPERTY_SOURCE(Fem::Constraint, App::DocumentObject)
 
 Constraint::Constraint()
diff --git a/src/Mod/Fem/App/FemConstraintFixed.cpp b/src/Mod/Fem/App/FemConstraintFixed.cpp
index 4d80945490..5b8874ec90 100644
--- a/src/Mod/Fem/App/FemConstraintFixed.cpp
+++ b/src/Mod/Fem/App/FemConstraintFixed.cpp
@@ -32,8 +32,6 @@
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 

From 6f3b00d67ec0bd0072b7b493e2a38d2a2e3af27d Mon Sep 17 00:00:00 2001
From: wmayer 
Date: Mon, 11 Oct 2021 00:30:22 +0200
Subject: [PATCH 092/101] SMESH: port to OCCT 7.6

---
 .../src/NETGENPlugin/NETGENPlugin_Mesher.cpp       |  7 +++++++
 .../salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp      |  7 +++++--
 .../src/StdMeshers/StdMeshers_Adaptive1D.cpp       | 14 ++++++++++++++
 .../src/StdMeshers/StdMeshers_Quadrangle_2D.cpp    |  2 +-
 .../src/StdMeshers/StdMeshers_ViscousLayers.cpp    |  8 ++++++++
 5 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp b/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp
index cd6f0b2b07..ea83984b97 100644
--- a/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp
+++ b/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp
@@ -56,6 +56,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -700,7 +701,13 @@ double NETGENPlugin_Mesher::GetDefaultMinSize(const TopoDS_Shape& geom,
       BRep_Tool::Triangulation ( TopoDS::Face( fExp.Current() ), loc);
     if ( triangulation.IsNull() ) continue;
     const double fTol = BRep_Tool::Tolerance( TopoDS::Face( fExp.Current() ));
+#if OCC_VERSION_HEX < 0x070600
     const TColgp_Array1OfPnt&   points = triangulation->Nodes();
+#else
+    auto points = [&triangulation](Standard_Integer index) {
+        return triangulation->Node(index);
+    };
+#endif
     const Poly_Array1OfTriangle& trias = triangulation->Triangles();
     for ( int iT = trias.Lower(); iT <= trias.Upper(); ++iT )
     {
diff --git a/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp b/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp
index 5a07308310..fbb1b25008 100644
--- a/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp
+++ b/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp
@@ -38,10 +38,13 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
+#include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
diff --git a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp
index 88970f36b5..7c51601c7b 100644
--- a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp
+++ b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp
@@ -46,6 +46,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -318,13 +319,26 @@ namespace // internal utils
     {
       myFaceTol         = SMESH_MesherHelper::MaxTolerance( face );
       myTree            = triaTree;
+#if OCC_VERSION_HEX < 0x070600
       myNodes           = & tr->Nodes();
+#else
+      TColgp_Array1OfPnt* trNodes = new TColgp_Array1OfPnt( 1, tr->NbNodes() );
+      for (Standard_Integer i = myNodes->Lower(); i <= myNodes->Upper(); i++)
+      {
+        trNodes->SetValue(i, tr->Node(i));
+      }
+      myNodes = trNodes;
+      myOwnNodes = true;
+#endif
       myPolyTrias       = & tr->Triangles();
       myTriasDeflection = tr->Deflection();
       if ( !loc.IsIdentity() ) // transform nodes if necessary
       {
         TColgp_Array1OfPnt* trsfNodes = new TColgp_Array1OfPnt( myNodes->Lower(), myNodes->Upper() );
         trsfNodes->Assign( *myNodes );
+#if OCC_VERSION_HEX >= 0x070600
+        delete myNodes; // it's already a copy
+#endif
         myNodes    = trsfNodes;
         myOwnNodes = true;
         const gp_Trsf& trsf = loc;
diff --git a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp
index f7ac411d9a..5d5c15c366 100644
--- a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp
+++ b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp
@@ -50,7 +50,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp
index 8ee0e26832..e9f4618305 100644
--- a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp
+++ b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp
@@ -44,7 +44,10 @@
 #include "SMESH_subMeshEventListener.hxx"
 #include "StdMeshers_FaceSide.hxx"
 
+#include 
+#if OCC_VERSION_HEX < 0x070600
 #include 
+#endif
 #include 
 #include 
 #include 
@@ -1340,8 +1343,13 @@ namespace VISCOUS_3D
     //case GeomAbs_SurfaceOfExtrusion:
     case GeomAbs_OffsetSurface:
     {
+#if OCC_VERSION_HEX < 0x070600
       Handle(Adaptor3d_HSurface) base = surface.BasisSurface();
       return getRovolutionAxis( base->Surface(), axis );
+#else
+      Handle(Adaptor3d_Surface) base = surface.BasisSurface();
+      return getRovolutionAxis( *base, axis );
+#endif
     }
     default: return false;
     }

From 70ad1396ea83e2e407e9f2e7f9a9f128412f5aa2 Mon Sep 17 00:00:00 2001
From: Chris Hennes 
Date: Sun, 10 Oct 2021 20:17:44 -0500
Subject: [PATCH 093/101] Gui: Add option to show alpha in QColorDialog

---
 src/Gui/Widgets.cpp | 19 +++++++++++++++++++
 src/Gui/Widgets.h   |  4 ++++
 2 files changed, 23 insertions(+)

diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp
index 2c850c95b0..d1cfad653d 100644
--- a/src/Gui/Widgets.cpp
+++ b/src/Gui/Widgets.cpp
@@ -595,6 +595,7 @@ struct ColorButtonP
     bool allowChange;
     bool autoChange;
     bool drawFrame;
+    bool allowTransparency;
     bool modal;
     bool dirty;
 
@@ -603,6 +604,7 @@ struct ColorButtonP
         , allowChange(true)
         , autoChange(false)
         , drawFrame(true)
+        , allowTransparency(false)
         , modal(true)
         , dirty(true)
     {
@@ -672,6 +674,21 @@ bool ColorButton::drawFrame() const
     return d->drawFrame;
 }
 
+void Gui::ColorButton::setAllowTransparency(bool allow)
+{
+    d->allowTransparency = allow;
+    if (d->cd)
+        d->cd->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, allow);
+}
+
+bool Gui::ColorButton::allowTransparency() const
+{
+    if (d->cd)
+        return d->cd->testOption(QColorDialog::ColorDialogOption::ShowAlphaChannel);
+    else
+        return d->allowTransparency;
+}
+
 void ColorButton::setModal(bool b)
 {
     d->modal = b;
@@ -764,6 +781,7 @@ void ColorButton::onChooseColor()
         QColor currentColor = d->col;
         QColorDialog cd(d->col, this);
         cd.setOptions(QColorDialog::DontUseNativeDialog);
+        cd.setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, d->allowTransparency);
 
         if (d->autoChange) {
             connect(&cd, SIGNAL(currentColorChanged(const QColor &)),
@@ -789,6 +807,7 @@ void ColorButton::onChooseColor()
             d->old = d->col;
             d->cd = new QColorDialog(d->col, this);
             d->cd->setOptions(QColorDialog::DontUseNativeDialog);
+            d->cd->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, d->allowTransparency);
             d->cd->setAttribute(Qt::WA_DeleteOnClose);
             connect(d->cd, SIGNAL(rejected()),
                     this, SLOT(onRejected()));
diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h
index f472a59966..09d9013a99 100644
--- a/src/Gui/Widgets.h
+++ b/src/Gui/Widgets.h
@@ -202,6 +202,7 @@ class GuiExport ColorButton : public QPushButton
     Q_PROPERTY( QColor color READ color WRITE setColor )
     Q_PROPERTY( bool allowChangeColor READ allowChangeColor WRITE setAllowChangeColor )
     Q_PROPERTY( bool drawFrame READ drawFrame WRITE setDrawFrame )
+    Q_PROPERTY( bool allowTransparency READ allowTransparency WRITE setAllowTransparency)
 
 public:
     ColorButton(QWidget* parent = 0);
@@ -216,6 +217,9 @@ public:
     void setDrawFrame(bool);
     bool drawFrame() const;
 
+    void setAllowTransparency(bool);
+    bool allowTransparency() const;
+
     void setModal(bool);
     bool isModal() const;
 

From bce8c254219c597f16f67c474b9c2253149851b1 Mon Sep 17 00:00:00 2001
From: wmayer 
Date: Mon, 11 Oct 2021 10:13:49 +0200
Subject: [PATCH 094/101] Start: if a corrupted file is part of the Recent File
 List then ignore it

---
 src/Mod/Start/StartPage/StartPage.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/Mod/Start/StartPage/StartPage.py b/src/Mod/Start/StartPage/StartPage.py
index f1270a8bc4..88556f1fb4 100644
--- a/src/Mod/Start/StartPage/StartPage.py
+++ b/src/Mod/Start/StartPage/StartPage.py
@@ -147,7 +147,11 @@ def getInfo(filename):
             files=zfile.namelist()
             # check for meta-file if it's really a FreeCAD document
             if files[0] == "Document.xml":
-                doc = str(zfile.read(files[0]))
+                try:
+                    doc = str(zfile.read(files[0]))
+                except OSError as e:
+                    print ("Fail to load corrupted FCStd file: '{0}' with this error: {1}".format(filename, str(e)))
+                    return None
                 doc = doc.replace("\n"," ")
                 r = re.findall("Property name=\"CreatedBy.*?String value=\"(.*?)\"/>",doc)
                 if r:

From b01d0e518170c1a7dd97e9ddb78742aa493c5aaa Mon Sep 17 00:00:00 2001
From: Chris Hennes 
Date: Sun, 10 Oct 2021 22:42:46 -0500
Subject: [PATCH 095/101] [Gui] Always hide progress bar on finished load

The loadFinished signal from QtWebEngine includes a boolean indicating
whether the load was "ssuccessful" or not, but no apparent way to
determine what error, if any, occurred. Given that we are never
displaying any error information to the user, hide the progress bar
regardless of the success or failure of the operation.
---
 src/Mod/Web/Gui/BrowserView.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/Mod/Web/Gui/BrowserView.cpp b/src/Mod/Web/Gui/BrowserView.cpp
index 0c776f066b..f3390c35eb 100644
--- a/src/Mod/Web/Gui/BrowserView.cpp
+++ b/src/Mod/Web/Gui/BrowserView.cpp
@@ -693,12 +693,10 @@ void BrowserView::onLoadProgress(int step)
 
 void BrowserView::onLoadFinished(bool ok)
 {
-    if (ok) {
-        QProgressBar* bar = SequencerBar::instance()->getProgressBar();
-        bar->setValue(100);
-        bar->hide();
-        getMainWindow()->showMessage(QString());
-    }
+    QProgressBar* bar = SequencerBar::instance()->getProgressBar();
+    bar->setValue(100);
+    bar->hide();
+    getMainWindow()->showMessage(QString());
     isLoading = false;
 }
 

From 910dbcf880ab38272b2369054c31f71cb45cbeea Mon Sep 17 00:00:00 2001
From: wmayer 
Date: Mon, 11 Oct 2021 10:31:48 +0200
Subject: [PATCH 096/101] Web: [skip ci] fix warning: unused parameter 'ok'
 [-Wunused-parameter]

---
 src/Mod/Web/Gui/BrowserView.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/Mod/Web/Gui/BrowserView.cpp b/src/Mod/Web/Gui/BrowserView.cpp
index f3390c35eb..3914e06ffd 100644
--- a/src/Mod/Web/Gui/BrowserView.cpp
+++ b/src/Mod/Web/Gui/BrowserView.cpp
@@ -693,6 +693,8 @@ void BrowserView::onLoadProgress(int step)
 
 void BrowserView::onLoadFinished(bool ok)
 {
+    Q_UNUSED(ok)
+
     QProgressBar* bar = SequencerBar::instance()->getProgressBar();
     bar->setValue(100);
     bar->hide();

From 7a7d58548bb1b2d3c64c8845042a98aea36af122 Mon Sep 17 00:00:00 2001
From: wmayer 
Date: Mon, 11 Oct 2021 16:09:23 +0200
Subject: [PATCH 097/101] Test: [skip ci] handle std. and unknown exceptions in
 unit test dialog

---
 src/Mod/Test/Gui/UnitTestImp.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/Mod/Test/Gui/UnitTestImp.cpp b/src/Mod/Test/Gui/UnitTestImp.cpp
index 5b34ce1988..a70f8602d7 100644
--- a/src/Mod/Test/Gui/UnitTestImp.cpp
+++ b/src/Mod/Test/Gui/UnitTestImp.cpp
@@ -192,6 +192,12 @@ void UnitTestDialog::on_startButton_clicked()
     catch (const Base::Exception& e) {
         showErrorDialog("Exception", e.what());
     }
+    catch (const std::exception& e) {
+        showErrorDialog("C++ standard exception", e.what());
+    }
+    catch (...) {
+        showErrorDialog("Unknown exception", "Unknown exception raised");
+    }
     ui->startButton->setEnabled(true);
 }
 

From ab57037f3ecc9e0ef72e6a0558a2405fb25f4f8d Mon Sep 17 00:00:00 2001
From: Abdullah Tahiri 
Date: Mon, 11 Oct 2021 11:33:04 +0200
Subject: [PATCH 098/101] Sketcher: Add preferences icon resource

---
 src/Mod/Sketcher/Gui/Resources/Sketcher.qrc   |   3 +
 .../icons/dialogs/Sketcher_Settings.svg       | 396 ++++++++++++++++++
 2 files changed, 399 insertions(+)
 create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/dialogs/Sketcher_Settings.svg

diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
index bd93ed58b2..eed7a6cc87 100644
--- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
+++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
@@ -238,6 +238,9 @@
         icons/tools/Sketcher_SelectVerticalAxis.svg
         icons/tools/Sketcher_Symmetry.svg
     
+    
+        icons/dialogs/Sketcher_Settings.svg
+    
     
         translations/Sketcher_af.qm
         translations/Sketcher_ar.qm
diff --git a/src/Mod/Sketcher/Gui/Resources/icons/dialogs/Sketcher_Settings.svg b/src/Mod/Sketcher/Gui/Resources/icons/dialogs/Sketcher_Settings.svg
new file mode 100644
index 0000000000..a6183e8b0a
--- /dev/null
+++ b/src/Mod/Sketcher/Gui/Resources/icons/dialogs/Sketcher_Settings.svg
@@ -0,0 +1,396 @@
+
+
+
+  
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+      
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+      
+      
+      
+      
+    
+    
+      
+      
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+          
+            Jakub Steiner
+          
+        
+        http://jimmac.musichall.cz
+        
+        Preferences System
+        
+          
+            preferences
+            settings
+            control panel
+            tweaks
+            system
+          
+        
+      
+      
+        
+        
+        
+        
+        
+        
+      
+    
+  
+  
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+

From 08542055c41beeb09e514d2baa7c92e2c49e6c0c Mon Sep 17 00:00:00 2001
From: Abdullah Tahiri 
Date: Mon, 11 Oct 2021 11:33:41 +0200
Subject: [PATCH 099/101] Sketcher: Redesign of Constraint settings

=========================================

=> The old controltab is substituted by: direct controls (buttons on the constraint widget) and a settings dialog that is independently fired via a button with a settings icon

This makes more space for the list of constraints and generates a lower amount of confussion regarding the old tab names and functions.

Direct control ensures that the most used operations are at hand, while other less changed settings are moved to the settings dialog.

=> Direct controls

One time visibility to match the list selection can be triggered from a new button "Visibility"

This button has drop selections for visibility selections, which are checkable items (currently only one option, but more are envisaged).
The one option currently is the "visibility tracking" functionality. This is a "shortcut" to the option in the settings panel to save unnecessary clicks
in typical operations.

=> Settings dialog

This dialog is live, in that changes to settings are immediatedly propagated to the list control and visibility.
---
 src/Mod/Sketcher/Gui/CMakeLists.txt           |   3 +
 .../Sketcher/Gui/ConstraintSettingsDialog.cpp | 136 +++++++++++
 .../Sketcher/Gui/ConstraintSettingsDialog.h   |  70 ++++++
 .../Sketcher/Gui/ConstraintSettingsDialog.ui  | 195 +++++++++++++++
 .../Sketcher/Gui/TaskSketcherConstrains.cpp   | 111 +++++++--
 src/Mod/Sketcher/Gui/TaskSketcherConstrains.h |   4 +
 .../Sketcher/Gui/TaskSketcherConstrains.ui    | 225 +++++-------------
 7 files changed, 558 insertions(+), 186 deletions(-)
 create mode 100644 src/Mod/Sketcher/Gui/ConstraintSettingsDialog.cpp
 create mode 100644 src/Mod/Sketcher/Gui/ConstraintSettingsDialog.h
 create mode 100644 src/Mod/Sketcher/Gui/ConstraintSettingsDialog.ui

diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt
index 2be18fd827..317d91c208 100644
--- a/src/Mod/Sketcher/Gui/CMakeLists.txt
+++ b/src/Mod/Sketcher/Gui/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SketcherGui_UIC_SRCS
     SketchRectangularArrayDialog.ui
     SketcherRegularPolygonDialog.ui
     ConstraintMultiFilterDialog.ui
+    ConstraintSettingsDialog.ui
 )
 
 if(BUILD_QT5)
@@ -120,6 +121,8 @@ SET(SketcherGui_SRCS
     SketcherRegularPolygonDialog.cpp
     ConstraintMultiFilterDialog.h
     ConstraintMultiFilterDialog.cpp
+    ConstraintSettingsDialog.h
+    ConstraintSettingsDialog.cpp
     TaskDlgEditSketch.cpp
     TaskDlgEditSketch.h
     ViewProviderPython.cpp
diff --git a/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.cpp b/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.cpp
new file mode 100644
index 0000000000..b107047610
--- /dev/null
+++ b/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ *   Copyright (c) 2021 Abdullah Tahiri      *
+ *                                                                         *
+ *   This file is part of the FreeCAD CAx development system.              *
+ *                                                                         *
+ *   This library is free software; you can redistribute it and/or         *
+ *   modify it under the terms of the GNU Library General Public           *
+ *   License as published by the Free Software Foundation; either          *
+ *   version 2 of the License, or (at your option) any later version.      *
+ *                                                                         *
+ *   This library  is distributed in the hope that it will be useful,      *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU Library General Public License for more details.                  *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library General Public     *
+ *   License along with this library; see the file COPYING.LIB. If not,    *
+ *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
+ *   Suite 330, Boston, MA  02111-1307, USA                                *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "PreCompiled.h"
+
+#ifndef _PreComp_
+# include 
+# include 
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ui_ConstraintSettingsDialog.h"
+#include "ConstraintSettingsDialog.h"
+
+using namespace SketcherGui;
+
+ConstraintSettingsDialog::ConstraintSettingsDialog(void)
+  : QDialog(Gui::getMainWindow()), ui(new Ui_ConstraintSettingsDialog)
+{
+    ui->setupUi(this);
+
+    { // in case any signal is connected before this
+        QSignalBlocker block(this);
+        loadSettings();
+        snapshotInitialSettings();
+    }
+
+    QObject::connect(
+        ui->filterInternalAlignment, SIGNAL(stateChanged(int)),
+        this                     , SLOT  (on_filterInternalAlignment_stateChanged(int))
+        );
+    QObject::connect(
+        ui->extendedInformation, SIGNAL(stateChanged(int)),
+                     this                     , SLOT  (on_extendedInformation_stateChanged(int))
+        );
+    QObject::connect(
+        ui->visualisationTrackingFilter, SIGNAL(stateChanged(int)),
+        this                     , SLOT  (on_visualisationTrackingFilter_stateChanged(int))
+        );
+}
+
+void ConstraintSettingsDialog::saveSettings()
+{
+    ui->extendedInformation->onSave();
+    ui->filterInternalAlignment->onSave();
+    ui->visualisationTrackingFilter->onSave();
+}
+
+void ConstraintSettingsDialog::loadSettings()
+{
+    ui->extendedInformation->onRestore();
+    ui->filterInternalAlignment->onRestore();
+    ui->visualisationTrackingFilter->onRestore();
+}
+
+void ConstraintSettingsDialog::snapshotInitialSettings()
+{
+    auto isChecked = [] (auto prefwidget) {return prefwidget->checkState() == Qt::Checked;};
+
+    extendedInformation = isChecked(ui->extendedInformation);
+    filterInternalAlignment = isChecked(ui->filterInternalAlignment);
+    visualisationTrackingFilter = isChecked(ui->visualisationTrackingFilter);
+}
+
+void ConstraintSettingsDialog::restoreInitialSettings()
+{
+    auto restoreCheck = [] (auto prefwidget, bool initialvalue) {
+        if( initialvalue != (prefwidget->checkState() == Qt::Checked)) // if the state really changed
+            initialvalue ? prefwidget->setCheckState(Qt::Checked) : prefwidget->setCheckState(Qt::Unchecked);
+    };
+
+    restoreCheck(ui->extendedInformation, extendedInformation);
+    restoreCheck(ui->filterInternalAlignment, filterInternalAlignment);
+    restoreCheck(ui->visualisationTrackingFilter, visualisationTrackingFilter);
+}
+
+void ConstraintSettingsDialog::accept()
+{
+    saveSettings();
+    QDialog::accept();
+}
+
+void ConstraintSettingsDialog::reject()
+{
+    restoreInitialSettings();
+    saveSettings();
+    QDialog::reject();
+}
+
+void ConstraintSettingsDialog::on_filterInternalAlignment_stateChanged(int state)
+{
+    ui->filterInternalAlignment->onSave();
+    Q_EMIT emit_filterInternalAlignment_stateChanged(state);
+}
+
+void ConstraintSettingsDialog::on_visualisationTrackingFilter_stateChanged(int state)
+{
+    ui->visualisationTrackingFilter->onSave();
+    Q_EMIT emit_visualisationTrackingFilter_stateChanged(state);
+}
+
+void ConstraintSettingsDialog::on_extendedInformation_stateChanged(int state)
+{
+    ui->extendedInformation->onSave();
+    Q_EMIT emit_extendedInformation_stateChanged(state);
+}
+
+ConstraintSettingsDialog::~ConstraintSettingsDialog()
+{
+}
+
+#include "moc_ConstraintSettingsDialog.cpp"
diff --git a/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.h b/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.h
new file mode 100644
index 0000000000..e190692ddd
--- /dev/null
+++ b/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ *   Copyright (c) 2021 Abdullah Tahiri      *
+ *                                                                         *
+ *   This file is part of the FreeCAD CAx development system.              *
+ *                                                                         *
+ *   This library is free software; you can redistribute it and/or         *
+ *   modify it under the terms of the GNU Library General Public           *
+ *   License as published by the Free Software Foundation; either          *
+ *   version 2 of the License, or (at your option) any later version.      *
+ *                                                                         *
+ *   This library  is distributed in the hope that it will be useful,      *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU Library General Public License for more details.                  *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library General Public     *
+ *   License along with this library; see the file COPYING.LIB. If not,    *
+ *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
+ *   Suite 330, Boston, MA  02111-1307, USA                                *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef SKETCHERGUI_ConstraintSettingsDialog_H
+#define SKETCHERGUI_ConstraintSettingsDialog_H
+
+#include 
+
+#include "ConstraintFilters.h"
+
+namespace SketcherGui {
+
+using namespace ConstraintFilter;
+
+class Ui_ConstraintSettingsDialog;
+class ConstraintSettingsDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    ConstraintSettingsDialog(void);
+    ~ConstraintSettingsDialog();
+
+Q_SIGNALS:
+    void emit_filterInternalAlignment_stateChanged(int);
+    void emit_extendedInformation_stateChanged(int);
+    void emit_visualisationTrackingFilter_stateChanged(int);
+
+public Q_SLOTS:
+    void accept();
+    void reject();
+    void on_filterInternalAlignment_stateChanged(int state);
+    void on_extendedInformation_stateChanged(int state);
+    void on_visualisationTrackingFilter_stateChanged(int state);
+
+private:
+    void saveSettings();
+    void loadSettings();
+    void snapshotInitialSettings();
+    void restoreInitialSettings();
+
+private:
+    std::unique_ptr ui;
+    bool extendedInformation;
+    bool filterInternalAlignment;
+    bool visualisationTrackingFilter;
+};
+
+}
+
+#endif // SKETCHERGUI_ConstraintSettingsDialog_H
diff --git a/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.ui b/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.ui
new file mode 100644
index 0000000000..340305ed43
--- /dev/null
+++ b/src/Mod/Sketcher/Gui/ConstraintSettingsDialog.ui
@@ -0,0 +1,195 @@
+
+
+ SketcherGui::ConstraintSettingsDialog
+ 
+  
+   Qt::WindowModal
+  
+  
+   
+    0
+    0
+    275
+    215
+   
+  
+  
+   
+    0
+    0
+   
+  
+  
+   Constraint widget settings
+  
+  
+   
+    
+     
+      
+       0
+       0
+      
+     
+     
+      List control
+     
+     
+      
+       
+        
+         
+          0
+          0
+         
+        
+        
+         Internal alignments will be hidden
+        
+        
+         Hide internal alignment
+        
+        
+         true
+        
+        
+         HideInternalAlignment
+        
+        
+         Mod/Sketcher
+        
+       
+      
+      
+       
+        
+         
+          0
+          0
+         
+        
+        
+         Extended information will be added to the list
+        
+        
+         Extended information
+        
+        
+         false
+        
+        
+         ExtendedConstraintInformation
+        
+        
+         Mod/Sketcher
+        
+       
+      
+     
+    
+   
+   
+    
+     
+      
+       0
+       0
+      
+     
+     
+      3D view control
+     
+     
+      
+       
+        
+         
+          0
+          0
+         
+        
+        
+         Constraint visualisation tracks filter selection so that filtered out constraints are hidden
+        
+        
+         Show only filtered constraints
+        
+        
+         false
+        
+        
+         VisualisationTrackingFilter
+        
+        
+         Mod/Sketcher
+        
+       
+      
+     
+    
+   
+   
+    
+     
+      Qt::Vertical
+     
+     
+      
+       20
+       0
+      
+     
+    
+   
+   
+    
+     
+      QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+     
+    
+   
+  
+ 
+ 
+  
+   Gui::PrefCheckBox
+   QCheckBox
+   
Gui/PrefWidgets.h
+
+
+ + + + buttonBox + accepted() + SketcherGui::ConstraintSettingsDialog + accept() + + + 20 + 20 + + + 20 + 20 + + + + + buttonBox + rejected() + SketcherGui::ConstraintSettingsDialog + reject() + + + 20 + 20 + + + 20 + 20 + + + + +
diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index 4add6a36ec..1f04614880 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -58,6 +58,7 @@ #include #include "ConstraintMultiFilterDialog.h" +#include "ConstraintSettingsDialog.h" using namespace SketcherGui; using namespace Gui::TaskView; @@ -642,6 +643,8 @@ TaskSketcherConstrains::TaskSketcherConstrains(ViewProviderSketch *sketchView) : ui->listWidgetConstraints->setEditTriggers(QListWidget::EditKeyPressed); //QMetaObject::connectSlotsByName(this); + createVisibilityButtonActions(); + // connecting the needed signals QObject::connect( ui->comboBoxFilter, SIGNAL(currentIndexChanged(int)), @@ -671,14 +674,6 @@ TaskSketcherConstrains::TaskSketcherConstrains(ViewProviderSketch *sketchView) : ui->listWidgetConstraints, SIGNAL(onUpdateActiveStatus(QListWidgetItem *, bool)), this , SLOT (on_listWidgetConstraints_updateActiveStatus(QListWidgetItem *, bool)) ); - QObject::connect( - ui->filterInternalAlignment, SIGNAL(stateChanged(int)), - this , SLOT (on_filterInternalAlignment_stateChanged(int)) - ); - QObject::connect( - ui->extendedInformation, SIGNAL(stateChanged(int)), - this , SLOT (on_extendedInformation_stateChanged(int)) - ); QObject::connect( ui->showAllButton, SIGNAL(clicked(bool)), this , SLOT (on_showAllButton_clicked(bool)) @@ -695,23 +690,29 @@ TaskSketcherConstrains::TaskSketcherConstrains(ViewProviderSketch *sketchView) : ui->listWidgetConstraints, SIGNAL(emitShowSelection3DVisibility()), this , SLOT (on_listWidgetConstraints_emitShowSelection3DVisibility()) ); - QObject::connect( - ui->visualisationTrackingFilter, SIGNAL(stateChanged(int)), - this , SLOT (on_visualisationTrackingFilter_stateChanged(int)) - ); QObject::connect( ui->multipleFilterButton, SIGNAL(clicked(bool)), this , SLOT (on_multipleFilterButton_clicked(bool)) ); + QObject::connect( + ui->settingsDialogButton, SIGNAL(clicked(bool)), + this , SLOT (on_settingsDialogButton_clicked(bool)) + ); + QObject::connect( + ui->visibilityButton, SIGNAL(clicked(bool)), + this , SLOT (on_visibilityButton_clicked(bool)) + ); + + QObject::connect( + ui->visibilityButton->actions()[0], SIGNAL(changed()), + this , SLOT (on_visibilityButton_trackingaction_changed()) + ); connectionConstraintsChanged = sketchView->signalConstraintsChanged.connect( boost::bind(&SketcherGui::TaskSketcherConstrains::slotConstraintsChanged, this)); this->groupLayout()->addWidget(proxy); - this->ui->filterInternalAlignment->onRestore(); - this->ui->extendedInformation->onRestore(); - multiFilterStatus.set(); // Match 'All' selection, all bits set. slotConstraintsChanged(); @@ -719,11 +720,27 @@ TaskSketcherConstrains::TaskSketcherConstrains(ViewProviderSketch *sketchView) : TaskSketcherConstrains::~TaskSketcherConstrains() { - this->ui->filterInternalAlignment->onSave(); - this->ui->extendedInformation->onSave(); connectionConstraintsChanged.disconnect(); } + +void TaskSketcherConstrains::createVisibilityButtonActions() +{ + QAction* action = new QAction(QString::fromLatin1("Show only filtered Constraints"),this); + + action->setCheckable(true); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool visibilityTracksFilter = hGrp->GetBool("VisualisationTrackingFilter",false); + + { + QSignalBlocker block(this); + action->setChecked(visibilityTracksFilter); + } + + ui->visibilityButton->addAction(action); +} + void TaskSketcherConstrains::updateSelectionFilter() { // Snapshot current selection @@ -738,7 +755,8 @@ void TaskSketcherConstrains::updateSelectionFilter() void TaskSketcherConstrains::updateList() { // enforce constraint visibility - bool visibilityTracksFilter = ui->visualisationTrackingFilter->isChecked(); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool visibilityTracksFilter = hGrp->GetBool("VisualisationTrackingFilter",false); if(visibilityTracksFilter) change3DViewVisibilityToTrackFilter(); // it will call slotConstraintChanged via update mechanism @@ -766,6 +784,26 @@ void TaskSketcherConstrains::on_multipleFilterButton_clicked(bool) } } +void TaskSketcherConstrains::on_settingsDialogButton_clicked(bool) +{ + ConstraintSettingsDialog cs; + + QObject::connect( + &cs, SIGNAL(emit_filterInternalAlignment_stateChanged(int)), + this , SLOT (on_filterInternalAlignment_stateChanged(int)) + ); + QObject::connect( + &cs, SIGNAL(emit_extendedInformation_stateChanged(int)), + this , SLOT (on_extendedInformation_stateChanged(int)) + ); + QObject::connect( + &cs, SIGNAL(emit_visualisationTrackingFilter_stateChanged(int)), + this , SLOT (on_visualisationTrackingFilter_stateChanged(int)) + ); + + cs.exec(); // The dialog reacted on any change, so the result of running the dialog is already reflected on return. +} + void TaskSketcherConstrains::changeFilteredVisibility(bool show, ActionTarget target) { assert(sketchView); @@ -934,14 +972,43 @@ void TaskSketcherConstrains::on_filterInternalAlignment_stateChanged(int state) void TaskSketcherConstrains::on_visualisationTrackingFilter_stateChanged(int state) { - if(state) + // Synchronise button drop state + { + QSignalBlocker block(this); + + if(ui->visibilityButton->actions()[0]->isChecked() != (state == Qt::Checked)) + ui->visibilityButton->actions()[0]->setChecked(state); + } + + if(state == Qt::Checked) change3DViewVisibilityToTrackFilter(); } +void TaskSketcherConstrains::on_visibilityButton_trackingaction_changed() +{ + // synchronise VisualisationTrackingFilter parameter + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool visibilityTracksFilter = hGrp->GetBool("VisualisationTrackingFilter",false); + + bool bstate = ui->visibilityButton->actions()[0]->isChecked(); + + if(visibilityTracksFilter != bstate) { + hGrp->SetBool("VisualisationTrackingFilter", bstate); + } + + // Act + if(bstate) + change3DViewVisibilityToTrackFilter(); +} + +void TaskSketcherConstrains::on_visibilityButton_clicked(bool) +{ + change3DViewVisibilityToTrackFilter(); +} + void TaskSketcherConstrains::on_extendedInformation_stateChanged(int state) { Q_UNUSED(state); - this->ui->extendedInformation->onSave(); slotConstraintsChanged(); } @@ -1150,7 +1217,9 @@ bool TaskSketcherConstrains::isConstraintFiltered(QListWidgetItem * item) const Sketcher::Constraint * constraint = vals[it->ConstraintNbr]; int Filter = ui->comboBoxFilter->currentIndex(); - bool hideInternalAlignment = this->ui->filterInternalAlignment->isChecked(); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool hideInternalAlignment = hGrp->GetBool("HideInternalAlignment",false); bool visible = true; bool showAll = (Filter == FilterValue::All); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h index f273b767ab..7965f60fbf 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h @@ -94,6 +94,7 @@ private: void changeFilteredVisibility(bool show, ActionTarget target = ActionTarget::All); void updateSelectionFilter(); void updateList(); + void createVisibilityButtonActions(); template bool isFilter(T filterValue); @@ -109,11 +110,14 @@ public Q_SLOTS: void on_filterInternalAlignment_stateChanged(int state); void on_extendedInformation_stateChanged(int state); void on_visualisationTrackingFilter_stateChanged(int state); + void on_visibilityButton_trackingaction_changed(); + void on_visibilityButton_clicked(bool); void on_showAllButton_clicked(bool); void on_hideAllButton_clicked(bool); void on_listWidgetConstraints_emitShowSelection3DVisibility(); void on_listWidgetConstraints_emitHideSelection3DVisibility(); void on_multipleFilterButton_clicked(bool); + void on_settingsDialogButton_clicked(bool); protected: void changeEvent(QEvent *e); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui index e2e4d454b6..dca26d8b8a 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui @@ -6,7 +6,7 @@ 0 0 - 357 + 405 388 @@ -30,6 +30,12 @@ + + + 0 + 0 + + Filter: @@ -37,6 +43,12 @@ + + + 0 + 0 + + 0 @@ -194,49 +206,34 @@ + + + + + 0 + 0 + + + + Settings + + + + + + + :/icons/dialogs/Sketcher_Settings.svg:/icons/dialogs/Sketcher_Settings.svg + + + - - - - 0 - 0 - - - - - 0 - 95 - - - - - - - 0 - - - - - 0 - 0 - - - - View - + + - - - 10 - 10 - 135 - 27 - - - + 0 0 @@ -248,17 +245,11 @@ Show Listed + + - - - 150 - 10 - 135 - 27 - - - + 0 0 @@ -270,132 +261,39 @@ Hide Listed - - - - Controls visualisation in the 3D view - - - Automation - - - - - 0 - 0 - 271 - 36 - - + + + - + 0 0 - Constraint visualisation tracks filter selection so that filtered out constraints are hidden + Restricts 3D visibility to the listed elements - Show only filtered constraints + Restrict Visibility - - false + + QToolButton::MenuButtonPopup - - VisualisationTrackingFilter - - - Mod/Sketcher + + Qt::ToolButtonTextOnly - - - - - 0 - 0 - - - - - 0 - 0 - - - - Controls widget list behaviour - - - List - - - - - 0 - 30 - 189 - 36 - - - - - 0 - 0 - - - - Extended information will be added to the list - - - Extended information - - - false - - - ExtendedConstraintInformation - - - Mod/Sketcher - - - - - - 0 - 0 - 189 - 36 - - - - - 0 - 0 - - - - Internal alignments will be hidden - - - Hide internal alignment - - - true - - - HideInternalAlignment - - - Mod/Sketcher - - - - + + + + + 0 + 0 + + 0 @@ -404,17 +302,14 @@ - - Gui::PrefCheckBox - QCheckBox -
Gui/PrefWidgets.h
-
ConstraintView QListWidget
QListWidget
- + + + From 9b2de68000a19cb69807d6032416d13bab362860 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Mon, 11 Oct 2021 16:38:45 +0200 Subject: [PATCH 100/101] Sketcher: Constraint widget associated constraints filter ========================================================= A new special filter, that filters the constraint list so as to show the constraints associated with the currently selected geometries. --- src/Mod/Sketcher/Gui/ConstraintFilters.h | 1 + .../Sketcher/Gui/TaskSketcherConstrains.cpp | 108 +++++++++++++++++- src/Mod/Sketcher/Gui/TaskSketcherConstrains.h | 6 + .../Sketcher/Gui/TaskSketcherConstrains.ui | 7 +- 4 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ConstraintFilters.h b/src/Mod/Sketcher/Gui/ConstraintFilters.h index 4c8a292948..68370e2c71 100644 --- a/src/Mod/Sketcher/Gui/ConstraintFilters.h +++ b/src/Mod/Sketcher/Gui/ConstraintFilters.h @@ -61,6 +61,7 @@ namespace ConstraintFilter { enum SpecialFilterValue { Multiple = 24, Selection = 25, + AssociatedConstraints = 26, NumSpecialFilterValue }; diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index 1f04614880..cd67fc5f72 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -752,6 +752,47 @@ void TaskSketcherConstrains::updateSelectionFilter() selectionFilter.push_back(static_cast(item)->ConstraintNbr); } +void TaskSketcherConstrains::updateAssociatedConstraintsFilter() +{ + associatedConstraintsFilter.clear(); + + assert(sketchView); + + std::vector selection; + selection = Gui::Selection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); + + // only one sketch with its subelements are allowed to be selected + if (selection.size() != 1) { + return; + } + + // get the needed lists and objects + const std::vector &SubNames = selection[0].getSubNames(); + const Sketcher::SketchObject * Obj = sketchView->getSketchObject(); + const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues(); + + std::vector constraintSubNames; + // go through the selected subelements + for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) { + // only handle edges + if (it->size() > 4 && it->substr(0,4) == "Edge") { + int GeoId = std::atoi(it->substr(4,4000).c_str()) - 1; + + // push all the constraints + int i = 0; + for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin(); + it != vals.end(); ++it,++i) + { + if ((*it)->First == GeoId || (*it)->Second == GeoId || (*it)->Third == GeoId) { + associatedConstraintsFilter.push_back(i); + } + } + } + } + + updateList(); +} + void TaskSketcherConstrains::updateList() { // enforce constraint visibility @@ -899,6 +940,8 @@ void TaskSketcherConstrains::on_listWidgetConstraints_emitShowSelection3DVisibil void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg) { + assert(sketchView); + std::string temp; if (msg.Type == Gui::SelectionChanges::ClrSelection) { ui->listWidgetConstraints->blockSignals(true); @@ -912,6 +955,10 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg updateList(); this->blockConnection(block); } + else if (isFilter(ConstraintFilter::SpecialFilterValue::AssociatedConstraints)) { + associatedConstraintsFilter.clear(); + updateList(); + } } else if (msg.Type == Gui::SelectionChanges::AddSelection || msg.Type == Gui::SelectionChanges::RmvSelection) { @@ -923,7 +970,7 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg QRegExp rx(QString::fromLatin1("^Constraint(\\d+)$")); QString expr = QString::fromLatin1(msg.pSubName); int pos = expr.indexOf(rx); - if (pos > -1) { + if (pos > -1) { // is a constraint bool ok; int ConstrId = rx.cap(1).toInt(&ok) - 1; if (ok) { @@ -938,10 +985,25 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg break; } } - updateSelectionFilter(); - bool block = this->blockConnection(true); // avoid to be notified by itself - updateList(); - this->blockConnection(block); + + if(isFilter(ConstraintFilter::SpecialFilterValue::Selection)) { + updateSelectionFilter(); + bool block = this->blockConnection(true); // avoid to be notified by itself + updateList(); + this->blockConnection(block); + } + } + } + else if(isFilter(ConstraintFilter::SpecialFilterValue::AssociatedConstraints)) { // is NOT a constraint + int geoid = Sketcher::Constraint::GeoUndef; + Sketcher::PointPos pointpos = Sketcher::none; + getSelectionGeoId(expr, geoid, pointpos); + + if(geoid != Sketcher::Constraint::GeoUndef && pointpos == Sketcher::none){ + // It is not possible to update on single addition/removal of a geometric element, + // as one removal may imply removing a constraint that should be added by a different element + // that is still selected. The necessary checks outweight a full rebuild of the filter. + updateAssociatedConstraintsFilter(); } } } @@ -952,14 +1014,46 @@ void TaskSketcherConstrains::onSelectionChanged(const Gui::SelectionChanges& msg } } +void TaskSketcherConstrains::getSelectionGeoId(QString expr, int & geoid, Sketcher::PointPos & pointpos) +{ + QRegExp rxEdge(QString::fromLatin1("^Edge(\\d+)$")); + int pos = expr.indexOf(rxEdge); + geoid = Sketcher::Constraint::GeoUndef; + pointpos = Sketcher::none; + + if (pos > -1) { + bool ok; + int edgeId = rxEdge.cap(1).toInt(&ok) - 1; + if (ok) { + geoid = edgeId; + } + } + else { + QRegExp rxVertex(QString::fromLatin1("^Vertex(\\d+)$")); + pos = expr.indexOf(rxVertex); + + if (pos > -1) { + bool ok; + int vertexId = rxVertex.cap(1).toInt(&ok) - 1; + if (ok) { + const Sketcher::SketchObject * sketch = sketchView->getSketchObject(); + sketch->getGeoVertexIndex(vertexId, geoid, pointpos); + } + } + } +} void TaskSketcherConstrains::on_comboBoxFilter_currentIndexChanged(int filterindex) { selectionFilter.clear(); // reset the stored selection filter + associatedConstraintsFilter.clear(); if(filterindex == ConstraintFilter::SpecialFilterValue::Selection) { updateSelectionFilter(); } + else if(filterindex == ConstraintFilter::SpecialFilterValue::AssociatedConstraints) { + updateAssociatedConstraintsFilter(); + } updateList(); } @@ -1313,6 +1407,10 @@ bool TaskSketcherConstrains::isConstraintFiltered(QListWidgetItem * item) visible = visible || (Filter == SpecialFilterValue::Selection && std::find(selectionFilter.begin(), selectionFilter.end(), it->ConstraintNbr) != selectionFilter.end()); + // Constraint Type independent, associated Constraints Filter + visible = visible || (Filter == SpecialFilterValue::AssociatedConstraints && + std::find(associatedConstraintsFilter.begin(), associatedConstraintsFilter.end(), it->ConstraintNbr) != associatedConstraintsFilter.end()); + return !visible; } diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h index 7965f60fbf..00e9d1715d 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h @@ -29,6 +29,8 @@ #include #include +#include + #include "ConstraintFilters.h" namespace App { @@ -93,12 +95,15 @@ private: void change3DViewVisibilityToTrackFilter(); void changeFilteredVisibility(bool show, ActionTarget target = ActionTarget::All); void updateSelectionFilter(); + void updateAssociatedConstraintsFilter(); void updateList(); void createVisibilityButtonActions(); template bool isFilter(T filterValue); + void getSelectionGeoId(QString expr, int & geoid, Sketcher::PointPos & pos); + public Q_SLOTS: void on_comboBoxFilter_currentIndexChanged(int); void on_listWidgetConstraints_itemSelectionChanged(void); @@ -131,6 +136,7 @@ private: std::unique_ptr ui; std::bitset multiFilterStatus; std::vector selectionFilter; + std::vector associatedConstraintsFilter; }; } //namespace SketcherGui diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui index dca26d8b8a..7730655b4a 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui @@ -6,7 +6,7 @@ 0 0 - 405 + 417 388 @@ -182,6 +182,11 @@ Selection Filter
+ + + Associated Constraint Filter + + From fbdb4e29d848511913d2ff58be0f0813693509ea Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 11 Oct 2021 16:47:27 +0200 Subject: [PATCH 101/101] TD: [skip ci] fix warning about trunction from double to float --- src/Mod/TechDraw/Gui/CommandExtensionPack.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp b/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp index ba33bab420..0363e6e3d0 100644 --- a/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp +++ b/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp @@ -134,9 +134,9 @@ void CmdTechDrawExtensionCircleCenterLines::activated(int iMsg) std::string line1tag = objFeat->addCosmeticEdge(right/scale, left/scale); std::string line2tag = objFeat->addCosmeticEdge(top/scale, bottom/scale); TechDraw::CosmeticEdge* horiz = objFeat->getCosmeticEdge(line1tag); - _setStyleAndWeight(horiz,4,0.35); + _setStyleAndWeight(horiz,4,0.35f); TechDraw::CosmeticEdge* vert = objFeat->getCosmeticEdge(line2tag); - _setStyleAndWeight(vert,4,0.35); + _setStyleAndWeight(vert,4,0.35f); } } } @@ -191,7 +191,7 @@ void CmdTechDrawExtensionThreadHoleSide::activated(int iMsg) } const std::vector SubNames = selection[0].getSubNames(); if (SubNames.size() >= 2) { - _createThreadLines(SubNames, objFeat, 1.176); + _createThreadLines(SubNames, objFeat, 1.176f); } getSelection().clearSelection(); objFeat->refreshCEGeoms(); @@ -244,7 +244,7 @@ void CmdTechDrawExtensionThreadBoltSide::activated(int iMsg) } const std::vector SubNames = selection[0].getSubNames(); if (SubNames.size() >= 2) { - _createThreadLines(SubNames, objFeat, 0.85); + _createThreadLines(SubNames, objFeat, 0.85f); } getSelection().clearSelection(); objFeat->refreshCEGeoms(); @@ -297,7 +297,7 @@ void CmdTechDrawExtensionThreadHoleBottom::activated(int iMsg) } const std::vector SubNames = selection[0].getSubNames(); for (std::string Name : SubNames) { - _createThreadCircle(Name, objFeat, 1.177); + _createThreadCircle(Name, objFeat, 1.177f); } getSelection().clearSelection(); objFeat->refreshCEGeoms(); @@ -350,7 +350,7 @@ void CmdTechDrawExtensionThreadBoltBottom::activated(int iMsg) } const std::vector SubNames = selection[0].getSubNames(); for (std::string Name : SubNames) { - _createThreadCircle(Name, objFeat, 0.85); + _createThreadCircle(Name, objFeat, 0.85f); } getSelection().clearSelection(); objFeat->refreshCEGeoms(); @@ -390,7 +390,7 @@ void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, floa TechDraw::BaseGeom* threadArc = new TechDraw::AOC(center/scale, radius*factor/scale, 255.0, 165.0); std::string arcTag = objFeat->addCosmeticEdge(threadArc); TechDraw::CosmeticEdge* arc = objFeat->getCosmeticEdge(arcTag); - _setStyleAndWeight(arc,1,0.35); + _setStyleAndWeight(arc,1,0.35f); } } } @@ -429,8 +429,8 @@ void _createThreadLines(std::vector SubNames, TechDraw::DrawViewPar std::string line1Tag = objFeat->addCosmeticEdge((start1+delta)/scale, (end1+delta)/scale); TechDraw::CosmeticEdge* cosTag0 = objFeat->getCosmeticEdge(line0Tag); TechDraw::CosmeticEdge* cosTag1 = objFeat->getCosmeticEdge(line1Tag); - _setStyleAndWeight(cosTag0,1,0.35); - _setStyleAndWeight(cosTag1,1,0.35); + _setStyleAndWeight(cosTag0,1,0.35f); + _setStyleAndWeight(cosTag1,1,0.35f); } else { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("TechDraw Thread Hole Side"),