/**************************************************************************** * Copyright (c) 2017 Zheng, Lei (realthunder) * * * * 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 "FeatureArea.h" #include "FeatureAreaPy.h" #include #include #include FC_LOG_LEVEL_INIT("Path.Area",true,true) using namespace Path; PROPERTY_SOURCE(Path::FeatureArea, Part::Feature) PARAM_ENUM_STRING_DECLARE(static const char *Enums,AREA_PARAMS_ALL) FeatureArea::FeatureArea() :myInited(false) { ADD_PROPERTY(Sources,(0)); ADD_PROPERTY(WorkPlane,(TopoDS_Shape())); PARAM_PROP_ADD("Area",AREA_PARAMS_OPCODE); PARAM_PROP_ADD("Area",AREA_PARAMS_BASE); PARAM_PROP_ADD("Offset",AREA_PARAMS_OFFSET); PARAM_PROP_ADD("Offset", AREA_PARAMS_OFFSET_CONF); PARAM_PROP_ADD("Pocket",AREA_PARAMS_POCKET); PARAM_PROP_ADD("Pocket",AREA_PARAMS_POCKET_CONF); PARAM_PROP_ADD("Section",AREA_PARAMS_SECTION); PARAM_PROP_ADD("libarea",AREA_PARAMS_CAREA); PARAM_PROP_SET_ENUM(Enums,AREA_PARAMS_ALL); PocketMode.setValue((long)0); } FeatureArea::~FeatureArea() { } Area &FeatureArea::getArea() { if(!myInited) execute(); return myArea; } App::DocumentObjectExecReturn *FeatureArea::execute(void) { myInited = true; std::vector links = Sources.getValues(); if (links.empty()) return new App::DocumentObjectExecReturn("No shapes linked"); for (std::vector::iterator it = links.begin(); it != links.end(); ++it) { if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId()))) return new App::DocumentObjectExecReturn("Linked object is not a Part object (has no Shape)."); TopoDS_Shape shape = static_cast(*it)->Shape.getShape().getShape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); } FC_TIME_INIT(t); AreaParams params; #define AREA_PROP_GET(_param) \ params.PARAM_FNAME(_param) = PARAM_FNAME(_param).getValue(); PARAM_FOREACH(AREA_PROP_GET,AREA_PARAMS_CONF) myArea.clean(true); myArea.setParams(params); TopoDS_Shape workPlane = WorkPlane.getShape().getShape(); myArea.setPlane(workPlane); for (std::vector::iterator it = links.begin(); it != links.end(); ++it) { myArea.add(static_cast(*it)->Shape.getShape().getShape(), PARAM_PROP_ARGS(AREA_PARAMS_OPCODE)); } myShapes.clear(); if(myArea.getSectionCount()==0) myShapes.push_back(myArea.getShape(-1)); else { myShapes.reserve(myArea.getSectionCount()); for(int i=0;i<(int)myArea.getSectionCount();++i) myShapes.push_back(myArea.getShape(i)); } bool hasShape = false; if(myShapes.empty()) Shape.setValue(TopoDS_Shape()); else{ // compound is built even if there is only one shape to save the // trouble of messing around with placement BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); for(auto &shape : myShapes) { if(shape.IsNull()) continue; hasShape = true; builder.Add(compound,shape); } Shape.setValue(compound); } FC_TIME_LOG(t,"feature execute"); if(!hasShape) return new App::DocumentObjectExecReturn("no output shape"); return DocumentObject::StdReturn; } const std::vector &FeatureArea::getShapes() { getArea(); return myShapes; } short FeatureArea::mustExecute(void) const { if(myInited && !myArea.isBuilt()) return 1; return Part::Feature::mustExecute(); } PyObject *FeatureArea::getPyObject() { if (PythonObject.is(Py::_None())){ // ref counter is set to 1 PythonObject = Py::Object(new FeatureAreaPy(this),true); } return Py::new_reference_to(PythonObject); } // FeatureAreaView ------------------------------------------------------------- // PROPERTY_SOURCE(Path::FeatureAreaView, Part::Feature) FeatureAreaView::FeatureAreaView() { ADD_PROPERTY(Source,(0)); ADD_PROPERTY_TYPE(SectionIndex,(0),"Section",App::Prop_None,"The start index of the section to show, negative value for reverse index from bottom"); ADD_PROPERTY_TYPE(SectionCount,(1),"Section",App::Prop_None,"Number of sections to show, 0 to show all section starting from SectionIndex"); } std::list FeatureAreaView::getShapes() { std::list shapes; App::DocumentObject* pObj = Source.getValue(); if (!pObj) return shapes; if(!pObj->isDerivedFrom(FeatureArea::getClassTypeId())) return shapes; auto all_shapes = static_cast(pObj)->getShapes(); if(all_shapes.empty()) return shapes; int index=SectionIndex.getValue(),count=SectionCount.getValue(); if(index<0) { index += ((int)all_shapes.size()); if(index<0) return shapes; if(count<=0 || index+1-count<0) { count = index+1; index = 0; }else index -= count-1; }else if(index >= (int)all_shapes.size()) return shapes; if(count<=0) count = all_shapes.size(); count += index; if(count>(int)all_shapes.size()) count = all_shapes.size(); for(int i=index;iisDerivedFrom(FeatureArea::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a FeatureArea"); bool hasShape = false; std::list shapes = getShapes(); if(shapes.empty()) Shape.setValue(TopoDS_Shape()); else{ BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); for(auto &shape : shapes) { if(shape.IsNull()) continue; hasShape = true; builder.Add(compound,shape); } Shape.setValue(compound); } if(!hasShape) return new App::DocumentObjectExecReturn("no output shape"); return DocumentObject::StdReturn; } // Python feature --------------------------------------------------------- namespace App { /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(Path::FeatureAreaPython, Path::FeatureArea) PROPERTY_SOURCE_TEMPLATE(Path::FeatureAreaViewPython, Path::FeatureAreaView) template<> const char* Path::FeatureAreaPython::getViewProviderName(void) const { return "PathGui::ViewProviderAreaPython"; } template<> const char* Path::FeatureAreaViewPython::getViewProviderName(void) const { return "PathGui::ViewProviderAreaViewPython"; } /// @endcond // explicit template instantiation template class PathExport FeaturePythonT; }