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

Fix PartDesign::Mirrored #816

Closed
wants to merge 7 commits into from
33 changes: 21 additions & 12 deletions src/Mod/Part/App/PartFeature.cpp
Expand Up @@ -337,44 +337,53 @@ std::vector<Part::cutFaces> Part::findAllFacesCutBy(

bool Part::checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second,
const bool quick, const bool touch_is_intersection) {

Bnd_Box first_bb, second_bb;
BRepBndLib::Add(first, first_bb);
first_bb.SetGap(0);
BRepBndLib::Add(second, second_bb);
second_bb.SetGap(0);

// Note: This test fails if the objects are touching one another at zero distance
if (first_bb.IsOut(second_bb))

// Improving reliability: If it fails sometimes when touching and touching is intersection,
// then please check further unless the user asked for a quick potentially unreliable result
if (first_bb.IsOut(second_bb) && !touch_is_intersection)
return false; // no intersection
if (quick)
if (quick && !first_bb.IsOut(second_bb))
return true; // assumed intersection

// Try harder

// This has been disabled because of:
// https://www.freecadweb.org/tracker/view.php?id=3065

//extrema method
BRepExtrema_DistShapeShape extrema(first, second);
/*BRepExtrema_DistShapeShape extrema(first, second);
if (!extrema.IsDone())
return true;
if (extrema.Value() > Precision::Confusion())
return false;
if (extrema.InnerSolution())
return true;

//here we should have touching shapes.
if (touch_is_intersection)
{
//non manifold condition. 1 has to be a face
for (int index = 1; index < extrema.NbSolution() + 1; ++index)
{
if (extrema.SupportTypeShape1(index) == BRepExtrema_IsInFace || extrema.SupportTypeShape2(index) == BRepExtrema_IsInFace)
return true;
}

//non manifold condition. 1 has to be a face
for (int index = 1; index < extrema.NbSolution() + 1; ++index)
{
if (extrema.SupportTypeShape1(index) == BRepExtrema_IsInFace || extrema.SupportTypeShape2(index) == BRepExtrema_IsInFace)
return true;
}
return false;
}
else
return false;
return false;*/

//boolean method.
/*

if (touch_is_intersection) {
// If both shapes fuse to a single solid, then they intersect
BRepAlgoAPI_Fuse mkFuse(first, second);
Expand Down Expand Up @@ -406,5 +415,5 @@ bool Part::checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& seco
xp.Init(mkCommon.Shape(),TopAbs_SOLID);
return (xp.More() == Standard_True);
}
*/

}
19 changes: 9 additions & 10 deletions src/Mod/Part/App/TopoShape.cpp
Expand Up @@ -372,20 +372,19 @@ void TopoShape::convertToMatrix(const gp_Trsf& trsf, Base::Matrix4D& mtrx)
#if OCC_VERSION_HEX >= 0x070000
gp_Mat m = trsf.VectorialPart();
gp_XYZ p = trsf.TranslationPart();
Standard_Real scale = trsf.ScaleFactor();

// set Rotation matrix
mtrx[0][0] = scale * m(1,1);
mtrx[0][1] = scale * m(1,2);
mtrx[0][2] = scale * m(1,3);
mtrx[0][0] = m(1,1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the scale factor here makes this function inconsistent for OCC < 7.0 and >= 7.0
So, what is the reason of removing it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gp_Trsf::VectorialPart returns the 3x3 matrix including the scale factor now [1], an equivalent change to me removing the (redundant) scale factor multiplication here would be to change to gp_Trsf::HVectorialPart [2] which does not include the scale factor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok. Thx for the pointer.

mtrx[0][1] = m(1,2);
mtrx[0][2] = m(1,3);

mtrx[1][0] = scale * m(2,1);
mtrx[1][1] = scale * m(2,2);
mtrx[1][2] = scale * m(2,3);
mtrx[1][0] = m(2,1);
mtrx[1][1] = m(2,2);
mtrx[1][2] = m(2,3);

mtrx[2][0] = scale * m(3,1);
mtrx[2][1] = scale * m(3,2);
mtrx[2][2] = scale * m(3,3);
mtrx[2][0] = m(3,1);
mtrx[2][1] = m(3,2);
mtrx[2][2] = m(3,3);

// set pos vector
mtrx[0][3] = p.X();
Expand Down
128 changes: 69 additions & 59 deletions src/Mod/PartDesign/App/FeatureTransformed.cpp
Expand Up @@ -256,9 +256,9 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
}

