diff --git a/src/Mod/TechDraw/App/DrawComplexSection.cpp b/src/Mod/TechDraw/App/DrawComplexSection.cpp index 3dab553f1e..036bba6831 100644 --- a/src/Mod/TechDraw/App/DrawComplexSection.cpp +++ b/src/Mod/TechDraw/App/DrawComplexSection.cpp @@ -214,15 +214,27 @@ TopoDS_Shape DrawComplexSection::makeCuttingTool(double dMax) return BRepPrimAPI_MakePrism(toolFace, extrudeDir).Shape(); } - //if the wire is open we need to make a "face" from the wire by extruding it - //in the direction of gClosestBasis , then extrude the face in the direction of the section normal + // if the wire is open (the normal case of a more or less linear profile), + // we need to make a "face" from the wire by extruding it + // in the direction of gClosestBasis , then extrude the face in the direction of the section normal + + if (ProjectionStrategy.getValue() == 0) { + // Offset. Warn if profile is not quite aligned with section normal. if + // the profile and normal are misaligned, the check below for empty "solids" + // will not be correct. + double angleThresholdDeg = 5.0; + // bool isOK = + validateOffsetProfile(profileWire, SectionNormal.getValue(), angleThresholdDeg); + } + m_toolFaceShape = extrudeWireToFace(profileWire, gClosestBasis, 2.0 * dMax); if (debugSection()) { BRepTools::Write(m_toolFaceShape, "DCSToolFaceShape.brep");//debug } extrudeDir = dMax * sectionCS.Direction(); TopoDS_Shape roughTool = BRepPrimAPI_MakePrism(m_toolFaceShape, extrudeDir).Shape(); - if (roughTool.ShapeType() == TopAbs_COMPSOLID) { + if (roughTool.ShapeType() == TopAbs_COMPSOLID || + roughTool.ShapeType() == TopAbs_COMPOUND) { //Composite Solids do not cut well if they contain "solids" with no volume. This //happens if the profile has segments parallel to the extrude direction. //We need to disassemble it and only keep the real solids. @@ -907,6 +919,41 @@ gp_Vec DrawComplexSection::projectVector(const gp_Vec& vec) const return gp_Vec(prjPnt.X(), prjPnt.Y(), 0.0); } +// check for profile segments that are almost, but not quite in the same direction +// as the section normal direction. this often indicates a problem with the direction +// being slightly wrong. see https://forum.freecad.org/viewtopic.php?t=79017&sid=612a62a60f5db955ee071a7aaa362dbb +bool DrawComplexSection::validateOffsetProfile(TopoDS_Wire profile, Base::Vector3d direction, double angleThresholdDeg) const +{ + double angleThresholdRad = angleThresholdDeg * M_PI / 180.0; // 5 degrees + TopExp_Explorer explEdges(profile, TopAbs_EDGE); + for (; explEdges.More(); explEdges.Next()) { + std::pair segmentEnds = getSegmentEnds(TopoDS::Edge(explEdges.Current())); + Base::Vector3d segmentDir = segmentEnds.second - segmentEnds.first; + double angleRad = segmentDir.GetAngle(direction); + if (angleRad < angleThresholdRad && + angleRad > 0.0) { + // profile segment is slightly skewed. possible bad SectionNormal? + Base::Console().Warning("%s profile is slightly skewed. Check SectionNormal low decimal places\n", + getNameInDocument()); + return false; + } + } + return true; +} + +std::pair DrawComplexSection::getSegmentEnds(TopoDS_Edge segment) const +{ + // Base::Console().Message("DCS::getSegmentEnds()\n"); + TopoDS_Vertex tvFirst, tvLast; + TopExp::Vertices(segment, tvFirst, tvLast); + gp_Pnt gpFirst = BRep_Tool::Pnt(tvFirst); + gp_Pnt gpLast = BRep_Tool::Pnt(tvLast); + std::pair result; + result.first = DU::toVector3d(gpFirst); + result.second = DU::toVector3d(gpLast); + return result; +} + //static //TODO: centralize all the projection routines scattered around the module! gp_Vec DrawComplexSection::projectVector(const gp_Vec& vec, gp_Ax2 sectionCS) diff --git a/src/Mod/TechDraw/App/DrawComplexSection.h b/src/Mod/TechDraw/App/DrawComplexSection.h index f5fc22624c..b342dd4ec2 100644 --- a/src/Mod/TechDraw/App/DrawComplexSection.h +++ b/src/Mod/TechDraw/App/DrawComplexSection.h @@ -100,6 +100,8 @@ public Q_SLOTS: private: gp_Dir getFaceNormal(TopoDS_Face& face); + bool validateOffsetProfile(TopoDS_Wire profile, Base::Vector3d direction, double angleThresholdDeg) const; + std::pair getSegmentEnds(TopoDS_Edge segment) const; TopoDS_Shape m_toolFaceShape; TopoDS_Shape m_alignResult; diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index ecbcf5f382..1a81c07c4a 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -723,7 +723,9 @@ TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign) } if (goodWires.empty()) { - Base::Console().Warning("DVS::mapToPage - %s - section face has no valid wires.\n", + // this may or may not be significant. In the offset or noparallel strategies, + // a profile segment that is parallel to the SectionNormal will not generate a face. + Base::Console().Log("DVS::mapToPage - %s - section face has no valid wires.\n", getNameInDocument()); continue; }