Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attacher10 (build test - please ignore) #153

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 195 additions & 2 deletions src/Mod/Part/App/Attacher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepExtrema_DistShapeShape.hxx>
# include <TopTools_HSequenceOfShape.hxx>
# include <ShapeExtend_Explorer.hxx>
# include <GProp_GProps.hxx>
# include <GProp_PGProps.hxx>
# include <GProp_PrincipalProps.hxx>
# include <BRepGProp.hxx>
#endif
#include <BRepLProp_SLProps.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
Expand Down Expand Up @@ -105,6 +111,13 @@ const char* AttachEngine::eMapModeStrings[]= {
"Vertex",
"ProximityPoint1",
"ProximityPoint2",

"AxisOfInertia1",
"AxisOfInertia2",
"AxisOfInertia3",

"InertialCS",

NULL};


Expand Down Expand Up @@ -247,7 +260,8 @@ Base::Placement AttachEngine::placementFactory(const gp_Dir &ZAxis,

eMapMode AttachEngine::listMapModes(eSuggestResult& msg,
std::vector<eMapMode>* allApplicableModes,
std::set<eRefType>* nextRefTypeHint) const
std::set<eRefType>* nextRefTypeHint,
std::map<eMapMode,refTypeStringList>* reachableModes) const
{
//replace a pointer with a valid reference, to avoid checks for zero pointer everywhere
std::vector<eMapMode> buf;
Expand All @@ -263,6 +277,12 @@ eMapMode AttachEngine::listMapModes(eSuggestResult& msg,
std::set<eRefType> &hints = *nextRefTypeHint;
hints.clear();

std::map<eMapMode,refTypeStringList> buf3;
if (reachableModes == 0)
reachableModes = &buf3;
std::map<eMapMode,refTypeStringList> &mlist_reachable = *reachableModes;
mlist_reachable.clear();


std::vector<App::GeoFeature*> parts;
std::vector<const TopoDS_Shape*> shapes;
Expand Down Expand Up @@ -305,9 +325,26 @@ eMapMode AttachEngine::listMapModes(eSuggestResult& msg,
}
}

if (score > 0 && str.size() > typeStr.size())
if (score > 0 && str.size() > typeStr.size()){
//mode does not fit, but adding more references will make this mode fit.
hints.insert(str[typeStr.size()]);

//build string of references to be added to fit this mode
refTypeString extraRefs;
extraRefs.resize(str.size() - typeStr.size());
for (int iChr = typeStr.size() ; iChr < str.size() ; iChr++){
extraRefs[iChr - typeStr.size()] = str[iChr];
}

//add reachable mode
auto it_r = mlist_reachable.find(eMapMode(iMode));
if (it_r == mlist_reachable.end()){
it_r = mlist_reachable.insert(std::pair<eMapMode,refTypeStringList>(eMapMode(iMode),refTypeStringList())).first;
}
refTypeStringList &list = it_r->second;
list.push_back(extraRefs);
}

//size check is last, because we needed to collect hints
if (str.size() != typeStr.size())
score = -1;
Expand Down Expand Up @@ -556,6 +593,81 @@ std::string AttachEngine::getModeName(eMapMode mmode)
return std::string(AttachEngine::eMapModeStrings[mmode]);
}

GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes)
{
//explode compounds
TopTools_HSequenceOfShape totalSeq;
for (const TopoDS_Shape* pSh: shapes){
ShapeExtend_Explorer xp;
totalSeq.Append( xp.SeqFromCompound(*pSh, /*recursive=*/true));
}
if (totalSeq.Length() == 0)
throw Base::Exception("AttachEngine::getInertialPropsOfShape: no geometry provided");
const TopoDS_Shape &sh0 = totalSeq.Value(1);
switch (sh0.ShapeType()){
case TopAbs_VERTEX:{
GProp_PGProps gpr;
for (int i = 0 ; i < totalSeq.Length() ; i++){
const TopoDS_Shape &sh = totalSeq.Value(i+1);
if (sh.ShapeType() != TopAbs_VERTEX)
throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only vertices)");
gpr.AddPoint(BRep_Tool::Pnt(TopoDS::Vertex(sh)));
}
return gpr;
} break;
case TopAbs_EDGE:
case TopAbs_WIRE:{
GProp_GProps gpr_acc;
GProp_GProps gpr;
for (int i = 0 ; i < totalSeq.Length() ; i++){
const TopoDS_Shape &sh = totalSeq.Value(i+1);
if (sh.ShapeType() != TopAbs_EDGE && sh.ShapeType() != TopAbs_WIRE)
throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only edges/wires)");
if (sh.Infinite())
throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided");
BRepGProp::LinearProperties(sh,gpr);
gpr_acc.Add(gpr);
}
return gpr_acc;
} break;
case TopAbs_FACE:
case TopAbs_SHELL:{
GProp_GProps gpr_acc;
GProp_GProps gpr;
for (int i = 0 ; i < totalSeq.Length() ; i++){
const TopoDS_Shape &sh = totalSeq.Value(i+1);
if (sh.ShapeType() != TopAbs_FACE && sh.ShapeType() != TopAbs_SHELL)
throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only faces/shells)");
if (sh.Infinite())
throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided");
BRepGProp::SurfaceProperties(sh,gpr);
gpr_acc.Add(gpr);
}
return gpr_acc;
} break;
case TopAbs_SOLID:
case TopAbs_COMPSOLID:{
GProp_GProps gpr_acc;
GProp_GProps gpr;
for (int i = 0 ; i < totalSeq.Length() ; i++){
const TopoDS_Shape &sh = totalSeq.Value(i+1);
if (sh.ShapeType() != TopAbs_SOLID && sh.ShapeType() != TopAbs_COMPSOLID)
throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only solids/compsolids)");
if (sh.Infinite())
throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided");
BRepGProp::SurfaceProperties(sh,gpr);
gpr_acc.Add(gpr);
}
return gpr_acc;
} break;
default:
throw Base::Exception("AttachEngine::getInertialPropsOfShape: unexpected shape type");
}