// Transform the add/subshape and collect the resulting shapes for overlap testing
typedef std::vector<std::vector<gp_Trsf>::const_iterator> trsf_it_vec;
/*typedef std::vector<std::vector<gp_Trsf>::const_iterator> trsf_it_vec;
trsf_it_vec v_transformations;
std::vector<TopoDS_Shape> v_transformedShapes;
std::vector<TopoDS_Shape> v_transformedShapes;*/

std::vector<gp_Trsf>::const_iterator t = transformations.begin();
++t; // Skip first transformation, which is always the identity transformation
Expand All @@ -276,15 +276,75 @@ App::DocumentObjectExecReturn *Transformed::execute(void)

// Check for intersection with support
try {

if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) {
#ifdef FC_DEBUG // do not write this in release mode because a message appears already in the task view
Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument());
#endif
nointersect_trsfms[*o].insert(t);
} else {
v_transformations.push_back(t);
v_transformedShapes.push_back(mkTrf.Shape());
// We cannot wait to fuse a transformation with the support until all the transformations are done,
// because the "support" potentially changes with every transformation, basically when checking intersection
// above you need:
// 1. The original support
// 2. Any extra support gained by any previous transformation of any previous feature (multi-feature transform)
// 3. Any extra support gained by any previous tranformation of this feature (feature multi-trasform)
//
// Therefore, if the transformation succeeded, then we fuse it with the support now, before checking the intersection
// of the next transformation.

/*v_transformations.push_back(t);
v_transformedShapes.push_back(mkTrf.Shape());*/

// Note: Transformations that do not intersect the support are ignored in the overlap tests

//insert scheme here.
/*TopoDS_Compound compoundTool;
std::vector<TopoDS_Shape> individualTools;
divideTools(v_transformedShapes, individualTools, compoundTool);*/

// Fuse/Cut the compounded transformed shapes with the support
//TopoDS_Shape result;
TopoDS_Shape current = support;

if (fuse) {
BRepAlgoAPI_Fuse mkFuse(current, mkTrf.Shape());
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
/*std::vector<TopoDS_Shape>::const_iterator individualIt;
for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt)
{
BRepAlgoAPI_Fuse mkFuse2(current, *individualIt);
if (!mkFuse2.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse2.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
}*/
} else {
BRepAlgoAPI_Cut mkCut(current, mkTrf.Shape());
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = mkCut.Shape();
/*std::vector<TopoDS_Shape>::const_iterator individualIt;
for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt)
{
BRepAlgoAPI_Cut mkCut2(current, *individualIt);
if (!mkCut2.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = this->getSolid(mkCut2.Shape());
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
}*/
}
support = current; // Use result of this operation for fuse/cut of next original
}
} catch (Standard_Failure) {
// Note: Ignoring this failure is probably pointless because if the intersection check fails, the later
Expand All @@ -296,61 +356,6 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
return new App::DocumentObjectExecReturn(msg.c_str());
}
}

if (v_transformedShapes.empty())
continue; // Skip the overlap check and go on to next original

if (v_transformedShapes.empty())
continue; // Skip the boolean operation and go on to next original


//insert scheme here.
TopoDS_Compound compoundTool;
std::vector<TopoDS_Shape> individualTools;
divideTools(v_transformedShapes, individualTools, compoundTool);

// Fuse/Cut the compounded transformed shapes with the support
TopoDS_Shape result;
TopoDS_Shape current = support;

if (fuse) {
BRepAlgoAPI_Fuse mkFuse(current, compoundTool);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
std::vector<TopoDS_Shape>::const_iterator individualIt;
for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt)
{
BRepAlgoAPI_Fuse mkFuse2(current, *individualIt);
if (!mkFuse2.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse2.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
}
} else {
BRepAlgoAPI_Cut mkCut(current, compoundTool);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = mkCut.Shape();
std::vector<TopoDS_Shape>::const_iterator individualIt;
for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt)
{
BRepAlgoAPI_Cut mkCut2(current, *individualIt);
if (!mkCut2.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = this->getSolid(mkCut2.Shape());
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
}
}
support = current; // Use result of this operation for fuse/cut of next original
}
support = refineShapeIfActive(support);

Expand All @@ -359,6 +364,11 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
rejected[it->first].push_back(**it2);

this->Shape.setValue(getSolid(support));

if (rejected.size() > 0) {
return new App::DocumentObjectExecReturn("Transformation failed");
}

return App::DocumentObject::StdReturn;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp
Expand Up @@ -78,7 +78,7 @@ bool ViewProviderTransformed::setEdit(int ModNum)
rejectedPickStyle->style = SoPickStyle::UNPICKABLE;

SoShapeHints* rejectedHints = new SoShapeHints();
rejectedHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
rejectedHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
rejectedHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;

SoMaterialBinding* rejectedBind = new SoMaterialBinding();
Expand Down