Download src/Mod/PartDesign/App/FeatureChamfer.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 11 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/PartDesign/App/FeatureChamfer.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/PartDesign/App/FeatureChamfer.cpp
-
curl -L -o FeatureChamfer.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/PartDesign/App/FeatureChamfer.cpp
11 kB
| /*************************************************************************** | |
| * Copyright (c) 2010 Juergen Riegel <FreeCAD@juergen-riegel.net> * | |
| * * | |
| * 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 * | |
| * * | |
| ***************************************************************************/ | |
| using namespace PartDesign; | |
| PROPERTY_SOURCE(PartDesign::Chamfer, PartDesign::DressUp) | |
| const char* ChamferTypeEnums[] = {"Equal distance", "Two distances", "Distance and Angle", nullptr}; | |
| const App::PropertyQuantityConstraint::Constraints Chamfer::floatSize | |
| = {0.0, std::numeric_limits<float>::max(), 0.1}; | |
| const App::PropertyAngle::Constraints Chamfer::floatAngle = {0.0, 180.0, 1.0}; | |
| static App::DocumentObjectExecReturn* validateParameters( | |
| int chamferType, | |
| double size, | |
| double size2, | |
| double angle | |
| ); | |
| Chamfer::Chamfer() | |
| { | |
| ADD_PROPERTY_TYPE(ChamferType, (0L), "Chamfer", App::Prop_None, "Type of chamfer"); | |
| ChamferType.setEnums(ChamferTypeEnums); | |
| ADD_PROPERTY_TYPE(Size, (1.0), "Chamfer", App::Prop_None, "Size of chamfer"); | |
| Size.setUnit(Base::Unit::Length); | |
| Size.setConstraints(&floatSize); | |
| ADD_PROPERTY_TYPE(Size2, (1.0), "Chamfer", App::Prop_None, "Second size of chamfer"); | |
| Size2.setUnit(Base::Unit::Length); | |
| Size2.setConstraints(&floatSize); | |
| ADD_PROPERTY_TYPE(Angle, (45.0), "Chamfer", App::Prop_None, "Angle of chamfer"); | |
| Angle.setUnit(Base::Unit::Angle); | |
| Angle.setConstraints(&floatAngle); | |
| ADD_PROPERTY_TYPE(FlipDirection, (false), "Chamfer", App::Prop_None, "Flip direction"); | |
| ADD_PROPERTY_TYPE( | |
| UseAllEdges, | |
| (false), | |
| "Chamfer", | |
| App::Prop_None, | |
| "Chamfer all edges if true, else use only those edges in Base property.\n" | |
| "If true, then this overrides any edge changes made to the Base property or in the " | |
| "dialog.\n" | |
| ); | |
| updateProperties(); | |
| } | |
| short Chamfer::mustExecute() const | |
| { | |
| bool touched = false; | |
| auto chamferType = ChamferType.getValue(); | |
| switch (chamferType) { | |
| case 0: // "Equal distance" | |
| touched = Size.isTouched() || ChamferType.isTouched(); | |
| break; | |
| case 1: // "Two distances" | |
| touched = Size.isTouched() || ChamferType.isTouched() || Size2.isTouched(); | |
| break; | |
| case 2: // "Distance and Angle" | |
| touched = Size.isTouched() || ChamferType.isTouched() || Angle.isTouched(); | |
| break; | |
| } | |
| if (Placement.isTouched() || touched) { | |
| return 1; | |
| } | |
| return DressUp::mustExecute(); | |
| } | |
| App::DocumentObjectExecReturn* Chamfer::execute() | |
| { | |
| if (onlyHaveRefined()) { | |
| return App::DocumentObject::StdReturn; | |
| } | |
| // NOTE: Normally the Base property and the BaseFeature property should point to the same object. | |
| // The only difference is that the Base property also stores the edges that are to be chamfered | |
| Part::TopoShape TopShape; | |
| try { | |
| TopShape = getBaseTopoShape(); | |
| } | |
| catch (Base::Exception& e) { | |
| return new App::DocumentObjectExecReturn(e.what()); | |
| } | |
| TopShape.setTransform(Base::Matrix4D()); | |
| auto edges = UseAllEdges.getValue() ? TopShape.getSubTopoShapes(TopAbs_EDGE) | |
| : getContinuousEdges(TopShape); | |
| if (edges.empty()) { | |
| return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "No edges specified")); | |
| } | |
| const int chamferType = ChamferType.getValue(); | |
| const double size = Size.getValue(); | |
| double size2 = Size2.getValue(); | |
| const double angle = Angle.getValue(); | |
| const bool flipDirection = FlipDirection.getValue(); | |
| auto res = validateParameters(chamferType, size, size2, angle); | |
| if (res != App::DocumentObject::StdReturn) { | |
| return res; | |
| } | |
| this->positionByBaseFeature(); | |
| if (static_cast<Part::ChamferType>(chamferType) == Part::ChamferType::distanceAngle) { | |
| size2 = angle; | |
| } | |
| try { | |
| TopoShape shape(0); | |
| shape.makeElementChamfer( | |
| TopShape, | |
| edges, | |
| static_cast<Part::ChamferType>(chamferType), | |
| size, | |
| size2, | |
| nullptr, | |
| flipDirection ? Part::Flip::flip : Part::Flip::none | |
| ); | |
| if (shape.isNull()) { | |
| return new App::DocumentObjectExecReturn( | |
| QT_TRANSLATE_NOOP("Exception", "Failed to create chamfer") | |
| ); | |
| } | |
| TopTools_ListOfShape aLarg; | |
| aLarg.Append(TopShape.getShape()); | |
| if (!BRepAlgo::IsValid(aLarg, shape.getShape(), Standard_False, Standard_False)) { | |
| ShapeFix_ShapeTolerance aSFT; | |
| aSFT.LimitTolerance( | |
| shape.getShape(), | |
| Precision::Confusion(), | |
| Precision::Confusion(), | |
| TopAbs_SHAPE | |
| ); | |
| } | |
| // store shape before refinement | |
| this->rawShape = shape; | |
| shape = refineShapeIfActive(shape); | |
| if (!isSingleSolidRuleSatisfied(shape.getShape())) { | |
| return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP( | |
| "Exception", | |
| "Result has multiple solids: enable 'Allow Compound' in the active body." | |
| )); | |
| } | |
| shape = getSolid(shape); | |
| this->Shape.setValue(shape); | |
| return App::DocumentObject::StdReturn; | |
| } | |
| catch (Standard_Failure& e) { | |
| return new App::DocumentObjectExecReturn(e.GetMessageString()); | |
| } | |
| } | |
| void Chamfer::Restore(Base::XMLReader& reader) | |
| { | |
| DressUp::Restore(reader); | |
| migrateFlippedProperties(reader); | |
| } | |
| void Chamfer::handleChangedPropertyType(Base::XMLReader& reader, const char* TypeName, App::Property* prop) | |
| { | |
| if (prop && strcmp(TypeName, "App::PropertyFloatConstraint") == 0 | |
| && strcmp(prop->getTypeId().getName(), "App::PropertyQuantityConstraint") == 0) { | |
| App::PropertyFloatConstraint p; | |
| p.Restore(reader); | |
| static_cast<App::PropertyQuantityConstraint*>(prop)->setValue(p.getValue()); | |
| } | |
| else { | |
| DressUp::handleChangedPropertyType(reader, TypeName, prop); | |
| } | |
| } | |
| bool Chamfer::requiresSizeSwapping(const Base::XMLReader& reader) const | |
| { | |
| return Base::getVersion(reader.ProgramVersion) < Base::Version::v1_0 | |
| && (ChamferType.getValue() == 1 || ChamferType.getValue() == 2); | |
| } | |
| void Chamfer::migrateFlippedProperties(const Base::XMLReader& reader) | |
| { | |
| if (!requiresSizeSwapping(reader)) { | |
| return; | |
| } | |
| Base::Console().warning( | |
| "The 'FlipDirection' property of the chamfer of %s is being adjusted to maintain" | |
| "the same geometry in this FreeCAD version. If the re-saved file is later opened " | |
| "in FreeCAD 0.21.x the chamfer result may differ due to the changed parameter " | |
| "interpretation.\n", | |
| getFullName() | |
| ); | |
| FlipDirection.setValue(!FlipDirection.getValue()); | |
| } | |
| void Chamfer::onChanged(const App::Property* prop) | |
| { | |
| if (prop == &ChamferType) { | |
| updateProperties(); | |
| } | |
| DressUp::onChanged(prop); | |
| } | |
| void Chamfer::updateProperties() | |
| { | |
| auto chamferType = ChamferType.getValue(); | |
| auto disableproperty = [](App::Property* prop, bool on) { | |
| prop->setStatus(App::Property::ReadOnly, on); | |
| }; | |
| switch (chamferType) { | |
| case 0: // "Equal distance" | |
| disableproperty(&this->Angle, true); | |
| disableproperty(&this->Size2, true); | |
| break; | |
| case 1: // "Two distances" | |
| disableproperty(&this->Angle, true); | |
| disableproperty(&this->Size2, false); | |
| break; | |
| case 2: // "Distance and Angle" | |
| disableproperty(&this->Angle, false); | |
| disableproperty(&this->Size2, true); | |
| break; | |
| } | |
| } | |
| static App::DocumentObjectExecReturn* validateParameters( | |
| int chamferType, | |
| double size, | |
| double size2, | |
| double angle | |
| ) | |
| { | |
| // Size is common to all chamfer types. | |
| if (size <= 0) { | |
| return new App::DocumentObjectExecReturn( | |
| QT_TRANSLATE_NOOP("Exception", "Size must be greater than zero") | |
| ); | |
| } | |
| switch (chamferType) { | |
| case 0: // Equal distance | |
| // Nothing to do. | |
| break; | |
| case 1: // Two distances | |
| if (size2 <= 0) { | |
| return new App::DocumentObjectExecReturn( | |
| QT_TRANSLATE_NOOP("Exception", "Size2 must be greater than zero") | |
| ); | |
| } | |
| break; | |
| case 2: // Distance and angle | |
| if (angle <= 0 || angle >= 180.0) { | |
| return new App::DocumentObjectExecReturn( | |
| QT_TRANSLATE_NOOP("Exception", "Angle must be greater than 0 and less than 180") | |
| ); | |
| } | |
| break; | |
| } | |
| return App::DocumentObject::StdReturn; | |
| } | |