[TD]fix 10013 detail of sketch
This commit is contained in:
@@ -566,6 +566,24 @@ TopoDS_Shape DrawUtil::vectorToCompound(std::vector<TopoDS_Wire> vecIn, bool inv
|
||||
return compOut;
|
||||
}
|
||||
|
||||
// construct a compound shape from a list of shapes
|
||||
// this version needs a different name since edges/wires are shapes
|
||||
TopoDS_Shape DrawUtil::shapeVectorToCompound(std::vector<TopoDS_Shape> vecIn, bool invert)
|
||||
{
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound compOut;
|
||||
builder.MakeCompound(compOut);
|
||||
for (auto& v : vecIn) {
|
||||
if (!v.IsNull()) {
|
||||
builder.Add(compOut, v);
|
||||
}
|
||||
}
|
||||
if (invert) {
|
||||
return TechDraw::mirrorShape(compOut);
|
||||
}
|
||||
return compOut;
|
||||
}
|
||||
|
||||
//constructs a list of edges from a shape
|
||||
std::vector<TopoDS_Edge> DrawUtil::shapeToVector(TopoDS_Shape shapeIn)
|
||||
{
|
||||
|
||||
@@ -130,6 +130,7 @@ public:
|
||||
|
||||
static TopoDS_Shape vectorToCompound(std::vector<TopoDS_Edge> vecIn, bool invert = true);
|
||||
static TopoDS_Shape vectorToCompound(std::vector<TopoDS_Wire> vecIn, bool invert = true);
|
||||
static TopoDS_Shape shapeVectorToCompound(std::vector<TopoDS_Shape> vecIn, bool invert = true);
|
||||
static std::vector<TopoDS_Edge> shapeToVector(TopoDS_Shape shapeIn);
|
||||
|
||||
static Base::Vector3d toR3(const gp_Ax2& fromSystem, const Base::Vector3d& fromPoint);
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "DrawViewSection.h"
|
||||
#include "GeometryObject.h"
|
||||
#include "Preferences.h"
|
||||
#include "ShapeUtils.h"
|
||||
|
||||
|
||||
using namespace TechDraw;
|
||||
@@ -205,9 +206,6 @@ void DrawViewDetail::makeDetailShape(const TopoDS_Shape& shape, DrawViewPart* dv
|
||||
Base::Vector3d dirDetail = dvp->Direction.getValue();
|
||||
double radius = getFudgeRadius();
|
||||
|
||||
int solidCount = DrawUtil::countSubShapes(shape, TopAbs_SOLID);
|
||||
int shellCount = DrawUtil::countSubShapes(shape, TopAbs_SHELL);
|
||||
|
||||
//make a copy of the input shape so we don't inadvertently change it
|
||||
BRepBuilderAPI_Copy BuilderCopy(shape);
|
||||
TopoDS_Shape copyShape = BuilderCopy.Shape();
|
||||
@@ -230,12 +228,9 @@ void DrawViewDetail::makeDetailShape(const TopoDS_Shape& shape, DrawViewPart* dv
|
||||
|
||||
m_viewAxis = dvp->getProjectionCS(shapeCenter);//save the CS for later
|
||||
Base::Vector3d anchor = AnchorPoint.getValue();//this is a 2D point in base view local coords
|
||||
// double baseRotationRad = dvp->Rotation.getValue() * M_PI / 180.0;
|
||||
// anchor.RotateZ(baseRotationRad);
|
||||
|
||||
anchor = DrawUtil::toR3(m_viewAxis, anchor);//actual anchor coords in R3
|
||||
|
||||
|
||||
Bnd_Box bbxSource;
|
||||
bbxSource.SetGap(0.0);
|
||||
BRepBndLib::AddOptimal(copyShape, bbxSource);
|
||||
@@ -280,105 +275,38 @@ void DrawViewDetail::makeDetailShape(const TopoDS_Shape& shape, DrawViewPart* dv
|
||||
}
|
||||
}
|
||||
|
||||
//for each solid and shell in the input shape, make a common with the tool and
|
||||
//add the result to a compound. This avoids issues with some geometry errors in the
|
||||
//input shape.
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound pieces;
|
||||
builder.MakeCompound(pieces);
|
||||
if (solidCount > 0) {
|
||||
TopExp_Explorer expl(copyShape, TopAbs_SOLID);
|
||||
for (; expl.More(); expl.Next()) {
|
||||
const TopoDS_Solid& s = TopoDS::Solid(expl.Current());
|
||||
|
||||
BRepAlgoAPI_Common mkCommon(s, tool);
|
||||
if (!mkCommon.IsDone()) {
|
||||
continue;
|
||||
}
|
||||
if (mkCommon.Shape().IsNull()) {
|
||||
continue;
|
||||
}
|
||||
//this might be overkill for piecewise algo
|
||||
//Did we get at least 1 solid?
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(mkCommon.Shape(), TopAbs_SOLID);
|
||||
if (xp.More() != Standard_True) {
|
||||
continue;
|
||||
}
|
||||
builder.Add(pieces, mkCommon.Shape());
|
||||
}
|
||||
}
|
||||
|
||||
if (shellCount > 0) {
|
||||
TopExp_Explorer expl(copyShape, TopAbs_SHELL);
|
||||
for (; expl.More(); expl.Next()) {
|
||||
const TopoDS_Shell& s = TopoDS::Shell(expl.Current());
|
||||
|
||||
BRepAlgoAPI_Common mkCommon(s, tool);
|
||||
if (!mkCommon.IsDone()) {
|
||||
continue;
|
||||
}
|
||||
if (mkCommon.Shape().IsNull()) {
|
||||
continue;
|
||||
}
|
||||
//this might be overkill for piecewise algo
|
||||
//Did we get at least 1 shell?
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(mkCommon.Shape(), TopAbs_SHELL);
|
||||
if (xp.More() != Standard_True) {
|
||||
continue;
|
||||
}
|
||||
builder.Add(pieces, mkCommon.Shape());
|
||||
}
|
||||
BRepAlgoAPI_Common mkCommon(copyShape, tool);
|
||||
if (!mkCommon.IsDone() || mkCommon.Shape().IsNull()) {
|
||||
Base::Console().Warning("DVD::detailExec - %s - failed to create detail shape\n",
|
||||
getNameInDocument());
|
||||
return;
|
||||
}
|
||||
|
||||
// save the detail shape for further processing
|
||||
m_detailShape = pieces;
|
||||
m_detailShape = mkCommon.Shape();
|
||||
|
||||
if (debugDetail()) {
|
||||
BRepTools::Write(tool, "DVDTool.brep"); //debug
|
||||
BRepTools::Write(copyShape, "DVDCopy.brep");//debug
|
||||
BRepTools::Write(pieces, "DVDCommon.brep"); //debug
|
||||
BRepTools::Write(m_detailShape, "DVDCommon.brep"); //debug
|
||||
}
|
||||
|
||||
gp_Pnt inputCenter;
|
||||
try {
|
||||
//centroid of result
|
||||
inputCenter = ShapeUtils::findCentroid(pieces, dirDetail);
|
||||
Base::Vector3d centroid(inputCenter.X(), inputCenter.Y(), inputCenter.Z());
|
||||
m_saveCentroid += centroid;//center of massaged shape
|
||||
gp_Pnt inputCenter = ShapeUtils::findCentroid(m_detailShape, dirDetail);
|
||||
Base::Vector3d centroid(inputCenter.X(), inputCenter.Y(), inputCenter.Z());
|
||||
m_saveCentroid += centroid;//center of massaged shape
|
||||
//align shape with detail anchor
|
||||
TopoDS_Shape centeredShape = ShapeUtils::moveShape(m_detailShape, anchor * -1.0);
|
||||
m_scaledShape = ShapeUtils::scaleShape(centeredShape, getScale());
|
||||
|
||||
if ((solidCount > 0) || (shellCount > 0)) {
|
||||
//align shape with detail anchor
|
||||
TopoDS_Shape centeredShape = ShapeUtils::moveShape(pieces, anchor * -1.0);
|
||||
m_scaledShape = ShapeUtils::scaleShape(centeredShape, getScale());
|
||||
if (debugDetail()) {
|
||||
BRepTools::Write(m_scaledShape, "DVDScaled.brep");//debug
|
||||
}
|
||||
}
|
||||
else {
|
||||
//no solids, no shells, do what you can with edges
|
||||
TopoDS_Shape projectedEdges = projectEdgesOntoFace(copyShape, extrusionFace, gdir);
|
||||
TopoDS_Shape centeredShape = ShapeUtils::moveShape(projectedEdges, anchor * -1.0);
|
||||
if (debugDetail()) {
|
||||
BRepTools::Write(projectedEdges, "DVDProjectedEdges.brep");//debug
|
||||
BRepTools::Write(centeredShape, "DVDCenteredShape.brep"); //debug
|
||||
}
|
||||
m_scaledShape = ShapeUtils::scaleShape(centeredShape, getScale());
|
||||
}
|
||||
if (debugDetail()) {
|
||||
BRepTools::Write(m_scaledShape, "DVDScaled.brep");//debug
|
||||
}
|
||||
|
||||
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
|
||||
m_viewAxis = dvp->getProjectionCS(stdOrg);
|
||||
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
|
||||
m_viewAxis = dvp->getProjectionCS(stdOrg);
|
||||
|
||||
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
|
||||
m_scaledShape = ShapeUtils::rotateShape(m_scaledShape, m_viewAxis, Rotation.getValue());
|
||||
}
|
||||
}//end try block
|
||||
|
||||
catch (Standard_Failure& e1) {
|
||||
Base::Console().Message("DVD::makeDetailShape - failed to create detail %s - %s **\n",
|
||||
getNameInDocument(), e1.GetMessageString());
|
||||
return;
|
||||
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
|
||||
m_scaledShape = ShapeUtils::rotateShape(m_scaledShape, m_viewAxis, Rotation.getValue());
|
||||
}
|
||||
|
||||
showProgressMessage(getNameInDocument(), "has finished making detail shape");
|
||||
|
||||
@@ -22,6 +22,18 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//===========================================================================
|
||||
// DrawViewPart overview
|
||||
//===========================================================================
|
||||
//
|
||||
// 1) get the shapes from the source objects
|
||||
// 2) center, scale and rotate the shapes
|
||||
// 3) project the shape using the OCC HLR algorithms
|
||||
// 4) add cosmetic and other objects that don't participate in hlr
|
||||
// 5) find the closed regions (faces) in the edges returned by hlr
|
||||
// everything else is mostly providing services to other objects, such as the
|
||||
// actual drawing routines in Gui
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
@@ -82,11 +94,6 @@
|
||||
using namespace TechDraw;
|
||||
using DU = DrawUtil;
|
||||
|
||||
//===========================================================================
|
||||
// DrawViewPart
|
||||
//===========================================================================
|
||||
|
||||
|
||||
PROPERTY_SOURCE_WITH_EXTENSIONS(TechDraw::DrawViewPart, TechDraw::DrawView)
|
||||
|
||||
DrawViewPart::DrawViewPart(void)
|
||||
@@ -157,6 +164,8 @@ DrawViewPart::~DrawViewPart()
|
||||
removeAllReferencesFromGeom();
|
||||
}
|
||||
|
||||
//! returns a compound of all the shapes from the DocumentObjects in the Source &
|
||||
//! XSource property lists
|
||||
TopoDS_Shape DrawViewPart::getSourceShape(bool fuse) const
|
||||
{
|
||||
// Base::Console().Message("DVP::getSourceShape()\n");
|
||||
@@ -170,15 +179,15 @@ TopoDS_Shape DrawViewPart::getSourceShape(bool fuse) const
|
||||
return ShapeExtractor::getShapes(links);
|
||||
}
|
||||
|
||||
// deliver a shape appropriate for making a detail view based on this view
|
||||
// TODO: why does dvp do the thinking for detail, but section picks its own
|
||||
// version of the shape? Should we have a getShapeForSection?
|
||||
//! deliver a shape appropriate for making a detail view based on this view
|
||||
//! TODO: why does dvp do the thinking for detail, but section picks its own
|
||||
//! version of the shape? Should we have a getShapeForSection?
|
||||
TopoDS_Shape DrawViewPart::getShapeForDetail() const
|
||||
{
|
||||
return ShapeUtils::rotateShape(getSourceShape(true), getProjectionCS(), Rotation.getValue());
|
||||
}
|
||||
|
||||
// combine the regular links and xlinks into a single list
|
||||
//! combine the regular links and xlinks into a single list
|
||||
std::vector<App::DocumentObject*> DrawViewPart::getAllSources() const
|
||||
{
|
||||
// Base::Console().Message("DVP::getAllSources()\n");
|
||||
@@ -192,8 +201,8 @@ std::vector<App::DocumentObject*> DrawViewPart::getAllSources() const
|
||||
return result;
|
||||
}
|
||||
|
||||
//pick supported 2d shapes out of the Source properties and
|
||||
//add them directly to the geometry without going through HLR
|
||||
//! pick supported 2d shapes out of the Source properties and
|
||||
//! add them directly to the geometry without going through HLR
|
||||
void DrawViewPart::addShapes2d(void)
|
||||
{
|
||||
std::vector<TopoDS_Shape> shapes = ShapeExtractor::getShapes2d(getAllSources());
|
||||
@@ -300,7 +309,7 @@ void DrawViewPart::partExec(TopoDS_Shape& shape)
|
||||
}
|
||||
}
|
||||
|
||||
//prepare the shape for HLR processing by centering, scaling and rotating it
|
||||
//! prepare the shape for HLR processing by centering, scaling and rotating it
|
||||
GeometryObjectPtr DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape)
|
||||
{
|
||||
// Base::Console().Message("DVP::makeGeometryForShape() - %s\n", getNameInDocument());
|
||||
@@ -320,7 +329,7 @@ GeometryObjectPtr DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape)
|
||||
return buildGeometryObject(localShape, getProjectionCS());
|
||||
}
|
||||
|
||||
//Modify a shape by centering, scaling and rotating and return the centered (but not rotated) shape
|
||||
//! Modify a shape by centering, scaling and rotating and return the centered (but not rotated) shape
|
||||
TopoDS_Shape DrawViewPart::centerScaleRotate(DrawViewPart* dvp, TopoDS_Shape& inOutShape,
|
||||
Base::Vector3d centroid)
|
||||
{
|
||||
@@ -339,7 +348,7 @@ TopoDS_Shape DrawViewPart::centerScaleRotate(DrawViewPart* dvp, TopoDS_Shape& in
|
||||
return centeredShape;
|
||||
}
|
||||
|
||||
//create a geometry object and trigger the HLR process in another thread
|
||||
//! create a geometry object and trigger the HLR process in another thread
|
||||
TechDraw::GeometryObjectPtr DrawViewPart::buildGeometryObject(TopoDS_Shape& shape,
|
||||
const gp_Ax2& viewAxis)
|
||||
{
|
||||
@@ -386,7 +395,7 @@ TechDraw::GeometryObjectPtr DrawViewPart::buildGeometryObject(TopoDS_Shape& shap
|
||||
return go;
|
||||
}
|
||||
|
||||
//continue processing after hlr thread completes
|
||||
//! continue processing after hlr thread completes
|
||||
void DrawViewPart::onHlrFinished(void)
|
||||
{
|
||||
// Base::Console().Message("DVP::onHlrFinished() - %s\n", getNameInDocument());
|
||||
@@ -436,7 +445,7 @@ void DrawViewPart::onHlrFinished(void)
|
||||
}
|
||||
}
|
||||
|
||||
//run any tasks that need to been done after geometry is available
|
||||
//! run any tasks that need to been done after geometry is available
|
||||
void DrawViewPart::postHlrTasks(void)
|
||||
{
|
||||
// Base::Console().Message("DVP::postHlrTasks() - %s\n", getNameInDocument());
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <Base/Placement.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Mod/Part/App/PrimitiveFeature.h>
|
||||
//#include <Mod/Sketcher/App/SketchObject.h>
|
||||
|
||||
#include "ShapeExtractor.h"
|
||||
#include "DrawUtil.h"
|
||||
@@ -50,12 +51,12 @@
|
||||
using namespace TechDraw;
|
||||
using DU = DrawUtil;
|
||||
|
||||
std::vector<TopoDS_Shape> ShapeExtractor::getShapes2d(const std::vector<App::DocumentObject*> links)
|
||||
std::vector<TopoDS_Shape> ShapeExtractor::getShapes2d(const std::vector<App::DocumentObject*> links, bool overridePref)
|
||||
{
|
||||
// Base::Console().Message("SE::getShapes2d()\n");
|
||||
|
||||
std::vector<TopoDS_Shape> shapes2d;
|
||||
if (!prefAdd2d()) {
|
||||
if (!prefAdd2d() && !overridePref) {
|
||||
return shapes2d;
|
||||
}
|
||||
for (auto& l:links) {
|
||||
@@ -89,12 +90,15 @@ std::vector<TopoDS_Shape> ShapeExtractor::getShapes2d(const std::vector<App::Doc
|
||||
return shapes2d;
|
||||
}
|
||||
|
||||
TopoDS_Shape ShapeExtractor::getShapes(const std::vector<App::DocumentObject*> links)
|
||||
TopoDS_Shape ShapeExtractor::getShapes(const std::vector<App::DocumentObject*> links, bool include2d)
|
||||
{
|
||||
// Base::Console().Message("SE::getShapes() - links in: %d\n", links.size());
|
||||
std::vector<TopoDS_Shape> sourceShapes;
|
||||
|
||||
for (auto& l:links) {
|
||||
if (is2dObject(l) && !include2d) {
|
||||
continue;
|
||||
}
|
||||
if (l->getTypeId().isDerivedFrom(App::Link::getClassTypeId())) {
|
||||
App::Link* xLink = dynamic_cast<App::Link*>(l);
|
||||
std::vector<TopoDS_Shape> xShapes = getXShapes(xLink);
|
||||
@@ -313,7 +317,8 @@ std::vector<TopoDS_Shape> ShapeExtractor::getShapesFromObject(const App::Documen
|
||||
TopoDS_Shape ShapeExtractor::getShapesFused(const std::vector<App::DocumentObject*> links)
|
||||
{
|
||||
// Base::Console().Message("SE::getShapesFused()\n");
|
||||
TopoDS_Shape baseShape = getShapes(links);
|
||||
// get only the 3d shapes and fuse them
|
||||
TopoDS_Shape baseShape = getShapes(links, false);
|
||||
if (!baseShape.IsNull()) {
|
||||
TopoDS_Iterator it(baseShape);
|
||||
TopoDS_Shape fusedShape = it.Value();
|
||||
@@ -330,6 +335,15 @@ TopoDS_Shape ShapeExtractor::getShapesFused(const std::vector<App::DocumentObjec
|
||||
}
|
||||
baseShape = fusedShape;
|
||||
}
|
||||
|
||||
// if there are 2d shapes in the links they will not fuse with the 3d shapes,
|
||||
// so instead we return a compound of the fused 3d shapes and the 2d shapes
|
||||
std::vector<TopoDS_Shape> shapes2d = getShapes2d(links, true);
|
||||
if (!shapes2d.empty()) {
|
||||
shapes2d.push_back(baseShape);
|
||||
return DrawUtil::shapeVectorToCompound(shapes2d);
|
||||
}
|
||||
|
||||
return baseShape;
|
||||
}
|
||||
|
||||
@@ -361,11 +375,21 @@ TopoDS_Shape ShapeExtractor::stripInfiniteShapes(TopoDS_Shape inShape)
|
||||
|
||||
bool ShapeExtractor::is2dObject(App::DocumentObject* obj)
|
||||
{
|
||||
bool result = false;
|
||||
if (isEdgeType(obj) || isPointType(obj)) {
|
||||
result = true;
|
||||
// TODO:: the check for an object being a sketch should be done as in the commented
|
||||
// if statement below. To do this, we need to include Mod/Sketcher/SketchObject.h,
|
||||
// but that makes TechDraw dependent on Eigen libraries which we don't use. As a
|
||||
// workaround we will inspect the object's class name.
|
||||
// if (obj->isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
|
||||
std::string objTypeName = obj->getTypeId().getName();
|
||||
std::string sketcherToken("Sketcher");
|
||||
if (objTypeName.find(sketcherToken) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
|
||||
if (isEdgeType(obj) || isPointType(obj)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//skip edges for now.
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace TechDraw
|
||||
class TechDrawExport ShapeExtractor
|
||||
{
|
||||
public:
|
||||
static TopoDS_Shape getShapes(const std::vector<App::DocumentObject*> links);
|
||||
static std::vector<TopoDS_Shape> getShapes2d(const std::vector<App::DocumentObject*> links);
|
||||
static TopoDS_Shape getShapes(const std::vector<App::DocumentObject*> links, bool include2d = true);
|
||||
static std::vector<TopoDS_Shape> getShapes2d(const std::vector<App::DocumentObject*> links, bool overridePref = false);
|
||||
static std::vector<TopoDS_Shape> getXShapes(const App::Link* xLink);
|
||||
static std::vector<TopoDS_Shape> getShapesFromObject(const App::DocumentObject* docObj);
|
||||
static TopoDS_Shape getShapesFused(const std::vector<App::DocumentObject*> links);
|
||||
|
||||
Reference in New Issue
Block a user