diff --git a/src/XCAFDoc/XCAFDoc_Editor.cxx b/src/XCAFDoc/XCAFDoc_Editor.cxx index dd92a88cfe..9c3489c8ed 100644 --- a/src/XCAFDoc/XCAFDoc_Editor.cxx +++ b/src/XCAFDoc/XCAFDoc_Editor.cxx @@ -155,6 +155,112 @@ Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& theDoc, return aResult; } +//======================================================================= +//function : Compact +//purpose : Converts assembly to compound +//======================================================================= +Standard_Boolean XCAFDoc_Editor::Compact(const TDF_Label& theDoc, + const TDF_Label& theAssemblyL) +{ + if (theAssemblyL.IsNull()) + { + return Standard_False; + } + Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc); + TopoDS_Shape aS = aShapeTool->GetShape(theAssemblyL); + if (aS.IsNull() || aS.ShapeType() != TopAbs_COMPOUND || !aShapeTool->IsAssembly(theAssemblyL)) + { + return Standard_False; + } + theAssemblyL.ForgetAttribute(XCAFDoc::AssemblyGUID()); + TopoDS_Compound aCompound; // new compound for shape label + BRep_Builder aBuilder; + aBuilder.MakeCompound(aCompound); + // convert assembly to compound + for (TDF_ChildIterator anIter(theAssemblyL); anIter.More(); anIter.Next()) + { + TDF_Label aChild = anIter.Value(); + TDF_Label aPart; + TopoDS_Shape aChildShape = aShapeTool->GetShape(aChild); // gets with own*ref location + if (aShapeTool->GetReferredShape(aChild, aPart)) + { + if (aChildShape.ShapeType() == TopAbs_COMPOUND && aShapeTool->IsAssembly(aPart)) + { + // iterate next level if it needed + Compact(theDoc, aPart); + } + // get location + Handle(XCAFDoc_Location) aLocationAttribute; + aChild.FindAttribute(XCAFDoc_Location::GetID(), aLocationAttribute); + + TopLoc_Location aLoc; + if (!aLocationAttribute.IsNull()) + { + aLoc = aLocationAttribute->Get(); + } + aChild.ForgetAllAttributes(Standard_False); + if (aChildShape.ShapeType() != TopAbs_COMPOUND) + { + //move shape + aShapeTool->SetShape(aChild, aChildShape); + aChildShape.Free(Standard_True); + aBuilder.Add(aCompound, aChildShape); + CloneMetaData(aPart, aChild, NULL); + } + // move subshapes + TDF_LabelSequence aSub; + aShapeTool->GetSubShapes(aPart, aSub); + for (TDF_LabelSequence::Iterator aSubIter(aSub); aSubIter.More(); aSubIter.Next()) + { + TopoDS_Shape aShapeSub = aShapeTool->GetShape(aSubIter.Value()).Moved(aLoc); // gets with own*ref*father location + TDF_TagSource aTag; + TDF_Label aSubC = aTag.NewChild(theAssemblyL); + // set shape + aShapeTool->SetShape(aSubC, aShapeSub); + aSubC.ForgetAttribute(XCAFDoc_ShapeMapTool::GetID()); + if (aChildShape.ShapeType() == TopAbs_COMPOUND) + { + aShapeSub.Free(Standard_True); + aBuilder.Add(aCompound, aShapeSub); + } + CloneMetaData(aSubIter.Value(), aSubC, NULL); + } + // if all references removed - delete all data + if (aShapeTool->IsFree(aPart)) + { + aPart.ForgetAllAttributes(); + } + } + } + aShapeTool->SetShape(theAssemblyL, aCompound); + return Standard_True; +} + +//======================================================================= +//function : Compact +//purpose : Converts all assembly in theDoc to compound +//======================================================================= +Standard_Boolean XCAFDoc_Editor::Compact(const TDF_Label& theDoc) +{ + if (theDoc.IsNull()) + { + return Standard_False; + } + Standard_Boolean aResult = Standard_False; + TDF_LabelSequence aShapeLabels; + Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc); + aShapeTool->GetFreeShapes(aShapeLabels); + for (TDF_LabelSequence::Iterator anIter(aShapeLabels); anIter.More(); anIter.Next()) + { + const TDF_Label& aShapeL = anIter.Value(); + if (Compact(theDoc, aShapeL)) + { + aResult = Standard_True; + } + } + return aResult; +} + //======================================================================= //function : Extract //purpose : diff --git a/src/XCAFDoc/XCAFDoc_Editor.hxx b/src/XCAFDoc/XCAFDoc_Editor.hxx index 89ac8ac7cf..65f62d8ab9 100644 --- a/src/XCAFDoc/XCAFDoc_Editor.hxx +++ b/src/XCAFDoc/XCAFDoc_Editor.hxx @@ -50,6 +50,22 @@ public: Standard_EXPORT static Standard_Boolean Expand(const TDF_Label& theDoc, const Standard_Boolean theRecursively = Standard_True); + //! Replaces assembly's childs to referred parts with location, making simple compound. + //! All parts without users are removed. + //! This action has an opposite effect to Expand() operation + //! @param[in] theDoc input document + //! @param[in] theAssemblyL input assembly shape's label + //! @return True if assembly label was successful compressed + Standard_EXPORT static Standard_Boolean Compact(const TDF_Label& theDoc, + const TDF_Label& theAssemblyL); + + //! Converts all assembly shapes in the document to simple compounds. + //! All parts without users are removed. + //! This action has an opposite effect to Expand() operation + //! @param[in] theDoc input document + //! @return True if one or more assembly labels were successful compressed + Standard_EXPORT static Standard_Boolean Compact(const TDF_Label& theDoc); + //! Clones all labels to a new position, keeping the structure with all the attributes //! @param[in] theSrcLabels original labels to copy from //! @param[in] theDstLabel label to set result as a component of or a main document's label to simply set new shape diff --git a/src/XDEDRAW/XDEDRAW_Common.cxx b/src/XDEDRAW/XDEDRAW_Common.cxx index a0697110e3..6a05fd8a23 100644 --- a/src/XDEDRAW/XDEDRAW_Common.cxx +++ b/src/XDEDRAW/XDEDRAW_Common.cxx @@ -693,6 +693,76 @@ static Standard_Integer Extract(Draw_Interpretor& di, return 0; } +//======================================================================= +//function : Compact +//purpose : +//======================================================================= +static Standard_Integer Compact(Draw_Interpretor& di, + Standard_Integer argc, + const char** argv) +{ + if (argc < 2) + { + di << "Use: " << argv[0] << " [-info] Doc [{shLabel1 shLabel2 ...}|{shape1 shape2 ...}]" << "\n"; + return 1; + } + Standard_Integer anArgcInd = 1; + Standard_Boolean toPrintInfo = Standard_False; + if (argc > 2) + { + TCollection_AsciiString aFirstArg(argv[anArgcInd]); + aFirstArg.LowerCase(); + if (aFirstArg.IsEqual("-info")) + { + toPrintInfo = Standard_True; + anArgcInd++; + } + } + Handle(TDocStd_Document) aDoc; + DDocStd::GetDocument(argv[anArgcInd], aDoc); + if (aDoc.IsNull()) + { + di << "Syntax error: " << argv[anArgcInd] << " is not a document" << "\n"; + return 1; + } + if (argc == 2) + { + if (!XCAFDoc_Editor::Compact(aDoc->Main()) && toPrintInfo) + { + di << "The document does not contain any assembly shapes" << "\n"; + } + } + else + { + Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(aDoc->Main()); + for (Standard_Integer anInd = anArgcInd + 1; anInd < argc; anInd++) + { + TDF_Label aLabel; + TDF_Tool::Label(aDoc->GetData(), argv[anInd], aLabel); + if (aLabel.IsNull()) + { + TopoDS_Shape aShape; + aShape = DBRep::Get(argv[anInd]); + aLabel = aShapeTool->FindShape(aShape); + } + if (!aLabel.IsNull()) + { + if (!XCAFDoc_Editor::Compact(aDoc->Main(), aLabel) && toPrintInfo) + { + di << argv[anInd] << " is not assembly" << "\n"; + // continue iteration + } + } + else + { + di << "Syntax error: " << argv[anInd] << " is not a shape" << "\n"; + return 1; + } + } + } + return 0; +} + //======================================================================= //function : WriteVrml //purpose : Write DECAF document to Vrml @@ -764,6 +834,10 @@ void XDEDRAW_Common::InitCommands(Draw_Interpretor& di) di.Add("XExtract", "XExtract dstDoc [dstAssmblSh] srcDoc srcLabel1 srcLabel2 ...\t" "Extracts given srcLabel1 srcLabel2 ... from srcDoc into given Doc or assembly shape", __FILE__, Extract, g); + di.Add("XCompact", "XCompact [-info] Doc [{shLabel1 shLabel2 ...}|{shape1 shape2 ...}]\t" + "Converts assembly shapes to compound shapes on the all document or selected labels or shapes\t" + " -info print information about skipped simple shapes" + __FILE__, Compact, g); di.Add("WriteVrml", "Doc filename [version VRML#1.0/VRML#2.0 (1/2): 2 by default] [representation shaded/wireframe/both (0/1/2): 0 by default]", __FILE__, WriteVrml, g); diff --git a/tests/bugs/xde/bug26302 b/tests/bugs/xde/bug26302 new file mode 100644 index 0000000000..21ca2f5004 --- /dev/null +++ b/tests/bugs/xde/bug26302 @@ -0,0 +1,85 @@ +puts "============================================================================" +puts " 0026302: Data Exchange - new functionality XCAFDoc_Editor::Compact() converting the assembly to compound" +puts "============================================================================" +puts "" + +pload DCAF + +# Trims spaces and removed empty lines within multi-line string +proc trimmedString { theString } { + set aString {} + foreach aLineIter [split $theString "\n"] { set aLine [string trimright $aLineIter]; if { $aLine != "" } { lappend aString $aLine } } + return [join $aString "\n"] +} + +Close D -silent + +box b1 0 0 0 10 10 10 +box b2 10 0 0 10 10 10 +box b3 20 0 0 10 10 10 +explode b1 +explode b2 +explode b3 +explode b1_1 +explode b2_1 +explode b3_1 +compound b1 b2 c1 +compound c1 b3 c2 +XNewDoc D +XAddShape D c2 1 +XSetColor D b1 1 0 0 +XSetColor D b2 0 1 0 +XSetColor D b3 0 0 1 +XSetColor D b1_1_4 1 1 0 +XSetColor D b2_1_4 0 1 1 +XSetColor D b3_1_4 1 0 1 +XSetColor D b1_1_3 1 0 1 +XSetColor D b2_1_3 1 1 0 +XSetColor D b3_1_3 0 1 1 + +# Input structure of the document +# ASSEMBLY COMPOUND 0:1:1:1 "ASSEMBLY" +# INSTANCE COMPOUND 0:1:1:1:1 (refers to 0:1:1:2) "=>[0:1:1:2]" +# INSTANCE SOLID 0:1:1:1:2 (refers to 0:1:1:5) "=>[0:1:1:5]" +# ASSEMBLY COMPOUND 0:1:1:2 "ASSEMBLY" +# INSTANCE SOLID 0:1:1:2:1 (refers to 0:1:1:3) "=>[0:1:1:3]" +# INSTANCE SOLID 0:1:1:2:2 (refers to 0:1:1:4) "=>[0:1:1:4]" +# PART SOLID 0:1:1:3 "SOLID" +# FACE 0:1:1:3:1 +# FACE 0:1:1:3:2 +# PART SOLID 0:1:1:4 "SOLID" +# FACE 0:1:1:4:1 +# FACE 0:1:1:4:2 +# PART SOLID 0:1:1:5 "SOLID" +# FACE 0:1:1:5:1 +# FACE 0:1:1:5:2 +# Free Shapes: 1 +# ASSEMBLY COMPOUND 0:1:1:1 "ASSEMBLY" + +# Compress all shapes in the document +XCompact D + +# Output structure of the document +set THE_REF_DUMP { +PART COMPOUND 0:1:1:1 "ASSEMBLY" + SOLID 0:1:1:1:2 "SOLID" + SOLID 0:1:1:1:3 "SOLID" + SOLID 0:1:1:1:4 "SOLID" + FACE 0:1:1:1:5 "FACE" + FACE 0:1:1:1:6 "FACE" + FACE 0:1:1:1:7 "FACE" + FACE 0:1:1:1:8 "FACE" + FACE 0:1:1:1:9 "FACE" + FACE 0:1:1:1:10 "FACE" +Free Shapes: 1 +PART COMPOUND 0:1:1:1 "ASSEMBLY" +} + +# Checking +if { [trimmedString "[uplevel #0 Xdump D]"] != [trimmedString $THE_REF_DUMP] } { + puts "Error: incorrect document structure" +} +if { [regexp "Number of labels with color link = 9" [XStat D]] != 1 } { + puts "Error: incorrect attributes" +} +Close D -silent diff --git a/tests/bugs/xde/bug26302_1 b/tests/bugs/xde/bug26302_1 new file mode 100644 index 0000000000..175064b021 --- /dev/null +++ b/tests/bugs/xde/bug26302_1 @@ -0,0 +1,17 @@ +puts "============================================================================" +puts " 0026302: Data Exchange - new functionality XCAFDoc_Editor::Compact() converting the assembly to compound" +puts "============================================================================" +puts "" + +pload DCAF + +Close D -silent + +ReadStep D [locate_data_file trj6_as1-ec-214.stp] +XGetOneShape origin D +XCompact D +XGetOneShape comp D + +checkprops origin -equal comp + +Close D -silent