assert(false);//exec shouldn't ever get here
return GProp_GProps();
}

/*!
* \brief AttachEngine3D::readLinks
* \param parts
Expand Down Expand Up @@ -671,6 +783,11 @@ AttachEngine3D::AttachEngine3D()
modeRefTypes[mmObjectXZ] = ss;
modeRefTypes[mmObjectYZ] = ss;

modeRefTypes[mmInertialCS].push_back(cat(rtAnything));
modeRefTypes[mmInertialCS].push_back(cat(rtAnything,rtAnything));
modeRefTypes[mmInertialCS].push_back(cat(rtAnything,rtAnything,rtAnything));
modeRefTypes[mmInertialCS].push_back(cat(rtAnything,rtAnything,rtAnything,rtAnything));

modeRefTypes[mmFlatFace].push_back(cat(rtFlatFace));

modeRefTypes[mmTangentPlane].push_back(cat(rtFace, rtVertex));
Expand Down Expand Up @@ -855,6 +972,33 @@ Base::Placement AttachEngine3D::calculateAttachedPlacement(Base::Placement origP
}

} break;
case mmInertialCS:{
GProp_GProps gpr = AttachEngine::getInertialPropsOfShape(shapes);
GProp_PrincipalProps pr = gpr.PrincipalProperties();
if (pr.HasSymmetryPoint())
throw Base::Exception("AttachEngine3D::calculateAttachedPlacement:InertialCS: inertia tensor is trivial, principal axes are undefined.");
if (pr.HasSymmetryAxis()){
Base::Console().Warning("AttachEngine3D::calculateAttachedPlacement:InertialCS: inertia tensor has axis of symmetry. Second and third axes of inertia are undefined.\n");
//find defined axis, and use it as Z axis
Standard_Real I1, I2, I3;
pr.Moments(I1,I2,I3);
Standard_Real d12, d23, d31;
d12 = fabs(I1-I2);
d23 = fabs(I2-I3);
d31 = fabs(I3-I1);
if(d12 < d23 && d12 < d31){
SketchNormal = pr.ThirdAxisOfInertia();
} else if (d23 < d31 && d23 < d12){
SketchNormal = pr.FirstAxisOfInertia();
} else {
SketchNormal = pr.SecondAxisOfInertia();
}
} else {
SketchNormal = pr.FirstAxisOfInertia();
SketchXAxis = pr.SecondAxisOfInertia();
}
SketchBasePoint = gpr.CentreOfMass();
}break;
case mmFlatFace:{
if (shapes.size() < 1)
throw Base::Exception("AttachEngine3D::calculateAttachedPlacement: no subobjects specified (needed one planar face).");
Expand Down Expand Up @@ -1322,6 +1466,15 @@ AttachEngineLine::AttachEngineLine()

modeRefTypes[mm1Proximity].push_back(cat(rtAnything, rtAnything));

modeRefTypes[mm1AxisInertia1].push_back(cat(rtAnything));
modeRefTypes[mm1AxisInertia1].push_back(cat(rtAnything,rtAnything));
modeRefTypes[mm1AxisInertia1].push_back(cat(rtAnything,rtAnything,rtAnything));
modeRefTypes[mm1AxisInertia1].push_back(cat(rtAnything,rtAnything,rtAnything,rtAnything));
modeRefTypes[mm1AxisInertia2] = modeRefTypes[mm1AxisInertia1];
modeRefTypes[mm1AxisInertia3] = modeRefTypes[mm1AxisInertia1];



this->EnableAllSupportedModes();
}

Expand Down Expand Up @@ -1399,6 +1552,37 @@ Base::Placement AttachEngineLine::calculateAttachedPlacement(Base::Placement ori
case mmDeactivated:
//should have been filtered out already!
break;
case mm1AxisInertia1:
case mm1AxisInertia2:
case mm1AxisInertia3:{
GProp_GProps gpr = AttachEngine::getInertialPropsOfShape(shapes);
LineBasePoint = gpr.CentreOfMass();
GProp_PrincipalProps pr = gpr.PrincipalProperties();
if (pr.HasSymmetryPoint())
throw Base::Exception("AttachEngineLine::calculateAttachedPlacement:AxisOfInertia: inertia tensor is trivial, principal axes are undefined.");

//query moments, to use them to check if axis is defined
Standard_Real I1, I2, I3;
pr.Moments(I1,I2,I3);
Standard_Real d12, d23, d31;
d12 = fabs(I1-I2);
d23 = fabs(I2-I3);
d31 = fabs(I3-I1);

if (mmode == mm1AxisInertia1){
LineDir = pr.FirstAxisOfInertia();
if (pr.HasSymmetryAxis() && !(d23 < d31 && d23 < d12))
throw Base::Exception("AttachEngineLine::calculateAttachedPlacement:AxisOfInertia: inertia tensor has axis of symmetry; first axis of inertia is undefined.");
} else if (mmode == mm1AxisInertia2) {
LineDir = pr.SecondAxisOfInertia();
if (pr.HasSymmetryAxis() && !(d31 < d12 && d31 < d23))
throw Base::Exception("AttachEngineLine::calculateAttachedPlacement:AxisOfInertia: inertia tensor has axis of symmetry; second axis of inertia is undefined.");
} else if (mmode == mm1AxisInertia3) {
LineDir = pr.ThirdAxisOfInertia();
if (pr.HasSymmetryAxis() && !(d12 < d23 && d12 < d31))
throw Base::Exception("AttachEngineLine::calculateAttachedPlacement:AxisOfInertia: inertia tensor has axis of symmetry; third axis of inertia is undefined.");
}
}break;
case mm1TwoPoints:{
std::vector<gp_Pnt> points;

Expand Down Expand Up @@ -1553,6 +1737,11 @@ AttachEnginePoint::AttachEnginePoint()
modeRefTypes[mm0ProximityPoint1].push_back(s);
modeRefTypes[mm0ProximityPoint2].push_back(s);

modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything));
modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything,rtAnything));
modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything,rtAnything,rtAnything));
modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything,rtAnything,rtAnything,rtAnything));

this->EnableAllSupportedModes();
}

Expand Down Expand Up @@ -1676,6 +1865,10 @@ Base::Placement AttachEnginePoint::calculateAttachedPlacement(Base::Placement or
else
BasePoint = p2;
}break;
case mm0CenterOfMass:{
GProp_GProps gpr = AttachEngine::getInertialPropsOfShape(shapes);
BasePoint = gpr.CentreOfMass();
}break;
default:
throwWrongMode(mmode);
}
Expand Down
25 changes: 22 additions & 3 deletions src/Mod/Part/App/Attacher.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "PartFeature.h"

#include <gp_Vec.hxx>
#include <GProp_GProps.hxx>

namespace Attacher
{
Expand Down Expand Up @@ -91,6 +92,13 @@ enum eMapMode {
mm0Vertex,
mm0ProximityPoint1,
mm0ProximityPoint2,

mm1AxisInertia1,
mm1AxisInertia2,
mm1AxisInertia3,

mmInertialCS,

mmDummy_NumberOfModes//a value useful to check the validity of mode value
};//see also eMapModeStrings[] definition in .cpp

Expand Down Expand Up @@ -144,6 +152,10 @@ enum eRefType {
class PartExport AttachEngine : public Base::BaseClass
{
TYPESYSTEM_HEADER();
public: //typedefs
typedef std::vector<eRefType> refTypeString; //a sequence of ref types, according to Support contents for example
typedef std::vector<refTypeString> refTypeStringList; //a set of type strings, defines which selection sets are supported by a certain mode

public: //methods
AttachEngine();
virtual void setUp(const App::PropertyLinkSubList &references,
Expand Down Expand Up @@ -216,10 +228,17 @@ class PartExport AttachEngine : public Base::BaseClass
* right type.
*
* @param nextRefTypeHint (output). A hint of what can be added to references.
*
* @param reachableModes (output). List of modes that can be reached by
* selecing more references. Is a map, where key is the mode that can be
* reached and value is a list of reference sequences that can be added to
* reach the mode (stuff already linked is omitted from these lists; only
* extra links needed are listed)
*/
virtual eMapMode listMapModes(eSuggestResult &msg,
std::vector<eMapMode>* allApplicableModes = 0,
std::set<eRefType>* nextRefTypeHint = 0) const;
std::set<eRefType>* nextRefTypeHint = 0,
std::map<eMapMode, refTypeStringList> *reachableModes = 0) const;

/**
* @brief getHint function returns a set of types that user can add to
Expand Down Expand Up @@ -293,6 +312,8 @@ class PartExport AttachEngine : public Base::BaseClass
*/
static std::string getModeName(eMapMode mmode);

static GProp_GProps getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes);


public: //enums
static const char* eMapModeStrings[];
Expand All @@ -314,8 +335,6 @@ class PartExport AttachEngine : public Base::BaseClass
*/
std::vector<bool> modeEnabled;

typedef std::vector<eRefType> refTypeString; //a sequence of ref types, according to Support contents for example
typedef std::vector<refTypeString> refTypeStringList; //a set of type strings, defines which selection sets are supported by a certain mode
std::vector<refTypeStringList> modeRefTypes; //a complete data structure, containing info on which modes support what selection

protected:
Expand Down
Loading