From 31fbfd33ef41dd10111ce8eabf0d4ce8652149d4 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 15 Jun 2013 15:39:29 -0300 Subject: [PATCH 1/5] 0001151: Draft loads Part module at start + Fixed loading of Part module at startup + Minor cleaning around --- src/Mod/Arch/InitGui.py | 37 +++++++++++++++++++--------------- src/Mod/Draft/DraftGui.py | 2 +- src/Mod/Draft/DraftSnap.py | 5 ++--- src/Mod/Draft/DraftTrackers.py | 3 ++- src/Mod/Draft/InitGui.py | 37 ++++++++++++++++++++-------------- src/Mod/Draft/importSVG.py | 3 ++- 6 files changed, 50 insertions(+), 37 deletions(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 7e0cd8361..94f34788a 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -59,13 +59,14 @@ class ArchWorkbench(Workbench): " *@!!!!!$=* ", " =>!!$& ", " -+ ", - " "};""" + " "};""" MenuText = "Arch" ToolTip = "Architecture workbench" - + def Initialize(self): import DraftTools,DraftGui,Arch_rc,Arch,Draft_rc + from DraftTools import translate # arch tools self.archtools = ["Arch_Wall","Arch_Structure", @@ -91,23 +92,24 @@ class ArchWorkbench(Workbench): "Draft_ShowSnapBar","Draft_ToggleGrid","Draft_UndoLine", "Draft_FinishLine","Draft_CloseLine"] - self.appendToolbar(str(DraftTools.translate("arch","Arch tools")),self.archtools) - self.appendToolbar(str(DraftTools.translate("arch","Draft tools")),self.drafttools) - self.appendToolbar(str(DraftTools.translate("arch","Draft mod tools")),self.draftmodtools) - self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Conversion Tools"))],self.meshtools) - self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Calculation Tools"))],self.calctools) - self.appendMenu(str(DraftTools.translate("arch","&Architecture")),self.archtools) - self.appendMenu(str(DraftTools.translate("arch","&Draft")),self.drafttools+self.draftmodtools) - self.appendMenu([str(DraftTools.translate("arch","&Draft")),str(DraftTools.translate("arch","Context Tools"))],self.draftcontexttools) + self.appendToolbar(str(translate("arch","Arch tools")),self.archtools) + self.appendToolbar(str(translate("arch","Draft tools")),self.drafttools) + self.appendToolbar(str(translate("arch","Draft mod tools")),self.draftmodtools) + self.appendMenu([str(translate("arch","&Architecture")),str(translate("arch","Conversion Tools"))],self.meshtools) + self.appendMenu([str(translate("arch","&Architecture")),str(translate("arch","Calculation Tools"))],self.calctools) + self.appendMenu(str(translate("arch","&Architecture")),self.archtools) + self.appendMenu(str(translate("arch","&Draft")),self.drafttools+self.draftmodtools) + self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Context Tools"))],self.draftcontexttools) FreeCADGui.addIconPath(":/icons") FreeCADGui.addLanguagePath(":/translations") FreeCADGui.addPreferencePage(":/ui/archprefs-base.ui","Arch") - if not hasattr(FreeCADGui.draftToolBar,"loadedPreferences"): - FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft") - FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft") - FreeCADGui.draftToolBar.loadedPreferences = True + if hasattr(FreeCADGui,"draftToolBar"): + if not hasattr(FreeCADGui.draftToolBar,"loadedPreferences"): + FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft") + FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft") + FreeCADGui.draftToolBar.loadedPreferences = True Log ('Loading Arch module... done\n') - + def Activated(self): if hasattr(FreeCADGui,"draftToolBar"): FreeCADGui.draftToolBar.Activated() @@ -121,7 +123,7 @@ class ArchWorkbench(Workbench): if hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper.hide() Msg("Arch workbench deactivated\n") - + def ContextMenu(self, recipient): self.appendContextMenu("Draft context tools",self.draftcontexttools) @@ -129,9 +131,12 @@ class ArchWorkbench(Workbench): return "Gui::PythonWorkbench" FreeCADGui.addWorkbench(ArchWorkbench) + +# add import/export types FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC") FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") FreeCAD.addExportType("WebGL file (*.html)","importWebGL") + # check for pycollada try: import collada diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index d50773561..1e44d34d0 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -33,7 +33,7 @@ Report to Draft.py for info import FreeCAD, FreeCADGui, os, Draft, sys try: - from PyQt4 import QtCore,QtGui,QtSvg + from PyQt4 import QtCore,QtGui,QtSvg except: FreeCAD.Console.PrintMessage("Error: Python-qt4 package must be installed on your system to use the Draft module.") diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 9b2d8ad9e..792f1c8be 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -27,7 +27,6 @@ __url__ = "http://free-cad.sourceforge.net" import FreeCAD, FreeCADGui, math, Draft, DraftGui, DraftTrackers, DraftVecUtils -from DraftGui import todo,getMainWindow from FreeCAD import Vector from pivy import coin from PyQt4 import QtCore,QtGui @@ -118,7 +117,7 @@ class Snapper: if not hasattr(self,"toolbar"): self.makeSnapToolBar() - mw = getMainWindow() + mw = DraftGui.getMainWindow() bt = mw.findChild(QtGui.QToolBar,"Draft Snap") if not bt: mw.addToolBar(self.toolbar) @@ -929,7 +928,7 @@ class Snapper: "shows the toolbar and the grid" if not hasattr(self,"toolbar"): self.makeSnapToolBar() - mw = getMainWindow() + mw = DraftGui.getMainWindow() bt = mw.findChild(QtGui.QToolBar,"Draft Snap") if not bt: mw.addToolBar(self.toolbar) diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 189819ca4..570883c06 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -28,7 +28,6 @@ __url__ = "http://free-cad.sourceforge.net" import FreeCAD,FreeCADGui,math,Draft, DraftVecUtils from FreeCAD import Vector from pivy import coin -from DraftGui import todo class Tracker: "A generic Draft Tracker, to be used by other specific trackers" @@ -52,9 +51,11 @@ class Tracker: self.switch.addChild(node) self.switch.whichChild = -1 self.Visible = False + from DraftGui import todo todo.delay(self._insertSwitch, self.switch) def finalize(self): + from DraftGui import todo todo.delay(self._removeSwitch, self.switch) self.switch = None diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 57fbca4db..1b2e7732f 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -62,8 +62,8 @@ class DraftWorkbench (Workbench): ".&&.++***,,)))!!", "#==+)!!!!!!!!!!!", " ##+)!!!!!!!!!!!", - " *,,,,,,,,,,,,"};""" - + " *,,,,,,,,,,,,"};""" + MenuText = "Draft" ToolTip = "The Draft module is used for basic 2D CAD Drafting" @@ -92,19 +92,18 @@ class DraftWorkbench (Workbench): depsOK = True if not depsOK: return - + + # import Draft tools, icons and macros menu try: - import os,macros,DraftTools,DraftGui,Draft_rc + import os,macros,Draft_rc,DraftTools, DraftGui + from DraftTools import translate FreeCADGui.addLanguagePath(":/translations") FreeCADGui.addIconPath(":/icons") - if not hasattr(FreeCADGui.draftToolBar,"loadedPreferences"): - FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft") - FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft") - FreeCADGui.draftToolBar.loadedPreferences = True - self.appendMenu(["&Macro",str(DraftTools.translate("draft","Installed Macros"))],macros.macrosList) - Log ('Loading Draft module...done\n') + self.appendMenu(["&Macro",str(translate("draft","Installed Macros"))],macros.macrosList) except: pass + + # setup menus self.cmdList = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse", "Draft_Polygon","Draft_Rectangle", "Draft_Text", "Draft_Dimension", "Draft_BSpline","Draft_Point", @@ -120,10 +119,16 @@ class DraftWorkbench (Workbench): self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] self.appendToolbar(QT_TRANSLATE_NOOP("Workbench","Draft creation tools"),self.cmdList) self.appendToolbar(QT_TRANSLATE_NOOP("Workbench","Draft modification tools"),self.modList) - self.appendMenu(str(DraftTools.translate("draft","&Draft")),self.cmdList+self.modList) - self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Context tools"))],self.treecmdList) - self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Wire tools"))],self.lineList) - + self.appendMenu(str(translate("draft","&Draft")),self.cmdList+self.modList) + self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Context tools"))],self.treecmdList) + self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Wire tools"))],self.lineList) + if hasattr(FreeCADGui,"draftToolBar"): + if not hasattr(FreeCADGui.draftToolBar,"loadedPreferences"): + FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft") + FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft") + FreeCADGui.draftToolBar.loadedPreferences = True + Log ('Loading Draft module...done\n') + def Activated(self): if hasattr(FreeCADGui,"draftToolBar"): FreeCADGui.draftToolBar.Activated() @@ -159,6 +164,8 @@ class DraftWorkbench (Workbench): # ability to turn off the Draft workbench (since it is also all included in Arch) if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("hideDraftWorkbench"): FreeCADGui.addWorkbench(DraftWorkbench) + +# add Import/Export types App.addImportType("Autodesk DXF (*.dxf)","importDXF") App.addImportType("SVG as geometry (*.svg)","importSVG") App.addImportType("Open CAD Format (*.oca *.gcad)","importOCA") @@ -167,7 +174,7 @@ App.addExportType("Autodesk DXF (*.dxf)","importDXF") App.addExportType("Flattened SVG (*.svg)","importSVG") App.addExportType("Open CAD Format (*.oca)","importOCA") -# DWG support +# add DWG support import importDWG if importDWG.getTeighaConverter(): App.addImportType("Autodesk DWG (*.dwg)","importDWG") diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index 3d4b3b55b..4eb5f3752 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -38,7 +38,7 @@ currently unsupported: use, image # implement inherting fill style from group # handle relative units -import xml.sax, string, FreeCAD, os, math, re, Draft, DraftVecUtils, DraftGeomUtils +import xml.sax, string, FreeCAD, os, math, re, Draft, DraftVecUtils from FreeCAD import Vector try: import FreeCADGui @@ -283,6 +283,7 @@ def makewire(path,checkclosed=False,donttry=False): #ToDo Do not catch all exceptions if not donttry: try: + import DraftGeomUtils sh = Part.Wire(DraftGeomUtils.sortEdges(path)) #sh = Part.Wire(path) isok = (not checkclosed) or sh.isClosed() From 2dce90b9b0ab2a6b2851ee49b4d3a6f916a8d9bb Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 15 Jun 2013 22:26:21 +0200 Subject: [PATCH 2/5] #0001150: Abort on startup --- src/Mod/Part/App/AppPart.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index b405fc561..2f5c49189 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -103,9 +103,13 @@ void PartExport initPart() App::GetApplication().addExportType("STEP with colors (*.step *.stp)","ImportGui"); #endif #endif -#if defined(FC_OS_LINUX) - OSD::SetSignal(); -#endif + // This is highly experimental and we should keep an eye on it + // if we have mysterious crashes + // The argument must be 'Standard_False' to avoid FPE caused by + // Python's cmath module. +//#if defined(FC_OS_LINUX) + OSD::SetSignal(Standard_False); +//#endif PyObject* partModule = Py_InitModule3("Part", Part_methods, module_part_doc); /* mod name, table ptr */ Base::Console().Log("Loading Part module... done\n"); From d14d5cb2e44c6b89bc0e2f79af5d443922895059 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 15 Jun 2013 23:07:26 +0200 Subject: [PATCH 3/5] #0001093: Improvements for Brep Inventor nodes (disabled atm) --- src/Mod/Part/Gui/AppPartGui.cpp | 1 + src/Mod/Part/Gui/CMakeLists.txt | 2 + src/Mod/Part/Gui/SoBrepFaceSet.cpp | 987 +++++++++++++++++++++++++++ src/Mod/Part/Gui/SoBrepFaceSet.h | 128 ++++ src/Mod/Part/Gui/ViewProviderExt.cpp | 1 + 5 files changed, 1119 insertions(+) create mode 100644 src/Mod/Part/Gui/SoBrepFaceSet.cpp create mode 100644 src/Mod/Part/Gui/SoBrepFaceSet.h diff --git a/src/Mod/Part/Gui/AppPartGui.cpp b/src/Mod/Part/Gui/AppPartGui.cpp index 889e46fce..8a368bf64 100644 --- a/src/Mod/Part/Gui/AppPartGui.cpp +++ b/src/Mod/Part/Gui/AppPartGui.cpp @@ -25,6 +25,7 @@ #include #include "SoBrepShape.h" +#include "SoBrepFaceSet.h" #include "SoFCShapeObject.h" #include "ViewProvider.h" #include "ViewProviderExt.h" diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index 9d9d482eb..c2d457ba2 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -128,6 +128,8 @@ SET(PartGui_SRCS SoFCShapeObject.h SoBrepShape.cpp SoBrepShape.h + SoBrepFaceSet.cpp + SoBrepFaceSet.h ViewProvider.cpp ViewProvider.h ViewProviderExt.cpp diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.cpp b/src/Mod/Part/Gui/SoBrepFaceSet.cpp new file mode 100644 index 000000000..7818e35ae --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepFaceSet.cpp @@ -0,0 +1,987 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * 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" +#if 0 +#ifndef _PreComp_ +# ifdef FC_OS_WIN32 +# include +# endif +# ifdef FC_OS_MACOSX +# include +# else +# include +# endif +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include +#include + + +#include "SoBrepFaceSet.h" + + +using namespace PartGui; + + +SO_NODE_SOURCE(SoBrepFaceSet); + +void SoBrepFaceSet::initClass() +{ + SO_NODE_INIT_CLASS(SoBrepFaceSet, SoIndexedFaceSet, "IndexedFaceSet"); +} + +SoBrepFaceSet::SoBrepFaceSet() +{ + SO_NODE_CONSTRUCTOR(SoBrepFaceSet); + SO_NODE_ADD_FIELD(partIndex, (-1)); + SO_NODE_ADD_FIELD(highlightIndex, (-1)); + SO_NODE_ADD_FIELD(selectionIndex, (-1)); + selectionIndex.setNum(0); +} + + +SoBrepFaceSet::~SoBrepFaceSet() +{ +} + + +void SoBrepFaceSet::doAction(SoAction* action) +{ + if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { + Gui::SoHighlightElementAction* hlaction = static_cast(action); + if (!hlaction->isHighlighted()) { + this->highlightIndex = -1; + return; + } + + const SoDetail* detail = hlaction->getElement(); + if (detail) { + if (detail->isOfType(SoFaceDetail::getClassTypeId())) { + int index = static_cast(detail)->getPartIndex(); + this->highlightIndex.setValue(index); + this->highlightColor = hlaction->getColor(); + } + else { + this->highlightIndex = -1; + return; + } + } + } + else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { + Gui::SoSelectionElementAction* selaction = static_cast(action); + this->selectionColor = selaction->getColor(); + if (selaction->getType() == Gui::SoSelectionElementAction::All) { + int num = this->partIndex.getNum(); + this->selectionIndex.setNum(num); + int32_t* v = this->selectionIndex.startEditing(); + for (int i=0; iselectionIndex.finishEditing(); + return; + } + else if (selaction->getType() == Gui::SoSelectionElementAction::None) { + this->selectionIndex.setNum(0); + return; + } + + const SoDetail* detail = selaction->getElement(); + if (detail) { + if (!detail->isOfType(SoFaceDetail::getClassTypeId())) { + return; + } + + int index = static_cast(detail)->getPartIndex(); + switch (selaction->getType()) { + case Gui::SoSelectionElementAction::Append: + { + int start = this->selectionIndex.getNum(); + this->selectionIndex.set1Value(start, index); + } + break; + case Gui::SoSelectionElementAction::Remove: + { + int start = this->selectionIndex.find(index); + this->selectionIndex.deleteValues(start,1); + } + break; + default: + break; + } + } + } + + inherited::doAction(action); +} + +void SoBrepFaceSet::GLRender(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + + SoMaterialBundle mb(action); + Binding mbind = this->findMaterialBinding(state); + + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + SbBool doTextures = tb.needCoordinates(); + + int32_t hl_idx = this->highlightIndex.getValue(); + int32_t num_selected = this->selectionIndex.getNum(); + + if (this->coordIndex.getNum() < 3) + return; + if (num_selected > 0) + renderSelection(action); + if (hl_idx >= 0) + renderHighlight(action); + + // When setting transparency shouldGLRender() handles the rendering and returns false. + // Therefore generatePrimitives() needs to be re-implemented to handle the materials + // correctly. + if (!this->shouldGLRender(action)) + return; + +#ifdef RENDER_GLARRAYS + if (!doTextures && index_array.size() && hl_idx < 0 && num_selected <= 0) { + if (mbind == 0) { + mb.sendFirst(); // only one material -> apply it! + renderSimpleArray(); + return; + } + else if (mbind == 1) { + renderColoredArray(&mb); + return; + } + } +#endif + + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + const int32_t * pindices; + int numparts; + SbBool normalCacheUsed; + + SbBool sendNormals = !mb.isColorOnly() || tb.isFunction(); + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + mb.sendFirst(); // make sure we have the correct material + + // just in case someone forgot + if (!mindices) mindices = cindices; + if (!nindices) nindices = cindices; + pindices = this->partIndex.getValues(0); + numparts = this->partIndex.getNum(); + + renderShape(static_cast(coords), cindices, numindices, + pindices, numparts, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); + + // Disable caching for this node + SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE); + + // Workaround for #0000433 +//#if !defined(FC_OS_WIN32) + if (hl_idx >= 0) + renderHighlight(action); + if (num_selected > 0) + renderSelection(action); +//#endif +} + +void SoBrepFaceSet::GLRenderBelowPath(SoGLRenderAction * action) +{ + inherited::GLRenderBelowPath(action); +} + + // this macro actually makes the code below more readable :-) +#define DO_VERTEX(idx) \ + if (mbind == PER_VERTEX) { \ + pointDetail.setMaterialIndex(matnr); \ + vertex.setMaterialIndex(matnr++); \ + } \ + else if (mbind == PER_VERTEX_INDEXED) { \ + pointDetail.setMaterialIndex(*mindices); \ + vertex.setMaterialIndex(*mindices++); \ + } \ + if (nbind == PER_VERTEX) { \ + pointDetail.setNormalIndex(normnr); \ + currnormal = &normals[normnr++]; \ + vertex.setNormal(*currnormal); \ + } \ + else if (nbind == PER_VERTEX_INDEXED) { \ + pointDetail.setNormalIndex(*nindices); \ + currnormal = &normals[*nindices++]; \ + vertex.setNormal(*currnormal); \ + } \ + if (tb.isFunction()) { \ + vertex.setTextureCoords(tb.get(coords->get3(idx), *currnormal)); \ + if (tb.needIndices()) pointDetail.setTextureCoordIndex(tindices ? *tindices++ : texidx++); \ + } \ + else if (tbind != NONE) { \ + pointDetail.setTextureCoordIndex(tindices ? *tindices : texidx); \ + vertex.setTextureCoords(tb.get(tindices ? *tindices++ : texidx++)); \ + } \ + vertex.setPoint(coords->get3(idx)); \ + pointDetail.setCoordinateIndex(idx); \ + this->shapeVertex(&vertex); + +void SoBrepFaceSet::generatePrimitives(SoAction * action) +{ + //TODO +#if 0 + inherited::generatePrimitives(action); +#else + //This is highly experimental!!! + + if (this->coordIndex.getNum() < 3) return; + + SoState * state = action->getState(); + + if (this->vertexProperty.getValue()) { + state->push(); + this->vertexProperty.getValue()->doAction(action); + } + + Binding mbind = this->findMaterialBinding(state); + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + SbBool doTextures; + SbBool sendNormals; + SbBool normalCacheUsed; + + sendNormals = TRUE; // always generate normals + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + SoTextureCoordinateBundle tb(action, FALSE, FALSE); + doTextures = tb.needCoordinates(); + + if (!sendNormals) nbind = OVERALL; + else if (normalCacheUsed && nbind == PER_VERTEX) { + nbind = PER_VERTEX_INDEXED; + } + else if (normalCacheUsed && nbind == PER_FACE_INDEXED) { + nbind = PER_FACE; + } + + if (this->getNodeType() == SoNode::VRML1) { + // For VRML1, PER_VERTEX means per vertex in shape, not PER_VERTEX + // on the state. + if (mbind == PER_VERTEX) { + mbind = PER_VERTEX_INDEXED; + mindices = cindices; + } + if (nbind == PER_VERTEX) { + nbind = PER_VERTEX_INDEXED; + nindices = cindices; + } + } + + Binding tbind = NONE; + if (doTextures) { + if (tb.isFunction() && !tb.needIndices()) { + tbind = NONE; + tindices = NULL; + } + // FIXME: just call inherited::areTexCoordsIndexed() instead of + // the if-check? 20020110 mortene. + else if (SoTextureCoordinateBindingElement::get(state) == + SoTextureCoordinateBindingElement::PER_VERTEX) { + tbind = PER_VERTEX; + tindices = NULL; + } + else { + tbind = PER_VERTEX_INDEXED; + if (tindices == NULL) tindices = cindices; + } + } + + if (nbind == PER_VERTEX_INDEXED && nindices == NULL) { + nindices = cindices; + } + if (mbind == PER_VERTEX_INDEXED && mindices == NULL) { + mindices = cindices; + } + + int texidx = 0; + TriangleShape mode = POLYGON; + TriangleShape newmode; + const int32_t *viptr = cindices; + const int32_t *viendptr = viptr + numindices; + const int32_t *piptr = this->partIndex.getValues(0); + int num_partindices = this->partIndex.getNum(); + const int32_t *piendptr = piptr + num_partindices; + int32_t v1, v2, v3, v4, v5 = 0, pi; // v5 init unnecessary, but kills a compiler warning. + + SoPrimitiveVertex vertex; + SoPointDetail pointDetail; + SoFaceDetail faceDetail; + + vertex.setDetail(&pointDetail); + + SbVec3f dummynormal(0,0,1); + const SbVec3f *currnormal = &dummynormal; + if (normals) currnormal = normals; + vertex.setNormal(*currnormal); + + int matnr = 0; + int normnr = 0; + int trinr = 0; + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + mindices++; + } + + while (viptr + 2 < viendptr) { + v1 = *viptr++; + v2 = *viptr++; + v3 = *viptr++; + if (v1 < 0 || v2 < 0 || v3 < 0) { + break; + } + v4 = viptr < viendptr ? *viptr++ : -1; + if (v4 < 0) newmode = TRIANGLES; + else { + v5 = viptr < viendptr ? *viptr++ : -1; + if (v5 < 0) newmode = QUADS; + else newmode = POLYGON; + } + if (newmode != mode) { + if (mode != POLYGON) this->endShape(); + mode = newmode; + this->beginShape(action, mode, &faceDetail); + } + else if (mode == POLYGON) this->beginShape(action, POLYGON, &faceDetail); + + // vertex 1 can't use DO_VERTEX + if (mbind == PER_PART) { + if (trinr == 0) { + pointDetail.setMaterialIndex(matnr); + vertex.setMaterialIndex(matnr++); + } + } + else if (mbind == PER_PART_INDEXED) { + if (trinr == 0) { + pointDetail.setMaterialIndex(*mindices); + vertex.setMaterialIndex(*mindices++); + } + } + else if (mbind == PER_VERTEX || mbind == PER_FACE) { + pointDetail.setMaterialIndex(matnr); + vertex.setMaterialIndex(matnr++); + } + else if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) { + pointDetail.setMaterialIndex(*mindices); + vertex.setMaterialIndex(*mindices++); + } + if (nbind == PER_VERTEX || nbind == PER_FACE) { + pointDetail.setNormalIndex(normnr); + currnormal = &normals[normnr++]; + vertex.setNormal(*currnormal); + } + else if (nbind == PER_FACE_INDEXED || nbind == PER_VERTEX_INDEXED) { + pointDetail.setNormalIndex(*nindices); + currnormal = &normals[*nindices++]; + vertex.setNormal(*currnormal); + } + + if (tb.isFunction()) { + vertex.setTextureCoords(tb.get(coords->get3(v1), *currnormal)); + if (tb.needIndices()) pointDetail.setTextureCoordIndex(tindices ? *tindices++ : texidx++); + } + else if (tbind != NONE) { + pointDetail.setTextureCoordIndex(tindices ? *tindices : texidx); + vertex.setTextureCoords(tb.get(tindices ? *tindices++ : texidx++)); + } + pointDetail.setCoordinateIndex(v1); + vertex.setPoint(coords->get3(v1)); + this->shapeVertex(&vertex); + + DO_VERTEX(v2); + DO_VERTEX(v3); + + if (mode != TRIANGLES) { + DO_VERTEX(v4); + if (mode == POLYGON) { + DO_VERTEX(v5); + v1 = viptr < viendptr ? *viptr++ : -1; + while (v1 >= 0) { + DO_VERTEX(v1); + v1 = viptr < viendptr ? *viptr++ : -1; + } + this->endShape(); + } + } + faceDetail.incFaceIndex(); + if (mbind == PER_VERTEX_INDEXED) { + mindices++; + } + if (nbind == PER_VERTEX_INDEXED) { + nindices++; + } + if (tindices) tindices++; + + trinr++; + if (pi == trinr) { + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + mindices++; + } + trinr = 0; + } + } + if (mode != POLYGON) this->endShape(); + + if (normalCacheUsed) { + this->readUnlockNormalCache(); + } + + if (this->vertexProperty.getValue()) { + state->pop(); + } +#endif +} + +#undef DO_VERTEX + +void SoBrepFaceSet::renderHighlight(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + state->push(); + + SoLazyElement::setEmissive(state, &this->highlightColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); +#if 0 // disables shading effect + // sendNormals will be FALSE + SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); +#endif + + Binding mbind = this->findMaterialBinding(state); + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + const int32_t * pindices; + SbBool doTextures; + SbBool normalCacheUsed; + + SoMaterialBundle mb(action); + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + doTextures = tb.needCoordinates(); + SbBool sendNormals = !mb.isColorOnly() || tb.isFunction(); + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + mb.sendFirst(); // make sure we have the correct material + + int32_t id = this->highlightIndex.getValue(); + + // just in case someone forgot + if (!mindices) mindices = cindices; + if (!nindices) nindices = cindices; + pindices = this->partIndex.getValues(0); + + // coords + int length = (int)pindices[id]*4; + int start=0; + for (int i=0;i(coords), &(cindices[start]), length, + &(pindices[id]), 1, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); + state->pop(); +} + +void SoBrepFaceSet::renderSelection(SoGLRenderAction *action) +{ + int numSelected = this->selectionIndex.getNum(); + const int32_t* selected = this->selectionIndex.getValues(0); + if (numSelected == 0) return; + + SoState * state = action->getState(); + state->push(); + + SoLazyElement::setEmissive(state, &this->selectionColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); +#if 0 // disables shading effect + SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); +#endif + + Binding mbind = this->findMaterialBinding(state); + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + const int32_t * pindices; + SbBool doTextures; + SbBool normalCacheUsed; + + SoMaterialBundle mb(action); + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + doTextures = tb.needCoordinates(); + SbBool sendNormals = !mb.isColorOnly() || tb.isFunction(); + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + mb.sendFirst(); // make sure we have the correct material + + // just in case someone forgot + if (!mindices) mindices = cindices; + if (!nindices) nindices = cindices; + pindices = this->partIndex.getValues(0); + + // materials + mbind = OVERALL; + doTextures = FALSE; + + for (int i=0; i(coords), &(cindices[start]), length, + &(pindices[id]), 1, normals_s, nindices_s, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); + } + state->pop(); +} + + +SoDetail * SoBrepFaceSet::createTriangleDetail(SoRayPickAction * action, + const SoPrimitiveVertex * v1, + const SoPrimitiveVertex * v2, + const SoPrimitiveVertex * v3, + SoPickedPoint * pp) +{ + SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp); + const int32_t * indices = this->partIndex.getValues(0); + int num = this->partIndex.getNum(); + if (indices) { + SoFaceDetail* face_detail = static_cast(detail); + int index = face_detail->getFaceIndex(); + int count = 0; + for (int i=0; isetPartIndex(i); + break; + } + } + } + return detail; +} + +SoBrepFaceSet::Binding +SoBrepFaceSet::findMaterialBinding(SoState * const state) const +{ + Binding binding = OVERALL; + SoMaterialBindingElement::Binding matbind = + SoMaterialBindingElement::get(state); + + switch (matbind) { + case SoMaterialBindingElement::OVERALL: + binding = OVERALL; + break; + case SoMaterialBindingElement::PER_VERTEX: + binding = PER_VERTEX; + break; + case SoMaterialBindingElement::PER_VERTEX_INDEXED: + binding = PER_VERTEX_INDEXED; + break; + case SoMaterialBindingElement::PER_PART: + binding = PER_PART; + break; + case SoMaterialBindingElement::PER_FACE: + binding = PER_FACE; + break; + case SoMaterialBindingElement::PER_PART_INDEXED: + binding = PER_PART_INDEXED; + break; + case SoMaterialBindingElement::PER_FACE_INDEXED: + binding = PER_FACE_INDEXED; + break; + default: + break; + } + return binding; +} + +SoBrepFaceSet::Binding +SoBrepFaceSet::findNormalBinding(SoState * const state) const +{ + Binding binding = PER_VERTEX_INDEXED; + SoNormalBindingElement::Binding normbind = + (SoNormalBindingElement::Binding) SoNormalBindingElement::get(state); + + switch (normbind) { + case SoNormalBindingElement::OVERALL: + binding = OVERALL; + break; + case SoNormalBindingElement::PER_VERTEX: + binding = PER_VERTEX; + break; + case SoNormalBindingElement::PER_VERTEX_INDEXED: + binding = PER_VERTEX_INDEXED; + break; + case SoNormalBindingElement::PER_PART: + binding = PER_PART; + break; + case SoNormalBindingElement::PER_FACE: + binding = PER_FACE; + break; + case SoNormalBindingElement::PER_PART_INDEXED: + binding = PER_PART_INDEXED; + break; + case SoNormalBindingElement::PER_FACE_INDEXED: + binding = PER_FACE_INDEXED; + break; + default: + break; + } + return binding; +} + + +//**************************************************************************** +// renderShape: fallback rendering: one vertex at a time +// +void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist, + const int32_t *vertexindices, + int num_indices, + const int32_t *partindices, + int num_partindices, + const SbVec3f *normals, + const int32_t *normalindices, + SoMaterialBundle *const materials, + const int32_t *matindices, + SoTextureCoordinateBundle * const texcoords, + const int32_t *texindices, + const int nbind, + const int mbind, + const int texture) +{ + int texidx = 0; + + const SbVec3f * coords3d = NULL; + coords3d = vertexlist->getArrayPtr3(); + + const int32_t *viptr = vertexindices; + const int32_t *viendptr = viptr + num_indices; + const int32_t *piptr = partindices; + const int32_t *piendptr = piptr + num_partindices; + int32_t v1, v2, v3, v4, pi; + SbVec3f dummynormal(0,0,1); + int numverts = vertexlist->getNum(); + + const SbVec3f *currnormal = &dummynormal; + if (normals) currnormal = normals; + + int matnr = 0; + int trinr = 0; + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + matindices++; + } + + glBegin(GL_TRIANGLES); + while (viptr + 2 < viendptr) { + v1 = *viptr++; + v2 = *viptr++; + v3 = *viptr++; + + // This test is for robustness upon buggy data sets + if (v1 < 0 || v2 < 0 || v3 < 0 || + v1 >= numverts || v2 >= numverts || v3 >= numverts) { + break; + } + v4 = viptr < viendptr ? *viptr++ : -1; + + /* vertex 1 *********************************************************/ + if (mbind == PER_PART) { + if (trinr == 0) + materials->send(matnr++, TRUE); + } + else if (mbind == PER_PART_INDEXED) { + if (trinr == 0) + materials->send(*matindices++, TRUE); + } + else if (mbind == PER_VERTEX || mbind == PER_FACE) { + materials->send(matnr++, TRUE); + } + else if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) { + materials->send(*matindices++, TRUE); + } + + if (normals) { + if (nbind == PER_VERTEX || nbind == PER_FACE) { + currnormal = normals++; + glNormal3fv((const GLfloat*)currnormal); + } + else if (nbind == PER_VERTEX_INDEXED || nbind == PER_FACE_INDEXED) { + currnormal = &normals[*normalindices++]; + glNormal3fv((const GLfloat*)currnormal); + } + } + + if (texture) { + texcoords->send(texindices ? *texindices++ : texidx++, + vertexlist->get3(v1), + *currnormal); + } + + glVertex3fv((const GLfloat*) (coords3d + v1)); + + /* vertex 2 *********************************************************/ + if (mbind == PER_VERTEX) + materials->send(matnr++, TRUE); + else if (mbind == PER_VERTEX_INDEXED) + materials->send(*matindices++, TRUE); + + if (normals) { + if (nbind == PER_VERTEX) { + currnormal = normals++; + glNormal3fv((const GLfloat*)currnormal); + } + else if (nbind == PER_VERTEX_INDEXED) { + currnormal = &normals[*normalindices++]; + glNormal3fv((const GLfloat*)currnormal); + } + } + + if (texture) { + texcoords->send(texindices ? *texindices++ : texidx++, + vertexlist->get3(v2), + *currnormal); + } + + glVertex3fv((const GLfloat*) (coords3d + v2)); + + /* vertex 3 *********************************************************/ + if (mbind == PER_VERTEX) + materials->send(matnr++, TRUE); + else if (mbind == PER_VERTEX_INDEXED) + materials->send(*matindices++, TRUE); + + if (normals) { + if (nbind == PER_VERTEX) { + currnormal = normals++; + glNormal3fv((const GLfloat*)currnormal); + } + else if (nbind == PER_VERTEX_INDEXED) { + currnormal = &normals[*normalindices++]; + glNormal3fv((const GLfloat*)currnormal); + } + } + + if (texture) { + texcoords->send(texindices ? *texindices++ : texidx++, + vertexlist->get3(v3), + *currnormal); + } + + glVertex3fv((const GLfloat*) (coords3d + v3)); + + if (mbind == PER_VERTEX_INDEXED) + matindices++; + + if (nbind == PER_VERTEX_INDEXED) + normalindices++; + + if (texture && texindices) { + texindices++; + } + + trinr++; + if (pi == trinr) { + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + matindices++; + } + trinr = 0; + } + } + glEnd(); +} + + +#ifdef RENDER_GLARRAYS +//**************************************************************************** +// renderSimpleArray: normal and coord from vertex_array; +// no texture, color, highlight or selection but highet possible speed; +// all vertices written in one go! +// +void SoBrepFaceSet::renderSimpleArray() +{ + int cnt = index_array.size(); + + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, index_array.data()); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} +#endif + + +#ifdef RENDER_GLARRAYS +//**************************************************************************** +// renderColoredArray: normal and coord from vertex_array; +// no texture, highlight or selection but color / material array. +// needs to iterate over parts (i.e. geometry faces) +// +void SoBrepFaceSet::renderColoredArray(SoMaterialBundle *const materials) +{ + int num_parts = partIndex.getNum(); + int cnt = index_array.size(); + + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + const int32_t* ptr = index_array.data(); + + for (int part_id = 0; part_id < num_parts; part_id++) { + int tris = partIndex[part_id]; + + if (tris > 0) { + materials->send(part_id, TRUE); + glDrawElements(GL_TRIANGLES, 3 * tris, GL_UNSIGNED_INT, ptr); + ptr += 3 * tris; + } + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} +#endif + +#endif + diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.h b/src/Mod/Part/Gui/SoBrepFaceSet.h new file mode 100644 index 000000000..9259601a0 --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepFaceSet.h @@ -0,0 +1,128 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * 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 PARTGUI_SOBREPFACESET_H +#define PARTGUI_SOBREPFACESET_H +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SoGLCoordinateElement; +class SoTextureCoordinateBundle; + + +#define RENDER_GLARRAYS + +namespace PartGui { + +class VertexArray; + + +class PartGuiExport SoBrepFaceSet : public SoIndexedFaceSet { + typedef SoIndexedFaceSet inherited; + + SO_NODE_HEADER(SoBrepFaceSet); + +public: + static void initClass(); + SoBrepFaceSet(); + + SoMFInt32 partIndex; + SoSFInt32 highlightIndex; + SoMFInt32 selectionIndex; + +#ifdef RENDER_GLARRAYS + std::vector index_array; + std::vector vertex_array; +#endif + + enum Binding { + OVERALL = 0, + PER_PART, + PER_PART_INDEXED, + PER_FACE, + PER_FACE_INDEXED, + PER_VERTEX, + PER_VERTEX_INDEXED, + NONE = OVERALL + }; + +protected: + virtual ~SoBrepFaceSet(); + virtual void GLRender(SoGLRenderAction *action); + virtual void GLRenderBelowPath(SoGLRenderAction * action); + virtual void doAction(SoAction* action); + virtual SoDetail * createTriangleDetail( + SoRayPickAction * action, + const SoPrimitiveVertex * v1, + const SoPrimitiveVertex * v2, + const SoPrimitiveVertex * v3, + SoPickedPoint * pp); + virtual void generatePrimitives(SoAction * action); + +private: + Binding findMaterialBinding(SoState * const state) const; + Binding findNormalBinding(SoState * const state) const; + void renderHighlight(SoGLRenderAction *action); + void renderSelection(SoGLRenderAction *action); + + + // low-level render functions + + void renderShape(const SoGLCoordinateElement * const vertexlist, + const int32_t *vertexindices, + int num_vertexindices, + const int32_t *partindices, + int num_partindices, + const SbVec3f *normals, + const int32_t *normindices, + SoMaterialBundle *const materials, + const int32_t *matindices, + SoTextureCoordinateBundle * const texcoords, + const int32_t *texindices, + const int nbind, + const int mbind, + const int texture); + +#ifdef RENDER_GLARRAYS + void renderSimpleArray(); + void renderColoredArray(SoMaterialBundle *const materials); +#endif + +private: + SbColor selectionColor; + SbColor highlightColor; + SoColorPacker colorpacker; +}; + +} // namespace PartGui +#endif +#endif // PARTGUI_SOBREPFACESET_H + diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 7dc155b08..cf35e4a14 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -102,6 +102,7 @@ #include "ViewProviderExt.h" #include "SoBrepShape.h" +#include "SoBrepFaceSet.h" #include "TaskFaceColors.h" #include From a63e18f170a3edb32f830c443619cb00e727e63c Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 16 Jun 2013 14:13:20 -0300 Subject: [PATCH 4/5] Arch: Added preliminary dimensions tracking to walls --- src/Mod/Draft/DraftSnap.py | 55 ++++++++++++++++++++++++++++++---- src/Mod/Draft/DraftTrackers.py | 48 +++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 792f1c8be..24d6cdb08 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -71,11 +71,15 @@ class Snapper: self.constrainLine = None self.trackLine = None self.radiusTracker = None + self.dim1 = None + self.dim2 = None self.snapInfo = None self.lastSnappedObject = None + self.lastArchPoint = None self.active = True self.forceGridOff = False - self.trackers = [[],[],[],[],[]] # view, grid, snap, extline, radius + # the trackers are stored in lists because there can be several views, each with its own set + self.trackers = [[],[],[],[],[],[],[]] # view, grid, snap, extline, radius, dim1, dim2 self.polarAngles = [90,45] @@ -85,9 +89,9 @@ class Snapper: 'parallel':'circle', 'grid':'circle', 'endpoint':'dot', - 'midpoint':'dot', + 'midpoint':'square', 'perpendicular':'dot', - 'angle':'dot', + 'angle':'square', 'center':'dot', 'ortho':'dot', 'intersection':'dot'} @@ -172,6 +176,10 @@ class Snapper: self.extLine.off() if self.trackLine: self.trackLine.off() + if self.dim1: + self.dim1.off() + if self.dim2: + self.dim2.off() point = self.getApparentPoint(screenpos[0],screenpos[1]) @@ -199,6 +207,9 @@ class Snapper: if self.trackLine and lastpoint and (not noTracker): self.trackLine.p2(fp) self.trackLine.on() + # set the arch point tracking + if self.lastArchPoint: + self.setArchDims(self.lastArchPoint,fp) return fp else: @@ -242,7 +253,7 @@ class Snapper: snaps.extend(self.snapToPerpendicular(edge,lastpoint)) snaps.extend(self.snapToIntersection(edge)) snaps.extend(self.snapToElines(edge,eline)) - + elif obj.isDerivedFrom("Part::Feature"): if (not self.maxEdges) or (len(obj.Edges) <= self.maxEdges): if "Edge" in comp: @@ -326,7 +337,16 @@ class Snapper: self.trackLine.on() # set the cursor self.setCursor(winner[1]) - + + # set the arch point tracking + if self.lastArchPoint: + self.setArchDims(self.lastArchPoint,fp) + if Draft.getType(obj) == "Wall": + if self.lastArchPoint != fp: + self.lastArchPoint = fp + else: + self.lastArchPoint = None + # return the final point return fp @@ -643,6 +663,21 @@ class Snapper: nv = DraftVecUtils.project(dv,DraftGeomUtils.vec(edge)) np = (edge.Vertexes[0].Point).add(nv) return np + + def setArchDims(self,p1,p2): + "show arch dimensions between 2 points" + if not self.dim1: + self.dim1 = DraftTrackers.archDimTracker(mode=2) + if not self.dim2: + self.dim1 = DraftTrackers.archDimTracker(mode=3) + self.dim1.p1(p1) + self.dim2.p1(p1) + self.dim1.p2(p2) + self.dim2.p2(p2) + if self.dim1.Distance: + self.dim1.on() + if self.dim2.Distance: + self.dim2.on() def setCursor(self,mode=None): "setCursor(self,mode=None): sets or resets the cursor to the given mode or resets" @@ -686,6 +721,10 @@ class Snapper: self.extLine.off() if self.radiusTracker: self.radiusTracker.off() + if self.dim1: + self.dim1.off() + if self.dim2: + self.dim2.off() if self.grid: if not Draft.getParam("alwaysShowGrid"): self.grid.off() @@ -958,6 +997,8 @@ class Snapper: self.tracker = self.trackers[2][i] self.extLine = self.trackers[3][i] self.radiusTracker = self.trackers[4][i] + self.dim1 = self.trackers[5][i] + self.dim2 = self.trackers[6][i] else: if Draft.getParam("grid"): self.grid = DraftTrackers.gridTracker() @@ -966,11 +1007,15 @@ class Snapper: self.tracker = DraftTrackers.snapTracker() self.extLine = DraftTrackers.lineTracker(dotted=True) self.radiusTracker = DraftTrackers.radiusTracker() + self.dim1 = DraftTrackers.archDimTracker(mode=2) + self.dim2 = DraftTrackers.archDimTracker(mode=3) self.trackers[0].append(v) self.trackers[1].append(self.grid) self.trackers[2].append(self.tracker) self.trackers[3].append(self.extLine) self.trackers[4].append(self.radiusTracker) + self.trackers[5].append(self.dim1) + self.trackers[6].append(self.dim2) if self.grid and (not self.forceGridOff): self.grid.set() diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 570883c06..89b4d9935 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -784,3 +784,51 @@ class radiusTracker(Tracker): self.trans.translation.setValue([arg2.x,arg2.y,arg2.z]) else: self.sphere.radius.setValue(arg2) + +class archDimTracker(Tracker): + "A wrapper around a Sketcher dim" + def __init__(self,p1=FreeCAD.Vector(0,0,0),p2=FreeCAD.Vector(1,0,0),mode=1): + import SketcherGui + self.dimnode = coin.SoType.fromName("SoDatumLabel").createInstance() + p1node = coin.SbVec3f([p1.x,p1.y,p1.z]) + p2node = coin.SbVec3f([p2.x,p2.y,p2.z]) + self.dimnode.pnts.setValues([p1node,p2node]) + self.dimnode.lineWidth = 1 + color = FreeCADGui.draftToolBar.getDefaultColor("snap") + self.dimnode.textColor.setValue(coin.SbVec3f(color)) + self.setString() + self.setMode(mode) + Tracker.__init__(self,children=[self.dimnode]) + + def setString(self,text=None): + "sets the dim string to the given value or auto value" + self.dimnode.param1.setValue(.5) + p1 = Vector(self.dimnode.pnts.getValues()[0].getValue()) + p2 = Vector(self.dimnode.pnts.getValues()[-1].getValue()) + self.Distance = p2.sub(p1).Length + if not text: + text = Draft.getParam("dimPrecision") + text = "%."+str(text)+"f" + text = (text % self.Distance) + self.dimnode.string.setValue(text) + + def setMode(self,mode=1): + """sets the mode: 0 = without lines (a simple mark), 1 = + aligned (default), 2 = horizontal, 3 = vertical.""" + self.dimnode.datumtype.setValue(mode) + + def p1(self,point=None): + "sets or gets the first point of the dim" + if point: + self.dimnode.pnts.set1Value(0,point.x,point.y,point.z) + self.setString() + else: + return Vector(self.dimnode.pnts.getValues()[0].getValue()) + + def p2(self,point=None): + "sets or gets the second point of the dim" + if point: + self.dimnode.pnts.set1Value(1,point.x,point.y,point.z) + self.setString() + else: + return Vector(self.dimnode.pnts.getValues()[-1].getValue()) From d26ffbe9aa1ccf17b964b646ee2f70124b71300e Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 16 Jun 2013 20:06:14 -0300 Subject: [PATCH 5/5] Arch: misc improvements + Further work on snap tracking dims + Better snap for structures + Corrected initial temp shape of structures + Added a box with wall length (still readonly) --- src/Mod/Arch/ArchStructure.py | 3 +++ src/Mod/Arch/ArchWall.py | 16 ++++++++++++++++ src/Mod/Draft/DraftSnap.py | 20 +++++++++++++++++--- src/Mod/Draft/DraftTrackers.py | 8 +++++++- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 14a9a3f80..379730903 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -97,6 +97,9 @@ class _CommandStructure: import DraftTrackers self.points = [] self.tracker = DraftTrackers.boxTracker() + self.tracker.width(self.Width) + self.tracker.height(self.Height) + self.tracker.length(self.Length) self.tracker.on() FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox()) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 91d3f26f6..9fd625b82 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -136,6 +136,7 @@ class _CommandWall: self.Width = 0.1 self.Height = 1 self.Align = "Center" + self.Length = None self.continueCmd = False p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") self.JOIN_WALLS = p.GetBool("joinWallSketches") @@ -223,12 +224,24 @@ class _CommandWall: else: dv = DraftVecUtils.neg(dv) self.tracker.update([b.add(dv),point.add(dv)]) + if self.Length: + self.Length.setValue(bv.Length) def taskbox(self): "sets up a taskbox widget" w = QtGui.QWidget() w.setWindowTitle(str(translate("Arch","Wall options"))) lay0 = QtGui.QVBoxLayout(w) + + lay5 = QtGui.QHBoxLayout() + lay0.addLayout(lay5) + label5 = QtGui.QLabel(str(translate("Arch","Length"))) + lay5.addWidget(label5) + self.Length = QtGui.QDoubleSpinBox() + self.Length.setDecimals(2) + self.Length.setValue(0.00) + lay5.addWidget(self.Length) + lay1 = QtGui.QHBoxLayout() lay0.addLayout(lay1) label1 = QtGui.QLabel(str(translate("Arch","Width"))) @@ -237,6 +250,7 @@ class _CommandWall: value1.setDecimals(2) value1.setValue(self.Width) lay1.addWidget(value1) + lay2 = QtGui.QHBoxLayout() lay0.addLayout(lay2) label2 = QtGui.QLabel(str(translate("Arch","Height"))) @@ -245,6 +259,7 @@ class _CommandWall: value2.setDecimals(2) value2.setValue(self.Height) lay2.addWidget(value2) + lay3 = QtGui.QHBoxLayout() lay0.addLayout(lay3) label3 = QtGui.QLabel(str(translate("Arch","Alignment"))) @@ -254,6 +269,7 @@ class _CommandWall: value3.addItems(items) value3.setCurrentIndex(items.index(self.Align)) lay3.addWidget(value3) + value4 = QtGui.QCheckBox(str(translate("Arch","Continue"))) lay0.addWidget(value4) QtCore.QObject.connect(value1,QtCore.SIGNAL("valueChanged(double)"),self.setWidth) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 24d6cdb08..685bce591 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -242,6 +242,7 @@ class Snapper: comp = self.snapInfo['Component'] if (Draft.getType(obj) == "Wall") and not oldActive: + # special snapping for wall: only to its base shape (except when CTRL is pressed) edges = [] for o in [obj]+obj.Additions: if Draft.getType(o) == "Wall": @@ -253,6 +254,19 @@ class Snapper: snaps.extend(self.snapToPerpendicular(edge,lastpoint)) snaps.extend(self.snapToIntersection(edge)) snaps.extend(self.snapToElines(edge,eline)) + + elif (Draft.getType(obj) == "Structure") and not oldActive: + # special snapping for struct: only to its base point (except when CTRL is pressed) + if obj.Base: + for edge in o.Base.Shape.Edges: + snaps.extend(self.snapToEndpoints(edge)) + snaps.extend(self.snapToMidpoint(edge)) + snaps.extend(self.snapToPerpendicular(edge,lastpoint)) + snaps.extend(self.snapToIntersection(edge)) + snaps.extend(self.snapToElines(edge,eline)) + else: + b = obj.Placement.Base + snaps.append([b,'endpoint',b]) elif obj.isDerivedFrom("Part::Feature"): if (not self.maxEdges) or (len(obj.Edges) <= self.maxEdges): @@ -341,9 +355,8 @@ class Snapper: # set the arch point tracking if self.lastArchPoint: self.setArchDims(self.lastArchPoint,fp) - if Draft.getType(obj) == "Wall": - if self.lastArchPoint != fp: - self.lastArchPoint = fp + if Draft.getType(obj) in ["Wall","Structure"]: + self.lastArchPoint = winner[2] else: self.lastArchPoint = None @@ -734,6 +747,7 @@ class Snapper: if Draft.getParam("hideSnapBar"): self.toolbar.hide() self.mask = None + self.lastArchPoint = None def constrain(self,point,basepoint=None,axis=None): '''constrain(point,basepoint=None,axis=None: Returns a diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 89b4d9935..f672cad5b 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -805,7 +805,13 @@ class archDimTracker(Tracker): self.dimnode.param1.setValue(.5) p1 = Vector(self.dimnode.pnts.getValues()[0].getValue()) p2 = Vector(self.dimnode.pnts.getValues()[-1].getValue()) - self.Distance = p2.sub(p1).Length + m = self.dimnode.datumtype.getValue() + if m == 2: + self.Distance = (DraftVecUtils.project(p2.sub(p1),Vector(1,0,0))).Length + elif m == 3: + self.Distance = (DraftVecUtils.project(p2.sub(p1),Vector(0,1,0))).Length + else: + self.Distance = (p2.sub(p1)).Length if not text: text = Draft.getParam("dimPrecision") text = "%."+str(text)+"f"