Part: Revolve: add support for axis link and midplane
Changes on the App side only. Added two properties: * AxisLink (accepts an edge - line or arc of circle) * Symmetric (for distributing the revolution symmetrically in both directions)
This commit is contained in:
parent
8b3f8cc9e6
commit
779b7eedb2
|
@ -24,11 +24,17 @@
|
|||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <gp_Ax1.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <gp_Circ.hxx>
|
||||
#endif
|
||||
|
||||
|
||||
#include "FeatureRevolution.h"
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <App/Application.h>
|
||||
|
||||
using namespace Part;
|
||||
|
||||
|
@ -38,13 +44,14 @@ PROPERTY_SOURCE(Part::Revolution, Part::Feature)
|
|||
|
||||
Revolution::Revolution()
|
||||
{
|
||||
//*** why not ADD_PROPERTY_TYPE??
|
||||
ADD_PROPERTY(Source,(0));
|
||||
ADD_PROPERTY(Base,(Base::Vector3d(0.0,0.0,0.0)));
|
||||
ADD_PROPERTY(Axis,(Base::Vector3d(0.0,0.0,1.0)));
|
||||
ADD_PROPERTY(Angle,(360.0));
|
||||
ADD_PROPERTY_TYPE(Solid,(false),"Base",App::Prop_None,"Make revolution a solid if possible");
|
||||
ADD_PROPERTY_TYPE(Source,(0), "Revolve", App::Prop_None, "Shape to revolve");
|
||||
ADD_PROPERTY_TYPE(Base,(Base::Vector3d(0.0,0.0,0.0)), "Revolve", App::Prop_None, "Base point of revolution axis");
|
||||
ADD_PROPERTY_TYPE(Axis,(Base::Vector3d(0.0,0.0,1.0)), "Revolve", App::Prop_None, "Direction of revolution axis");
|
||||
ADD_PROPERTY_TYPE(AxisLink,(0),"Revolve",App::Prop_None,"Link to edge to use as revolution axis.");
|
||||
ADD_PROPERTY_TYPE(Angle,(360.0), "Revolve", App::Prop_None, "Angle span of revolution. If angle is zero, and an arc is used for axis link, angle span of arc will be used.");
|
||||
Angle.setConstraints(&angleRangeU);
|
||||
ADD_PROPERTY_TYPE(Symmetric,(false),"Revolve",App::Prop_None,"Extend revolution symmetrically from the profile.");
|
||||
ADD_PROPERTY_TYPE(Solid,(false),"Revolve",App::Prop_None,"Make revolution a solid if possible");
|
||||
}
|
||||
|
||||
short Revolution::mustExecute() const
|
||||
|
@ -53,11 +60,75 @@ short Revolution::mustExecute() const
|
|||
Axis.isTouched() ||
|
||||
Angle.isTouched() ||
|
||||
Source.isTouched() ||
|
||||
Solid.isTouched())
|
||||
Solid.isTouched() ||
|
||||
AxisLink.isTouched() ||
|
||||
Symmetric.isTouched())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setReadonlyness(App::Property &prop, bool on)
|
||||
{
|
||||
unsigned long status = prop.getStatus();
|
||||
prop.setStatus(App::Property::ReadOnly, on);
|
||||
if (status != prop.getStatus())
|
||||
App::GetApplication().signalChangePropertyEditor(prop);
|
||||
}
|
||||
|
||||
void Revolution::onChanged(const App::Property* prop)
|
||||
{
|
||||
if(! this->isRestoring()){
|
||||
if(prop == &AxisLink){
|
||||
setReadonlyness(Base, AxisLink.getValue() != nullptr);
|
||||
setReadonlyness(Axis, AxisLink.getValue() != nullptr);
|
||||
}
|
||||
}
|
||||
Part::Feature::onChanged(prop);
|
||||
}
|
||||
|
||||
bool Revolution::fetchAxisLink(const App::PropertyLinkSub &axisLink,
|
||||
Base::Vector3d& center,
|
||||
Base::Vector3d& dir,
|
||||
double& angle)
|
||||
{
|
||||
if (!axisLink.getValue())
|
||||
return false;
|
||||
|
||||
if (!axisLink.getValue()->isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
throw Base::TypeError("AxisLink has no OCC shape");
|
||||
|
||||
Part::Feature* linked = static_cast<Part::Feature*>(axisLink.getValue());
|
||||
|
||||
TopoDS_Shape axEdge;
|
||||
if (axisLink.getSubValues().size() > 0 && axisLink.getSubValues()[0].length() > 0){
|
||||
axEdge = linked->Shape.getShape().getSubShape(axisLink.getSubValues()[0].c_str());
|
||||
} else {
|
||||
axEdge = linked->Shape.getValue();
|
||||
}
|
||||
|
||||
if (axEdge.IsNull())
|
||||
throw Base::ValueError("AxisLink shape is null");
|
||||
if (axEdge.ShapeType() != TopAbs_EDGE)
|
||||
throw Base::TypeError("AxisLink shape is not an edge");
|
||||
|
||||
BRepAdaptor_Curve crv(TopoDS::Edge(axEdge));
|
||||
gp_Pnt base;
|
||||
gp_Dir occdir;
|
||||
if (crv.GetType() == GeomAbs_Line){
|
||||
base = crv.Value(crv.FirstParameter());
|
||||
occdir = crv.Line().Direction();
|
||||
} else if (crv.GetType() == GeomAbs_Circle) {
|
||||
base = crv.Circle().Axis().Location();
|
||||
occdir = crv.Circle().Axis().Direction();
|
||||
angle = crv.LastParameter() - crv.FirstParameter();
|
||||
} else {
|
||||
throw Base::TypeError("AxisLink edge is neither line nor arc of circle.");
|
||||
}
|
||||
center.Set(base.X(), base.Y(),base.Z());
|
||||
dir.Set(occdir.X(), occdir.Y(), occdir.Z());
|
||||
return true;
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||
{
|
||||
App::DocumentObject* link = Source.getValue();
|
||||
|
@ -67,18 +138,40 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
|||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
Part::Feature *base = static_cast<Part::Feature*>(Source.getValue());
|
||||
|
||||
Base::Vector3d b = Base.getValue();
|
||||
Base::Vector3d v = Axis.getValue();
|
||||
gp_Pnt pnt(b.x,b.y,b.z);
|
||||
gp_Dir dir(v.x,v.y,v.z);
|
||||
Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False;
|
||||
|
||||
try {
|
||||
// Now, let's get the TopoDS_Shape
|
||||
//TopoDS_Shape revolve = base->Shape.getShape().revolve(gp_Ax1(pnt, dir),
|
||||
// Angle.getValue()/180.0f*M_PI);
|
||||
TopoDS_Shape revolve = base->Shape.getShape().revolve(gp_Ax1(pnt, dir),
|
||||
Angle.getValue()/180.0f*M_PI,isSolid);
|
||||
//read out axis link
|
||||
double angle_edge = 0;
|
||||
Base::Vector3d b = Base.getValue();
|
||||
Base::Vector3d v = Axis.getValue();
|
||||
bool linkFetched = this->fetchAxisLink(this->AxisLink, b, v, angle_edge);
|
||||
if (linkFetched){
|
||||
this->Base.setValue(b);
|
||||
this->Axis.setValue(v);
|
||||
}
|
||||
|
||||
gp_Pnt pnt(b.x,b.y,b.z);
|
||||
gp_Dir dir(v.x,v.y,v.z);
|
||||
gp_Ax1 revAx(pnt, dir);
|
||||
|
||||
//read out revolution angle
|
||||
double angle = Angle.getValue()/180.0f*M_PI;
|
||||
if (fabs(angle) < Precision::Angular())
|
||||
angle = angle_edge;
|
||||
|
||||
//apply "midplane" symmetry
|
||||
TopoShape sourceShape = base->Shape.getShape();
|
||||
if (Symmetric.getValue()) {
|
||||
//rotate source shape backwards by half angle, to make resulting revolution symmetric to the profile
|
||||
gp_Trsf mov;
|
||||
mov.SetRotation(revAx, angle * (-0.5));
|
||||
TopLoc_Location loc(mov);
|
||||
sourceShape.setShape(sourceShape.getShape().Moved(loc));
|
||||
}
|
||||
|
||||
//do it!
|
||||
Standard_Boolean makeSolid = Solid.getValue() ? Standard_True : Standard_False;
|
||||
TopoDS_Shape revolve = sourceShape.revolve(revAx, angle, makeSolid);
|
||||
|
||||
if (revolve.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Resulting shape is null");
|
||||
this->Shape.setValue(revolve);
|
||||
|
|
|
@ -26,11 +26,12 @@
|
|||
|
||||
#include <App/PropertyStandard.h>
|
||||
#include "PartFeature.h"
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
namespace Part
|
||||
{
|
||||
|
||||
class Revolution : public Part::Feature
|
||||
class PartExport Revolution : public Part::Feature
|
||||
{
|
||||
PROPERTY_HEADER(Part::Revolution);
|
||||
|
||||
|
@ -40,7 +41,9 @@ public:
|
|||
App::PropertyLink Source;
|
||||
App::PropertyVector Base;
|
||||
App::PropertyVector Axis;
|
||||
App::PropertyLinkSub AxisLink;
|
||||
App::PropertyFloatConstraint Angle;
|
||||
App::PropertyBool Symmetric; //like "Midplane" in PartDesign
|
||||
App::PropertyBool Solid;
|
||||
|
||||
/** @name methods override feature */
|
||||
|
@ -48,12 +51,32 @@ public:
|
|||
/// recalculate the feature
|
||||
App::DocumentObjectExecReturn *execute(void);
|
||||
short mustExecute() const;
|
||||
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
/// returns the type name of the view provider
|
||||
const char* getViewProviderName(void) const {
|
||||
return "PartGui::ViewProviderRevolution";
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @brief fetchAxisLink: read AxisLink to obtain the axis parameters and
|
||||
* angle span. Note: this routine is re-used in Revolve dialog, hence it
|
||||
* is static.
|
||||
* @param axisLink (input): the link
|
||||
* @param center (output): base point of axis
|
||||
* @param dir (output): direction of axis
|
||||
* @param angle (output): if edge is an arc of circle, this argument is
|
||||
* used to return the angle span of the arc.
|
||||
* @return true if link was fetched. false if link was empty. Throws if the
|
||||
* link is wrong.
|
||||
*/
|
||||
static bool fetchAxisLink(const App::PropertyLinkSub& axisLink,
|
||||
Base::Vector3d ¢er,
|
||||
Base::Vector3d &dir,
|
||||
double &angle);
|
||||
|
||||
private:
|
||||
static App::PropertyFloatConstraint::Constraints angleRangeU;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user