Path changes

* Relaxed valid base shape requirement, as long as it can return a
  shape using part.getShape()

* Improve ViewProviderPath performance by sharing the same selection
  observer

* Relocate libarea binary installation
This commit is contained in:
Zheng, Lei
2019-07-13 21:34:43 +08:00
committed by wmayer
parent 435815ccc8
commit d93259e238
7 changed files with 97 additions and 65 deletions

View File

@@ -40,6 +40,7 @@
#include <Mod/Part/App/OCCError.h>
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/TopoShapePy.h>
#include <Mod/Part/App/PartPyCXX.h>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Edge.hxx>
@@ -94,10 +95,6 @@
PyErr_SetString(Base::BaseExceptionFreeCADError,e); \
} throw Py::Exception();
namespace Part {
extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape);
}
namespace Path {
class Module : public Py::ExtensionModule<Module>
{

View File

@@ -35,13 +35,10 @@
#include <Base/Console.h>
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/PartPyCXX.h>
#include "Path.h"
#include "AreaParams.h"
namespace Part {
extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape);
}
class CArea;
class CCurve;
class Bnd_Box;

View File

@@ -43,6 +43,8 @@
# include <QFile>
#endif
#include <boost/algorithm/string/replace.hpp>
#include "ViewProviderPath.h"
#include <Mod/Path/App/FeaturePath.h>
@@ -53,6 +55,7 @@
#include <Base/Stream.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/SoFCBoundingBox.h>
#include <Gui/SoAxisCrossKit.h>
@@ -75,6 +78,72 @@ using namespace PathGui;
using namespace Path;
using namespace PartGui;
namespace PathGui {
class PathSelectionObserver: public Gui::SelectionObserver {
public:
static void init() {
static PathSelectionObserver *instance;
if(!instance)
instance = new PathSelectionObserver();
}
void setArrow(SoSwitch *pcSwitch=0) {
if(pcSwitch==pcLastArrowSwitch)
return;
if(pcLastArrowSwitch) {
pcLastArrowSwitch->whichChild = -1;
pcLastArrowSwitch->unref();
pcLastArrowSwitch = 0;
}
if(pcSwitch) {
pcSwitch->ref();
pcSwitch->whichChild = 0;
pcLastArrowSwitch = pcSwitch;
}
}
void onSelectionChanged(const Gui::SelectionChanges& msg) {
if(msg.Type == Gui::SelectionChanges::RmvPreselect) {
setArrow();
return;
}
if((msg.Type!=Gui::SelectionChanges::SetPreselect
&& msg.Type!=Gui::SelectionChanges::MovePreselect)
|| !msg.pOriginalMsg || !msg.pSubObject || !msg.pParentObject)
return;
Base::Matrix4D linkMat;
auto sobj = msg.pSubObject->getLinkedObject(true,&linkMat,false);
auto vp = Base::freecad_dynamic_cast<ViewProviderPath>(
Application::Instance->getViewProvider(sobj));
if(!vp) {
setArrow();
return;
}
if(vp->pt0Index >= 0) {
Base::Matrix4D mat;
msg.pParentObject->getSubObject(msg.pSubName,0,&mat);
mat *= linkMat;
mat.inverse();
Base::Vector3d pt = mat*Base::Vector3d(msg.x,msg.y,msg.z);
const SbVec3f &ptTo = *vp->pcLineCoords->point.getValues(vp->pt0Index);
SbVec3f ptFrom(pt.x,pt.y,pt.z);
if(ptFrom != ptTo) {
vp->pcArrowTransform->pointAt(ptFrom,ptTo);
setArrow(vp->pcArrowSwitch);
return;
}
}
setArrow();
}
SoSwitch *pcLastArrowSwitch = 0;
};
}
//////////////////////////////////////////////////////////////////////////////
PROPERTY_SOURCE(PathGui::ViewProviderPath, Gui::ViewProviderGeometryObject)
ViewProviderPath::ViewProviderPath()
@@ -171,6 +240,8 @@ ViewProviderPath::ViewProviderPath()
SelectionStyle.setEnums(SelectionStyleEnum);
unsigned long sstyle = hGrp->GetInt("DefaultSelectionStyle",0);
SelectionStyle.setValue(sstyle);
PathSelectionObserver::init();
}
ViewProviderPath::~ViewProviderPath()
@@ -249,7 +320,7 @@ std::string ViewProviderPath::getElement(const SoDetail* detail) const
pt0Index = line_detail->getPoint0()->getCoordinateIndex();
if(pt0Index<0 || pt0Index>=pcLineCoords->point.getNum())
pt0Index = -1;
return str.str();
return boost::replace_all_copy(str.str(),".",",");
}
}
}
@@ -272,31 +343,6 @@ SoDetail* ViewProviderPath::getDetail(const char* subelement) const
return detail;
}
void ViewProviderPath::onSelectionChanged(const Gui::SelectionChanges& msg) {
if(msg.Type == Gui::SelectionChanges::SetPreselect && msg.pSubName &&
pt0Index >= 0 && getObject() && getObject()->getDocument())
{
const char *docName = getObject()->getDocument()->getName();
const char *objName = getObject()->getNameInDocument();
if(docName && objName &&
strcmp(msg.pDocName,docName)==0 &&
strcmp(msg.pObjectName,objName)==0)
{
Path::Feature* pcPathObj = static_cast<Path::Feature*>(pcObject);
Base::Vector3d pt = pcPathObj->Placement.getValue().inverse().toMatrix()*
Base::Vector3d(msg.x,msg.y,msg.z);
const SbVec3f &ptTo = *pcLineCoords->point.getValues(pt0Index);
SbVec3f ptFrom(pt.x,pt.y,pt.z);
if(ptFrom != ptTo) {
pcArrowTransform->pointAt(ptFrom,ptTo);
pcArrowSwitch->whichChild = 0;
return;
}
}
}
pcArrowSwitch->whichChild = -1;
}
void ViewProviderPath::onChanged(const App::Property* prop)
{
if(blockPropertyChange) return;

View File

@@ -42,8 +42,9 @@ class SoSwitch;
namespace PathGui
{
class PathSelectionObserver;
class PathGuiExport ViewProviderPath : public Gui::ViewProviderGeometryObject
, public Gui::SelectionObserver
{
PROPERTY_HEADER(PathGui::ViewProviderPath);
typedef ViewProviderGeometryObject inherited;
@@ -78,14 +79,14 @@ public:
virtual std::string getElement(const SoDetail *) const;
SoDetail* getDetail(const char* subelement) const;
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);
void updateShowConstraints();
void updateVisual(bool rebuild = false);
void hideSelection();
virtual void showBoundingBox(bool show);
friend class PathSelectionObserver;
protected:
virtual void onChanged(const App::Property* prop);

View File

@@ -104,15 +104,18 @@ class _CommandSelectLoop:
FreeCADGui.Selection.addSelection(obj, "Edge" + str(elist.index(e) + 1))
def formsPartOfALoop(self, obj, sub, names):
if names[0][0:4] != 'Edge':
if names[0][0:4] == 'Face' and horizontalFaceLoop(obj, sub, names):
try:
if names[0][0:4] != 'Edge':
if names[0][0:4] == 'Face' and horizontalFaceLoop(obj, sub, names):
return True
return False
if len(names) == 1 and horizontalEdgeLoop(obj, sub):
return True
return False
if len(names) == 1 and horizontalEdgeLoop(obj, sub):
if len(names) == 1 or names[1][0:4] != 'Edge':
return False
return True
if len(names) == 1 or names[1][0:4] != 'Edge':
except Exception:
return False
return True
if FreeCAD.GuiUp:

View File

@@ -53,31 +53,20 @@ def isValidBaseObject(obj):
# Can't link to anything inside a geo feature group anymore
PathLog.debug("%s is inside a geo feature group" % obj.Label)
return False
if hasattr(obj, 'TypeId') and 'App::Part' == obj.TypeId:
return obj.Group and any(hasattr(o, 'Shape') for o in obj.Group)
if not hasattr(obj, 'Shape'):
PathLog.debug("%s has no shape" % obj.Label)
return False
if obj.TypeId in NotValidBaseTypeIds:
PathLog.debug("%s is blacklisted (%s)" % (obj.Label, obj.TypeId))
return False
if hasattr(obj, 'Sheets') or hasattr(obj, 'TagText'): # Arch.Panels and Arch.PanelCut
PathLog.debug("%s is not an Arch.Panel" % (obj.Label))
return False
return True
import Part
return not Part.getShape(obj).isNull()
def isSolid(obj):
'''isSolid(obj) ... return True if the object is a valid solid.'''
if hasattr(obj, 'Tip'):
return isSolid(obj.Tip)
if hasattr(obj, 'Shape'):
if obj.Shape.Volume > 0.0 and obj.Shape.isClosed():
return True
if hasattr(obj, 'TypeId') and 'App::Part' == obj.TypeId:
if not obj.Group or any(hasattr(o, 'Shape') and not isSolid(o) for o in obj.Group):
return False
return True
return False
import Part
shape = Part.getShape(obj)
return not shape.isNull() and shape.Volume and shape.isClosed()
def toolControllerForOp(op):
'''toolControllerForOp(op) ... return the tool controller used by the op.

View File

@@ -98,7 +98,7 @@ add_library(
add_library(
area
MODULE
SHARED
${PYAREA_SRC}
)
@@ -151,7 +151,7 @@ else(MSVC)
endif(MSVC)
target_link_libraries(area-native ${area_native_LIBS})
SET_BIN_DIR(area-native area-native)
SET_BIN_DIR(area-native area-native /Mod/Path)
target_link_libraries(area area-native ${area_LIBS} ${area_native_LIBS})
@@ -161,7 +161,7 @@ if(NOT BUILD_DYNAMIC_LINK_PYTHON AND CMAKE_COMPILER_IS_CLANGXX)
target_link_libraries(area "-Wl,-undefined,dynamic_lookup")
endif()
SET_BIN_DIR(area area)
SET_BIN_DIR(area area /Mod/Path)
SET_PYTHON_PREFIX_SUFFIX(area)
# this figures out where to install the Python modules
@@ -176,12 +176,11 @@ message(STATUS "area module (for Path Workbench) will be installed to: " ${CMAKE
if(WIN32)
set_target_properties(area-native PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
INSTALL(TARGETS area-native
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
else(WIN32)
INSTALL(TARGETS area-native
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endif(WIN32)