From f8d4cfbb80eebca67e16df4451edcbaf9f1cf430 Mon Sep 17 00:00:00 2001 From: aba Date: Mon, 8 Feb 2016 14:47:57 +0300 Subject: [PATCH] 0027142: Data Exchange - add possibility to set location in XCAFDoc_ShapeTool interface --- src/XCAFDoc/XCAFDoc_ShapeTool.cxx | 34 ++++++++ src/XCAFDoc/XCAFDoc_ShapeTool.hxx | 9 ++ src/XDEDRAW/XDEDRAW_Shapes.cxx | 137 ++++++++++++++++++++++++++++++ tests/bugs/xde/bug27142 | 98 +++++++++++++++++++++ 4 files changed, 278 insertions(+) create mode 100644 tests/bugs/xde/bug27142 diff --git a/src/XCAFDoc/XCAFDoc_ShapeTool.cxx b/src/XCAFDoc/XCAFDoc_ShapeTool.cxx index 84bafa4dbb..b226c6f133 100644 --- a/src/XCAFDoc/XCAFDoc_ShapeTool.cxx +++ b/src/XCAFDoc/XCAFDoc_ShapeTool.cxx @@ -416,6 +416,40 @@ void XCAFDoc_ShapeTool::MakeReference (const TDF_Label &L, SetLabelNameByLink(L); } +//======================================================================= +// function : SetLocation +// purpose : +//======================================================================= +Standard_Boolean XCAFDoc_ShapeTool::SetLocation (const TDF_Label& theShapeLabel, + const TopLoc_Location& theLoc, + TDF_Label& theRefLabel) +{ + if (theLoc.IsIdentity()) + { + theRefLabel = theShapeLabel; + return Standard_True; + } + // if input label is reference -> just change the location attribute + if (IsReference (theShapeLabel)) + { + TopLoc_Location anOldLoc; + anOldLoc = GetLocation (theShapeLabel); + TopLoc_Location aNewLoc (theLoc.Transformation() * anOldLoc.Transformation()); + XCAFDoc_Location::Set(theShapeLabel, aNewLoc); + theRefLabel = theShapeLabel; + return Standard_True; + } + // if input label is shape, and it is free -> create reference to the shape + if (IsShape(theShapeLabel) && IsFree(theShapeLabel)) + { + theRefLabel = TDF_TagSource::NewChild (Label()); + MakeReference (theRefLabel, theShapeLabel, theLoc); + return Standard_True; + } + // other cases of label meaning doesn't need to apply new location + return Standard_False; +} + //======================================================================= //function : addShape //purpose : private diff --git a/src/XCAFDoc/XCAFDoc_ShapeTool.hxx b/src/XCAFDoc/XCAFDoc_ShapeTool.hxx index 7aca2734a2..100b0f6b10 100644 --- a/src/XCAFDoc/XCAFDoc_ShapeTool.hxx +++ b/src/XCAFDoc/XCAFDoc_ShapeTool.hxx @@ -401,6 +401,15 @@ public: //! from upper_usage component to next_usage //! Returns null attribute if no SHUO found Standard_EXPORT static Standard_Boolean FindSHUO (const TDF_LabelSequence& Labels, Handle(XCAFDoc_GraphNode)& theSHUOAttr); + + //! Sets location to the shape label + //! If label is reference -> changes location attribute + //! If label is free shape -> creates reference with location to it + //! @param[in] theShapeLabel the shape label to change location + //! @param[in] theLoc location to set + //! @param[out] theRefLabel the reference label with new location + //! @return TRUE if new location was set + Standard_EXPORT Standard_Boolean SetLocation (const TDF_Label& theShapeLabel, const TopLoc_Location& theLoc, TDF_Label& theRefLabel); //! Convert Shape (compound/compsolid/shell/wire) to assembly Standard_EXPORT Standard_Boolean Expand (const TDF_Label& Shape); diff --git a/src/XDEDRAW/XDEDRAW_Shapes.cxx b/src/XDEDRAW/XDEDRAW_Shapes.cxx index 709808406b..dc0edf0b5e 100644 --- a/src/XDEDRAW/XDEDRAW_Shapes.cxx +++ b/src/XDEDRAW/XDEDRAW_Shapes.cxx @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -1113,6 +1115,127 @@ static Standard_Integer XAutoNaming (Draw_Interpretor& theDI, return 0; } +//======================================================================= +// function : parseXYZ +// purpose : Converts three string arguments, to gp_XYZ with check +//======================================================================= +static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt) +{ + const TCollection_AsciiString aXYZ[3] = {theArgVec[0], theArgVec[1], theArgVec[2] }; + if (!aXYZ[0].IsRealValue (Standard_True) + || !aXYZ[1].IsRealValue (Standard_True) + || !aXYZ[2].IsRealValue (Standard_True)) + { + return Standard_False; + } + + thePnt.SetCoord (aXYZ[0].RealValue(), aXYZ[1].RealValue(), aXYZ[2].RealValue()); + return Standard_True; +} + +//======================================================================= +// function : setLocation +// purpose : Sets location to the shape at the label in XDE document +//======================================================================= +static Standard_Integer setLocation (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 4) + { + Message::SendFail() << "Error: not enough arguments, see help " << theArgVec[0] << " for details"; + return 1; + } + // get and check the document + Handle(TDocStd_Document) aDoc; + DDocStd::GetDocument (theArgVec[1], aDoc); + if (aDoc.IsNull ()) + { + Message::SendFail() << "Error: " << theArgVec[1] << " is not a document"; + return 1; + } + // get and check the label + TDF_Label aShapeLabel; + TDF_Tool::Label (aDoc->GetData(), theArgVec[2], aShapeLabel); + if (aShapeLabel.IsNull ()) + { + Message::SendFail() << "Error: no such Label: " << theArgVec[2]; + return 1; + } + // get the transformation + gp_Trsf aTransformation; + for (Standard_Integer anArgIter = 3; anArgIter < theArgNb; ++anArgIter) + { + gp_Trsf aCurTransformation; + gp_XYZ aMoveXYZ, aRotPnt, aRotAxis, aScalePnt; + Standard_Real aRotAngle, aScale; + TCollection_AsciiString anArg = theArgVec[anArgIter]; + anArg.LowerCase(); + + if (anArg == "-rotate" && + anArgIter + 7 < theArgNb && + parseXYZ (theArgVec + anArgIter + 1, aRotPnt) && + parseXYZ (theArgVec + anArgIter + 4, aRotAxis) && + Draw::ParseReal (theArgVec[anArgIter + 7], aRotAngle)) + { + anArgIter += 7; + aCurTransformation.SetRotation (gp_Ax1 (gp_Pnt (aRotPnt), gp_Dir (aRotAxis)), aRotAngle * (M_PI / 180.0)); + } + else if (anArg == "-move" && + anArgIter + 3 < theArgNb && + parseXYZ (theArgVec + anArgIter + 1, aMoveXYZ)) + { + anArgIter += 3; + aCurTransformation.SetTranslation (aMoveXYZ); + } + // first check scale with base point + else if (anArg == "-scale" && + anArgIter + 4 < theArgNb && + parseXYZ (theArgVec + anArgIter + 1, aScalePnt) && + Draw::ParseReal (theArgVec[anArgIter + 4], aScale)) + { + anArgIter += 4; + aCurTransformation.SetScale (gp_Pnt (aScalePnt), aScale); + } + // second check for scale with scale factor only + else if (anArg == "-scale" && + anArgIter + 1 < theArgNb && + Draw::ParseReal (theArgVec[anArgIter + 1], aScale)) + { + anArgIter += 1; + aCurTransformation.SetScaleFactor (aScale); + } + else + { + Message::SendFail() << "Syntax error: unknown options '" << anArg << "', or incorrect option parameters"; + return 1; + } + aTransformation.PreMultiply (aCurTransformation); + } + TopLoc_Location aLoc(aTransformation); + + // Create the ShapeTool and try to set location + Handle(XCAFDoc_ShapeTool) anAssembly = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main()); + TDF_Label aRefLabel; + if (anAssembly->SetLocation (aShapeLabel, aLoc, aRefLabel)) + { + if (aShapeLabel == aRefLabel) + { + Message::SendInfo() << "New location was set"; + } + else + { + TCollection_AsciiString aLabelStr; + TDF_Tool::Entry(aRefLabel, aLabelStr); + Message::SendInfo() << "Reference to the shape at label " << aLabelStr << " was created and location was set"; + } + } + else + { + Message::SendFail() << "Error: an attempt to set the location to a shape to which there is a reference, or to not a shape at all"; + } + + return 0; +} + //======================================================================= //function : InitCommands //purpose : @@ -1222,6 +1345,20 @@ void XDEDRAW_Shapes::InitCommands(Draw_Interpretor& di) di.Add ("XSetInstanceSHUO","Doc shape \t: sets the SHUO structure for indicated component", __FILE__, setStyledComponent, g); + + di.Add ("XSetLocation", R"( +Doc Label transformation [transformation ... ] +Applies given complex transformation to the shape at Label from Document. +The label may contain a reference to a shape, an assembly or simple shape. +The assembly or simple shape should not be referred by any reference. +Transformations: + '-move x y z' - move shape + '-rotate x y z dx dy dz angle' - rotate shape + '-scale [x y z] factor' - scale shape +Transformations are applied from left to right. +There can be more than one transformation of the same type. +At least one transformation must be specified. +)", __FILE__, setLocation, g); di.Add ("XUpdateAssemblies","Doc \t: updates assembly compounds", __FILE__, updateAssemblies, g); diff --git a/tests/bugs/xde/bug27142 b/tests/bugs/xde/bug27142 new file mode 100644 index 0000000000..49a76ca165 --- /dev/null +++ b/tests/bugs/xde/bug27142 @@ -0,0 +1,98 @@ +puts "==========" +puts "0027142: Data Exchange - add possibility to set location in XCAFDoc_ShapeTool interface" +puts "==========" +puts "" + +puts "TODO 0027142 ALL: Error: area of d1" +puts "TODO 0027142 ALL: Error: area of d2" +puts "TODO 0027142 ALL: Error: center of gravity" + +pload OCAF XDE +Close Doc -silent +XNewDoc Doc + +# Create five boxes 'a', 'b', 'c', 'd', 'e' +# Box 'e' will stay at origin of coords +# Boxes 'a', 'b', 'c', 'd' should form the new box of the size 2x2x1 at the point (3 3 0) +box a 1 1 1 +box b 1 1 1 +ttranslate b 1 1 0 +compound a b ab +XAddShape Doc ab +SetName Doc 0:1:1:1 ab +SetName Doc 0:1:1:1:1 ref_a +SetName Doc 0:1:1:1:2 ref_b +SetName Doc 0:1:1:2 a +SetName Doc 0:1:1:3 b +box c 1 1 1 +ttranslate c 1 0 0 +box d 0.5 0.5 0.5 +XAddShape Doc c +SetName Doc 0:1:1:4 ref_c +SetName Doc 0:1:1:5 c +XAddShape Doc d +SetName Doc 0:1:1:6 d +box e 1 1 1 +XAddShape Doc e +SetName Doc 0:1:1:7 e + +# Set location to the assembly (compound of boxes 'a' and 'b') +XSetLocation Doc 0:1:1:1 -rotate 0 0 0 0 0 1 90 -move 4 2 0 +SetName Doc 0:1:1:8 ref_ab +# Set location to the reference to shape (box 'c') +XSetLocation Doc 0:1:1:4 -move 1 0 0 -move 1 3 0 +# Set location to the simple shape (box 'd') +XSetLocation Doc 0:1:1:6 -move 2 2 0 -scale 2 2 0 2 +SetName Doc 0:1:1:9 ref_d + +# Write the document to files of different formats +WriteStep Doc ${imagedir}/step.step +WriteIges Doc ${imagedir}/iges.iges +XSave Doc ${imagedir}/xbf.xbf +Close Doc + +# Read document back and make screenshots +vinit +ReadStep Doc1 ${imagedir}/step.step +XDisplay Doc1; vfit +vdump ${imagedir}/step.png +vclear +ReadIges Doc2 ${imagedir}/iges.iges +XDisplay Doc2; vfit +vdump ${imagedir}/iges.png +vclear +XOpen ${imagedir}/xbf.xbf Doc3 +XDisplay Doc3; vfit +vdump ${imagedir}/xbf.png +vclose + +# Get the box 'd' from the documents +XGetShape d1 Doc1 0:1:1:8 +XGetShape d2 Doc2 0:1:1:4 +XGetShape d3 Doc3 0:1:1:9 + +# Saving disk space +Close Doc1 +Close Doc2 +Close Doc3 +file delete $imagedir/step.step +file delete $imagedir/iges.iges +file delete $imagedir/xbf.xbf + +# Scale transformation doesn't apply in STEP format and incorrectly applies in IGES format + +# Check the areas of the "problem" box 'd' +puts "Check area of the box from STEP file" +checkarea d1 6 1e-7 0.001 +puts "Check area of the box from IGES file" +checkarea d2 6 1e-7 0.001 +puts "Check area of the box from XBF file" +checkarea d3 6 1e-7 0.001 + +# Check the gravity centers of the "problem" box 'd' +puts "Check gravity center of the box from STEP file" +checkgravitycenter d1 -s 2.5 2.5 0.5 1e-7 +puts "Check gravity center of the box from IGES file" +checkgravitycenter d2 -s 2.5 2.5 0.5 1e-7 +puts "Check gravity center of the box from XBF file" +checkgravitycenter d3 -s 2.5 2.5 0.5 1e-7