0029692: Add functionality to make the group of touching same-dimensional shapes...
authoremv <emv@opencascade.com>
Thu, 12 Apr 2018 13:22:34 +0000 (16:22 +0300)
committerapn <apn@opencascade.com>
Fri, 7 Dec 2018 15:49:58 +0000 (18:49 +0300)
Implementation of the new class *BOPAlgo_MakeConnected* for making the group of touching same-dimensional shapes connected.
Provide the material association for the first sub-elements of the input shapes.
Provide possibility to make the connected shape periodic.

Draw commands for new algorithm:
* makeconnected - make the input shapes connected or glued, performs material associations;
* cmaterialson - returns the materials located on the requested side of a shape;
* cmakeperiodic - makes the connected shape periodic in requested directions;
* crepeatshape - repeats the periodic connected shape in requested directions requested number of times;
* cperiodictwins - returns all periodic twins for the shape;
* cclearrepetitions - clears all previous repetitions of the periodic shape, keeping the shape periodic.

Documentation & test cases for the new algorithm.

19 files changed:
dox/user_guides/draw_test_harness/draw_test_harness.md
dox/user_guides/modeling_algos/modeling_algos.md
src/BOPAlgo/BOPAlgo.msg
src/BOPAlgo/BOPAlgo_Alerts.hxx
src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
src/BOPAlgo/BOPAlgo_MakeConnected.cxx [new file with mode: 0644]
src/BOPAlgo/BOPAlgo_MakeConnected.hxx [new file with mode: 0644]
src/BOPAlgo/FILES
src/BOPTest/BOPTest.cxx
src/BOPTest/BOPTest.hxx
src/BOPTest/BOPTest_MkConnectedCommands.cxx [new file with mode: 0644]
src/BOPTest/BOPTest_PeriodicityCommands.cxx
src/BOPTest/FILES
tests/boolean/grids.list
tests/boolean/mkconnected/A1 [new file with mode: 0644]
tests/boolean/mkconnected/A2 [new file with mode: 0644]
tests/boolean/mkconnected/A3 [new file with mode: 0644]
tests/boolean/mkconnected/A4 [new file with mode: 0644]
tests/boolean/mkconnected/A5 [new file with mode: 0644]

index fdabe65..78447f5 100644 (file)
@@ -5861,6 +5861,7 @@ The following topics are covered in the eight sections of this chapter:
   * Drafting and blending.
   * Defeaturing.
   * Making shapes periodic in 3D space.
+  * Making shapes connected.
   * Analysis of shapes.
 
 
@@ -7252,6 +7253,100 @@ The command clears all previous repetitions of the periodic shape allowing to st
 No arguments are needed for the command.
 
 
+@subsection occt_draw_makeconnected Making the touching shapes connected
+
+Draw module for @ref occt_modalg_makeconnected "making the touching same-dimensional shapes connected" includes the following commands:
+* **makeconnected** - make the input shapes connected or glued, performs material associations;
+* **cmaterialson** - returns the materials located on the requested side of a shape;
+* **cmakeperiodic** - makes the connected shape periodic in requested directions;
+* **crepeatshape** - repeats the periodic connected shape in requested directions requested number of times;
+* **cperiodictwins** - returns all periodic twins for the shape;
+* **cclearrepetitions** - clears all previous repetitions of the periodic shape, keeping the shape periodic.
+
+@subsubsection occt_draw_makeconnected_makeconnected makeconnected
+
+The command makes the input touching shapes connected.
+
+Syntax:
+~~~~
+makeconnected result shape1 shape2 ...
+
+Where:
+result            - resulting connected shape.
+shape1 shape2 ... - shapes to be made connected.
+~~~~
+
+@subsubsection occt_draw_makeconnected_cmaterialson cmaterialson
+
+The command returns the materials located on the requested side of the shape.
+The command should be called after the shapes have been made connected, i.e. after the command **makeconnected**.
+
+Syntax:
+~~~~
+cmaterialson result +/- shape
+
+Where:
+result - material shapes
+shape  - shape for which the materials are needed
++/-    - side of a given shape ('+' for positive side, '-' - for negative).
+~~~~
+
+@subsubsection occt_draw_makeconnected_cmakeperiodic cmakeperiodic
+
+The command makes the connected shape periodic in the required directions with the required period.
+The command should be called after the shapes have been made connected, i.e. after the command **makeconnected**.
+
+Syntax:
+~~~~
+cmakeperiodic result [-x/y/z period [-trim first]]
+Where:
+result        - resulting periodic shape;
+shape         - input shape to make it periodic:
+-x/y/z period - option to make the shape periodic in X, Y or Z direction with the given period;
+-trim first   - option to trim the shape to fit the required period, starting the period in first.
+~~~~
+
+@subsubsection occt_draw_makeconnected_crepeatshape crepeatshape
+
+The command repeats the connected periodic shape in the required periodic directions required number of times.
+The command should be called after the shapes have been made connected and periodic, i.e. after the commands **makeconnected** and **cmakeperiodic**.
+
+Syntax:
+~~~~
+crepeatshape result -x/y/z times
+
+Where:
+result       - resulting shape;
+-x/y/z times - direction for repetition and number of repetitions (negative number of times means the repetition in negative direction).
+~~~~
+
+@subsubsection occt_draw_makeconnected_cperiodictwins cperiodictwins
+
+The command returns all periodic twins for the shape.
+The command should be called after the shapes have been made connected and periodic, i.e. after the commands **makeconnected** and **cmakeperiodic**.
+
+Syntax:
+~~~~
+cperiodictwins twins shape
+
+Where:
+twins - periodic twins of a shape.
+shape - input shape.
+~~~~
+
+@subsubsection occt_draw_makeconnected_cclearrepetitions cclearrepetitions
+
+The command clears all previous repetitions of the periodic shape keeping the shape periodic.
+The command should be called after the shapes have been made connected, periodic and the repetitions have been applied to the periodic shape, i.e. after the commands **makeconnected**, **cmakeperiodic** and **crepeatshape**.
+Otherwise the command will have no effect.
+
+Syntax:
+~~~~
+cclearrepetitions [result]
+~~~~
+
+
 @subsection occt_draw_7_9  Analysis of topology and geometry
 
 Analysis of shapes includes commands to compute length, area, volumes and inertial properties, as well as to compute some aspects impacting shape validity.
index b5bf481..dbd19bd 100644 (file)
@@ -3603,3 +3603,147 @@ repeatshape drills -x 24 -y 24
 bcut result plate drills
 ~~~~
 @figure{/user_guides/modeling_algos/images/modeling_algos_mkperiodic_im006.png,"Plate with drills",220}
+
+
+@section occt_modalg_makeconnected Making touching shapes connected
+
+Open CASCADE Technology provides tools for making the same-dimensional touching shapes connected (or glued), i.e. for making the coinciding geometries topologically shared among shapes.
+To make the shapes connected they are glued by the means of @ref occt_algorithms_7 "General Fuse algorithm". The option BOPAlgo_GlueShift is used, thus if the input shapes have been interfering the algorithm will be unable to recognize this.
+
+Making the group of shapes connected can be useful e.g. before meshing the group. It will allow making the resulting mesh conformal.
+
+The algorithm for making the shapes connected is implemented in the class *BOPAlgo_MakeConnected*.
+
+@subsection occt_modalg_makeconnected_materials Material association
+
+In frames of this tool the input shapes are called materials, and each input shape has a unique material.
+
+After making the shapes connected, the border elements of the input shapes are associated with the shapes to which they belong. At that, the orientation of the border elements in the shape is taken into account.
+The associations are made for the following types:
+* For input SOLIDS the resulting FACES are associated with the input solids;
+* For input FACES the resulting EDGES are associated with the input faces;
+* For input EDGES the resulting VERTICES are associated with the input edges.
+The association process is called the material association. It allows finding the coinciding elements for the opposite input shapes. These elements will be associated to at least two materials (one on the positive side of the shape, the other - on negative).
+
+For obtaining the material information the following methods should be used
+* *MaterialsOnPositiveSide()* - returns the original shapes (materials) located on the positive side of the given shape (i.e. with FORWARD orientation);
+* *MaterialsOnNegativeSide()* - returns the original shapes (materials) located on the negative side of the given shape (i.e. with REVERSED orientation);
+
+~~~~
+// Returns the original shapes which images contain the given shape with FORWARD orientation.
+const TopTools_ListOfShape& BOPAlgo_MakeConnected::MaterialsOnPositiveSide(const TopoDS_Shape& theS)
+
+// Returns the original shapes which images contain the given shape with REVERSED orientation.
+const TopTools_ListOfShape& BOPAlgo_MakeConnected::MaterialsOnNegativeSide(const TopoDS_Shape& theS)
+~~~~
+
+@subsection occt_modalg_makeconnected_makeperiodic Making connected shape periodic
+
+The tool provides possibility to make the connected shape @ref occt_modalg_makeperiodic "periodic".
+Since by making the shape periodic it ensures that the geometry of coinciding shapes on the opposite sides will be the same it allows reusing the mesh of the shape for its periodic twins.
+
+After making the shape periodic the material associations are updated to correspond to the actual state of the result shape. Repetition of the periodic shape is also possible from here. Material associations are not going to be lost.
+
+@subsection occt_modalg_makeconnected_history History support
+
+The algorithm supports history of shapes modifications during the operation. Additionally to standard history method provided by *BRepTools_History* and used here as a history tool, the algorithm also provides the method to track the back connection - from resulting shapes to the input ones.
+The method is called *GetOrigins()*:
+~~~~
+// Returns the list of original shapes from which the current shape has been created.
+const TopTools_ListOfShape& BOPAlgo_MakeConnected::GetOrigins(const TopoDS_Shape& theS);
+~~~~
+
+Both Gluing history and history of making the shape periodic and periodic shape repetition are available here. Note, that all repeated shapes are stored as generated into the history.
+
+@subsection occt_modalg_makeconnected_errors Errors/Warnings
+
+The algorithm supports the Error/Warning reporting system which allows obtaining the extended overview of the errors and warning occurred during the operation.
+As soon as any error appears the algorithm stops working. The warnings allow continuing the job, informing the user that something went wrong.
+The algorithm returns the following alerts:
+* *BOPAlgo_AlertTooFewArguments* - error alert is given on the attempt to run the algorithm without the arguments;
+* *BOPAlgo_AlertMultiDimensionalArguments* - error alert is given on the attempt to run the algorithm on multi-dimensional arguments;
+* *BOPAlgo_AlertUnableToGlue* - error alert is given if the gluer algorithm is unable to glue the given arguments;
+* *BOPAlgo_AlertUnableToMakePeriodic* - warning alert is given if the periodicity maker is unable to make the connected shape periodic with given options;
+* *BOPAlgo_AlertShapeIsNotPeriodic* - warning alert is given on the attempt to repeat the shape before making it periodic.
+
+For more information on the error/warning reporting system please see the chapter @ref occt_algorithms_ers "Errors and warnings reporting system" of Boolean operations user guide.
+
+@subsection occt_modalg_makeconnected_usage Usage
+
+Here is the example of usage of the *BOPAlgo_MakePeriodic* algorithm on the API level:
+~~~~
+TopTools_ListOfShape anArguments = ...;  // Shapes to make connected
+Standard_Boolean bRunParallel = ...;     // Parallel processing mode
+
+BOPAlgo_MakeConnected aMC;               // Tool for making the shapes connected
+aMC.SetArguments(anArguments);           // Set the shapes
+aMC.SetRunParallel(bRunParallel);        // Set parallel processing mode
+aMC.Perform();                           // Perform the operation
+
+if (aMC.HasErrors())                     // Check for the errors
+{
+  // errors treatment
+  Standard_SStream aSStream;
+  aMC.DumpErrors(aSStream);
+  return;
+}
+if (aMC.HasWarnings())                   // Check for the warnings
+{
+  // warnings treatment
+  Standard_SStream aSStream;
+  aMC.DumpWarnings(aSStream);
+}
+
+const TopoDS_Shape& aGluedShape = aMC.Shape(); // Connected shape
+
+// Checking material associations
+TopAbs_ShapeEnum anElemType = ...;       // Type of border element
+TopExp_Explorer anExp(anArguments.First(), anElemType);
+for (; anExp.More(); anExp.Next())
+{
+  const TopoDS_Shape& anElement = anExp.Current();
+  const TopTools_ListOfShape& aNegativeM = aMC.MaterialsOnNegativeSide(anElement);
+  const TopTools_ListOfShape& aPositiveM = aMC.MaterialsOnPositiveSide(anElement);
+}
+
+// Making the connected shape periodic
+BOPAlgo_MakePeriodic::PeriodicityParams aParams = ...; // Options for periodicity of the connected shape
+aMC.MakePeriodic(aParams);
+
+// Shape repetition after making it periodic
+// Check if the shape has been made periodic successfully
+if (aMC.PeriodicityTool().HasErrors())
+{
+  // Periodicity maker error treatment
+}
+
+// Shape repetition in periodic directions
+aMC.RepeatShape(0, 2);
+
+const TopoDS_Shape& aShape = aMC.PeriodicShape(); // Periodic and repeated shape
+~~~~
+
+Please note, that the class is based on the options class *BOPAlgo_Options*, which provides the following options for the algorithm:
+* Error/Warning reporting system;
+* Parallel processing mode.
+The other options of the base class are not supported here and will have no effect.
+
+All the history information obtained during the operation is stored into *BRepTools_History* object and available through *History()* method:
+~~~~
+// Get the history object
+const Handle(BRepTools_History)& BOPAlgo_MakeConnected::History();
+~~~~
+
+For the usage of the MakeConnected algorithm on the Draw level the following commands have been implemented:
+* **makeconnected**
+* **cmaterialson**
+* **cmakeperiodic**
+* **crepeatshape**
+* **cperiodictwins**
+* **cclearrepetitions**
+
+For more details on the connexity commands please refer the @ref occt_draw_makeconnected "MakeConnected commands" of the Draw test harness user guide.
+
+To track the history of a shape modification during MakeConnected operation the @ref occt_draw_hist "standard history commands" can be used.
+
+To have possibility to access the error/warning shapes of the operation use the *bdrawwarnshapes* command before running the algorithm (see command usage in the @ref occt_algorithms_ers "Errors and warnings reporting system" of Boolean operations user guide).
index abef3cc..7217079 100644 (file)
@@ -112,3 +112,15 @@ Unable to make the shape to look identical on opposite sides (Splitter fails)
 
 .BOPAlgo_AlertUnableToRepeat
 Unable to repeat the shape (Gluer fails)
+
+.BOPAlgo_AlertMultiDimensionalArguments
+Multi-dimensional arguments
+
+.BOPAlgo_AlertUnableToMakePeriodic
+Unable to make the shape periodic
+
+.BOPAlgo_AlertUnableToGlue
+Unable to glue the shapes
+
+.BOPAlgo_AlertShapeIsNotPeriodic
+The shape is not periodic
index 21960d8..39fe789 100644 (file)
@@ -126,4 +126,16 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToMakeIdentical)
 //! Unable to repeat the shape (Gluer fails)
 DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToRepeat)
 
+//! Multi-dimensional arguments
+DEFINE_SIMPLE_ALERT(BOPAlgo_AlertMultiDimensionalArguments)
+
+//! Unable to make the shape periodic
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToMakePeriodic)
+
+//! Unable to glue the shapes
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToGlue)
+
+//! The shape is not periodic
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertShapeIsNotPeriodic)
+
 #endif // _BOPAlgo_Alerts_HeaderFile
index 1647b22..d8fd52f 100644 (file)
@@ -114,4 +114,16 @@ static const char BOPAlgo_BOPAlgo_msg[] =
   "Unable to make the shape to look identical on opposite sides (Splitter fails)\n"
   "\n"
   ".BOPAlgo_AlertUnableToRepeat\n"
-  "Unable to repeat the shape (Gluer fails)\n";
+  "Unable to repeat the shape (Gluer fails)\n"
+  "\n"
+  ".BOPAlgo_AlertMultiDimensionalArguments\n"
+  "Multi-dimensional arguments\n"
+  "\n"
+  ".BOPAlgo_AlertUnableToMakePeriodic\n"
+  "Unable to make the shape periodic\n"
+  "\n"
+  ".BOPAlgo_AlertUnableToGlue\n"
+  "Unable to glue the shapes\n"
+  "\n"
+  ".BOPAlgo_AlertShapeIsNotPeriodic\n"
+  "The shape is not periodic\n";
diff --git a/src/BOPAlgo/BOPAlgo_MakeConnected.cxx b/src/BOPAlgo/BOPAlgo_MakeConnected.cxx
new file mode 100644 (file)
index 0000000..cd8ae8e
--- /dev/null
@@ -0,0 +1,333 @@
+// Created on: 2018-03-29
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BOPAlgo_MakeConnected.hxx>
+
+#include <BOPAlgo_Alerts.hxx>
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_Tools.hxx>
+
+#include <BOPTools_AlgoTools.hxx>
+
+#include <BRep_Builder.hxx>
+
+#include <TopExp_Explorer.hxx>
+
+#include <TopoDS_Iterator.hxx>
+
+//=======================================================================
+//function : Perform
+//purpose  : Makes the shapes connected
+//=======================================================================
+void BOPAlgo_MakeConnected::Perform()
+{
+  // Check the input data
+  CheckData();
+  if (HasErrors())
+    return;
+
+  if (myHistory.IsNull())
+    myHistory = new BRepTools_History;
+
+  // Glue the arguments
+  MakeConnected();
+  if (HasErrors())
+    return;
+
+  // Perform material associations for the faces
+  AssociateMaterials();
+  if (HasErrors())
+    return;
+}
+
+//=======================================================================
+//function : CheckData
+//purpose  : Check the validity of input data
+//=======================================================================
+void BOPAlgo_MakeConnected::CheckData()
+{
+  // Check the number of arguments
+  if (myArguments.IsEmpty())
+  {
+    // Not enough arguments
+    AddError(new BOPAlgo_AlertTooFewArguments());
+    return;
+  }
+
+  // Check that all shapes in arguments are of the same type
+
+  // Extract the shapes from the compound arguments
+  TopTools_ListOfShape aLA;
+  // Fence map
+  TopTools_MapOfShape aMFence;
+
+  TopTools_ListIteratorOfListOfShape itLA(myArguments);
+  for (; itLA.More(); itLA.Next())
+    BOPAlgo_Tools::TreatCompound(itLA.Value(), aMFence, aLA);
+
+  if (aLA.IsEmpty())
+  {
+    // It seems that all argument shapes are empty compounds
+    AddError(new BOPAlgo_AlertTooFewArguments());
+    return;
+  }
+
+  // Check dimensions of the extracted non-compound shapes
+  itLA.Initialize(aLA);
+  Standard_Integer iDim = BOPTools_AlgoTools::Dimension(itLA.Value());
+  for (itLA.Next(); itLA.More(); itLA.Next())
+  {
+    if (iDim != BOPTools_AlgoTools::Dimension(itLA.Value()))
+    {
+      // The arguments are of different type
+      AddError(new BOPAlgo_AlertMultiDimensionalArguments());
+      return;
+    }
+  }
+}
+
+//=======================================================================
+//function : MakeConnected
+//purpose  : Glues the argument shapes
+//=======================================================================
+void BOPAlgo_MakeConnected::MakeConnected()
+{
+  // Initialize the history
+  if (myGlueHistory.IsNull())
+    myGlueHistory = new BRepTools_History;
+
+  if (myArguments.Extent() == 1)
+  {
+    // No need to glue the single shape
+    myShape = myArguments.First();
+  }
+  else
+  {
+    // Glue the shapes
+    BOPAlgo_Builder aGluer;
+    aGluer.SetArguments(myArguments);
+    aGluer.SetGlue(BOPAlgo_GlueShift);
+    aGluer.SetRunParallel(myRunParallel);
+    aGluer.SetNonDestructive(Standard_True);
+    aGluer.Perform();
+    if (aGluer.HasErrors())
+    {
+      // Unable to glue the shapes
+      TopoDS_Compound aCW;
+      BRep_Builder().MakeCompound(aCW);
+      for (TopTools_ListIteratorOfListOfShape it(myArguments); it.More(); it.Next())
+        BRep_Builder().Add(aCW, it.Value());
+      AddError(new BOPAlgo_AlertUnableToGlue(aCW));
+      return;
+    }
+    myShape = aGluer.Shape();
+    // Save the gluing history
+    myGlueHistory->Merge(aGluer.Arguments(), aGluer);
+    myHistory->Merge(myGlueHistory);
+  }
+
+  // Keep the glued shape
+  myGlued = myShape;
+
+  // Fill the map of origins
+  FillOrigins();
+}
+
+//=======================================================================
+//function : FillOrigins
+//purpose  : Fills the map of origins
+//=======================================================================
+void BOPAlgo_MakeConnected::FillOrigins()
+{
+  myOrigins.Clear();
+
+  // Map the history shapes of the arguments
+  if (myAllInputsMap.IsEmpty())
+  {
+    TopTools_ListIteratorOfListOfShape itLA(myArguments);
+    for (; itLA.More(); itLA.Next())
+      TopExp::MapShapes(itLA.Value(), myAllInputsMap);
+  }
+
+  const Standard_Integer aNbS = myAllInputsMap.Extent();
+  for (Standard_Integer i = 1; i <= aNbS; ++i)
+  {
+    const TopoDS_Shape& aS = myAllInputsMap(i);
+    if (!BRepTools_History::IsSupportedType(aS))
+      continue;
+
+    // Get Modified & Generated shapes
+    for (Standard_Integer j = 0; j < 2; ++j)
+    {
+      const TopTools_ListOfShape& aLH = !j ? myHistory->Modified(aS) : myHistory->Generated(aS);
+      TopTools_ListIteratorOfListOfShape itLH(aLH);
+      for (; itLH.More(); itLH.Next())
+      {
+        const TopoDS_Shape& aHS = itLH.Value();
+        TopTools_ListOfShape* pLOr = myOrigins.ChangeSeek(aHS);
+        if (!pLOr)
+          pLOr = myOrigins.Bound(aHS, TopTools_ListOfShape());
+        if (!pLOr->Contains(aS))
+          pLOr->Append(aS);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : AssociateMaterials
+//purpose  : Associates the materials for the border elements
+//=======================================================================
+void BOPAlgo_MakeConnected::AssociateMaterials()
+{
+  myMaterials.Clear();
+
+  // Extract all non-compound shapes from the result
+  TopTools_ListOfShape aLShapes;
+  TopTools_MapOfShape aMFence;
+  BOPAlgo_Tools::TreatCompound(myShape, aMFence, aLShapes);
+
+  if (aLShapes.IsEmpty())
+    return;
+
+  // Define the element type and the material type
+  TopAbs_ShapeEnum anElemType;
+  const TopAbs_ShapeEnum aMaterialType = aLShapes.First().ShapeType();
+  if (aMaterialType == TopAbs_SOLID || aMaterialType == TopAbs_COMPSOLID)
+    anElemType = TopAbs_FACE;
+  else if (aMaterialType == TopAbs_FACE || aMaterialType == TopAbs_SHELL)
+    anElemType = TopAbs_EDGE;
+  else if (aMaterialType == TopAbs_EDGE || aMaterialType == TopAbs_WIRE)
+    anElemType = TopAbs_VERTEX;
+  else
+    return;
+
+  TopTools_ListIteratorOfListOfShape itLS(aLShapes);
+  for (; itLS.More(); itLS.Next())
+  {
+    const TopoDS_Shape& aS = itLS.Value();
+    const TopTools_ListOfShape& aLOr = GetOrigins(aS);
+    const TopoDS_Shape& aSOr = aLOr.IsEmpty() ? aS : aLOr.First();
+
+    TopExp_Explorer anExp(aS, anElemType);
+    for (; anExp.More(); anExp.Next())
+    {
+      const TopoDS_Shape& anElement = anExp.Current();
+      TopTools_ListOfShape* pLM = myMaterials.ChangeSeek(anElement);
+      if (!pLM)
+        pLM = myMaterials.Bound(anElement, TopTools_ListOfShape());
+      pLM->Append(aSOr);
+    }
+  }
+}
+
+//=======================================================================
+//function : Update
+//purpose  : Updates the history, material associations and origins map
+//           after periodicity operations
+//=======================================================================
+void BOPAlgo_MakeConnected::Update()
+{
+  // Update history
+  myHistory->Clear();
+  if (!myGlueHistory.IsNull())
+    myHistory->Merge(myGlueHistory);
+  if (!myPeriodicityMaker.History().IsNull())
+    myHistory->Merge(myPeriodicityMaker.History());
+
+  // Fill the map of origins
+  FillOrigins();
+
+  // Update the material associations after making the shape periodic
+  AssociateMaterials();
+}
+
+//=======================================================================
+//function : MakePeriodic
+//purpose  : Makes the shape periodic according to the given parameters
+//=======================================================================
+void BOPAlgo_MakeConnected::MakePeriodic(const BOPAlgo_MakePeriodic::PeriodicityParams& theParams)
+{
+  if (HasErrors())
+    return;
+
+  // Make the shape periodic
+  myPeriodicityMaker.Clear();
+  myPeriodicityMaker.SetShape(myGlued);
+  myPeriodicityMaker.SetPeriodicityParameters(theParams);
+  myPeriodicityMaker.SetRunParallel(myRunParallel);
+  myPeriodicityMaker.Perform();
+  if (myPeriodicityMaker.HasErrors())
+  {
+    // Add warning informing the user that periodicity with
+    // given parameters is not possible
+    AddWarning(new BOPAlgo_AlertUnableToMakePeriodic(myShape));
+    return;
+  }
+
+  myShape = myPeriodicityMaker.Shape();
+
+  // Update history, materials, origins
+  Update();
+}
+
+//=======================================================================
+//function : RepeatShape
+//purpose  : Repeats the shape in the given direction given number of times
+//=======================================================================
+void BOPAlgo_MakeConnected::RepeatShape(const Standard_Integer theDirectionID,
+                                        const Standard_Integer theTimes)
+{
+  if (HasErrors())
+    return;
+
+  if (myPeriodicityMaker.Shape().IsNull() || myPeriodicityMaker.HasErrors())
+  {
+    // The shape has not been made periodic yet
+    AddWarning(new BOPAlgo_AlertShapeIsNotPeriodic(myShape));
+    return;
+  }
+
+  // Repeat the shape
+  myShape = myPeriodicityMaker.RepeatShape(theDirectionID, theTimes);
+
+  // Update history, materials, origins
+  Update();
+}
+
+//=======================================================================
+//function : ClearRepetitions
+//purpose  : Clears the repetitions performed on the periodic shape
+//           keeping the shape periodic
+//=======================================================================
+void BOPAlgo_MakeConnected::ClearRepetitions()
+{
+  if (HasErrors())
+    return;
+
+  if (myPeriodicityMaker.Shape().IsNull() || myPeriodicityMaker.HasErrors())
+  {
+    // The shape has not been made periodic yet
+    AddWarning(new BOPAlgo_AlertShapeIsNotPeriodic(myShape));
+    return;
+  }
+
+  // Clear repetitions
+  myPeriodicityMaker.ClearRepetitions();
+  myShape = myPeriodicityMaker.Shape();
+
+  // Update history, materials, origins
+  Update();
+}
diff --git a/src/BOPAlgo/BOPAlgo_MakeConnected.hxx b/src/BOPAlgo/BOPAlgo_MakeConnected.hxx
new file mode 100644 (file)
index 0000000..d00aa05
--- /dev/null
@@ -0,0 +1,338 @@
+// Created on: 2018-03-29
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BOPAlgo_MakeConnected_HeaderFile
+#define _BOPAlgo_MakeConnected_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <BOPAlgo_Options.hxx>
+#include <BOPAlgo_MakePeriodic.hxx>
+
+#include <BRepTools_History.hxx>
+
+#include <NCollection_DataMap.hxx>
+
+#include <TopTools_OrientedShapeMapHasher.hxx>
+
+//! BOPAlgo_MakeConnected is the algorithm for making the touching
+//! shapes connected or glued, i.e. for making the coinciding geometries
+//! be topologically shared among the shapes.
+//!
+//! The input shapes should be of the same dimension, otherwise
+//! the gluing will not make any sense.
+//!
+//! After the shapes are made connected, the border elements of input shapes
+//! are associated with the shapes to which they belong. At that, the orientation of
+//! the border element in the shape is taken into account.
+//! The associations are made for the following types:
+//! - For input SOLIDS, the resulting FACES are associated with the input solids;
+//! - For input FACES, the resulting EDGES are associated with the input faces;
+//! - For input EDGES, the resulting VERTICES are associated with the input edges.
+//!
+//! In frames of this algorithm the input shapes are called materials,
+//! and the association process is called the material association.
+//! The material association allows finding the coinciding elements for the opposite
+//! input shapes. These elements will be associated to at least two materials.
+//!
+//! After making the shapes connected, it is possible to make the connected
+//! shape periodic using the *BOPAlgo_MakePeriodic* tool.
+//! After making the shape periodic, the material associations will be updated
+//! to correspond to the actual state of the result shape.
+//! Repetition of the periodic shape is also possible here. Material associations
+//! are not going to be lost.
+//!
+//! The algorithm supports history of shapes modification, thus it is possible
+//! to track the modification of the input shapes during the operations.
+//! Additionally to standard history methods, the algorithm provides the
+//! the method *GetOrigins()* which allows obtaining the input shapes from which
+//! the resulting shape has been created.
+//!
+//! The algorithm supports the parallel processing mode, which allows faster
+//! completion of the operations.
+//!
+//! The algorithm returns the following Error/Warning messages:
+//! - *BOPAlgo_AlertTooFewArguments* - error alert is given on the attempt to run
+//!     the algorithm without the arguments;
+//! - *BOPAlgo_AlertMultiDimensionalArguments* - error alert is given on the attempt
+//!     to run the algorithm on multi-dimensional arguments;
+//! - *BOPAlgo_AlertUnableToGlue* - error alert is given if the gluer algorithm
+//!     is unable to glue the given arguments;
+//! - *BOPAlgo_AlertUnableToMakePeriodic* - warning alert is given if the periodicity
+//!     maker is unable to make the connected shape periodic with given options;
+//! - *BOPAlgo_AlertShapeIsNotPeriodic* - warning alert is given on the attempt to
+//!     repeat the shape before making it periodic.
+//!
+//! Here is the example of usage of the algorithm:
+//! ~~~~
+//! TopTools_ListOfShape anArguments = ...;  // Shapes to make connected
+//! Standard_Boolean bRunParallel = ...;     // Parallel processing mode
+//!
+//! BOPAlgo_MakeConnected aMC;               // Tool for making the shapes connected
+//! aMC.SetArguments(anArguments);           // Set the shapes
+//! aMC.SetRunParallel(bRunParallel);        // Set parallel processing mode
+//! aMC.Perform();                           // Perform the operation
+//!
+//! if (aMC.HasErrors())                     // Check for the errors
+//! {
+//!   // errors treatment
+//!   Standard_SStream aSStream;
+//!   aMC.DumpErrors(aSStream);
+//!   return;
+//! }
+//! if (aMC.HasWarnings())                   // Check for the warnings
+//! {
+//!   // warnings treatment
+//!   Standard_SStream aSStream;
+//!   aMC.DumpWarnings(aSStream);
+//! }
+//!
+//! const TopoDS_Shape& aGluedShape = aMC.Shape(); // Connected shape
+//!
+//! // Checking material associations
+//! TopAbs_ShapeEnum anElemType = ...;       // Type of border element
+//! TopExp_Explorer anExp(anArguments.First(), anElemType);
+//! for (; anExp.More(); anExp.Next())
+//! {
+//!   const TopoDS_Shape& anElement = anExp.Current();
+//!   const TopTools_ListOfShape& aNegativeM = aMC.MaterialsOnNegativeSide(anElement);
+//!   const TopTools_ListOfShape& aPositiveM = aMC.MaterialsOnPositiveSide(anElement);
+//! }
+//!
+//! // Making the connected shape periodic
+//! BOPAlgo_MakePeriodic::PeriodicityParams aParams = ...; // Options for periodicity of the connected shape
+//! aMC.MakePeriodic(aParams);
+//!
+//! // Shape repetition after making it periodic
+//! // Check if the shape has been made periodic successfully
+//! if (aMC.PeriodicityTool().HasErrors())
+//! {
+//!   // Periodicity maker error treatment
+//! }
+//!
+//! // Shape repetition in periodic directions
+//! aMC.RepeatShape(0, 2);
+//!
+//! const TopoDS_Shape& aShape = aMC.PeriodicShape(); // Periodic and repeated shape
+//! ~~~~
+//!
+class BOPAlgo_MakeConnected : public BOPAlgo_Options
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+public: //! @name Constructor
+
+  //! Empty constructor
+  BOPAlgo_MakeConnected() : BOPAlgo_Options()
+  {
+  }
+
+
+public: //! @name Setters for the shapes to make connected
+
+  //! Sets the shape for making them connected.
+  //! @param theArgs [in] The arguments for the operation.
+  void SetArguments(const TopTools_ListOfShape& theArgs)
+  {
+    myArguments = theArgs;
+  }
+
+  //! Adds the shape to the arguments.
+  //! @param theS [in] One of the argument shapes.
+  void AddArgument(const TopoDS_Shape& theS)
+  {
+    myArguments.Append(theS);
+  }
+
+  //! Returns the list of arguments of the operation.
+  const TopTools_ListOfShape& Arguments() const
+  {
+    return myArguments;
+  }
+
+public: //! @name Performing the operations
+
+  //! Performs the operation, i.e. makes the input shapes connected.
+  Standard_EXPORT void Perform();
+
+
+public: //! @name Shape periodicity & repetition
+
+  //! Makes the connected shape periodic.
+  //! Repeated calls of this method overwrite the previous calls
+  //! working with the basis connected shape.
+  //! @param theParams [in] Periodic options.
+  Standard_EXPORT void MakePeriodic(const BOPAlgo_MakePeriodic::PeriodicityParams& theParams);
+
+  //! Performs repetition of the periodic shape in specified direction
+  //! required number of times.
+  //! @param theDirectionID [in] The direction's ID (0 for X, 1 for Y, 2 for Z);
+  //! @param theTimes [in] Requested number of repetitions (sign of the value defines
+  //!                      the side of the repetition direction (positive or negative)).
+  Standard_EXPORT void RepeatShape(const Standard_Integer theDirectionID,
+                                   const Standard_Integer theTimes);
+
+  //! Clears the repetitions performed on the periodic shape,
+  //! keeping the shape periodic.
+  Standard_EXPORT void ClearRepetitions();
+
+  //! Returns the periodicity tool.
+  const BOPAlgo_MakePeriodic& PeriodicityTool() const
+  {
+    return myPeriodicityMaker;
+  }
+
+
+public: //! @name Material transitions
+
+  //! Returns the original shapes which images contain the
+  //! the given shape with FORWARD orientation.
+  //! @param theS [in] The shape for which the materials are necessary.
+  const TopTools_ListOfShape& MaterialsOnPositiveSide(const TopoDS_Shape& theS)
+  {
+    const TopTools_ListOfShape* pLM = myMaterials.Seek(theS.Oriented(TopAbs_FORWARD));
+    return (pLM ? *pLM : EmptyList());
+  }
+
+  //! Returns the original shapes which images contain the
+  //! the given shape with REVERSED orientation.
+  //! @param theS [in] The shape for which the materials are necessary.
+  const TopTools_ListOfShape& MaterialsOnNegativeSide(const TopoDS_Shape& theS)
+  {
+    const TopTools_ListOfShape* pLM = myMaterials.Seek(theS.Oriented(TopAbs_REVERSED));
+    return (pLM ? *pLM : EmptyList());
+  }
+
+
+public: //! @name History methods
+
+  //! Returns the history of operations
+  const Handle(BRepTools_History)& History() const
+  {
+    return myHistory;
+  }
+
+  //! Returns the list of shapes modified from the given shape.
+  //! @param theS [in] The shape for which the modified shapes are necessary.
+  const TopTools_ListOfShape& GetModified(const TopoDS_Shape& theS)
+  {
+    return (myHistory.IsNull() ? EmptyList() : myHistory->Modified(theS));
+  }
+
+  //! Returns the list of original shapes from which the current shape has been created.
+  //! @param theS [in] The shape for which the origins are necessary.
+  const TopTools_ListOfShape& GetOrigins(const TopoDS_Shape& theS)
+  {
+    const TopTools_ListOfShape* pLOr = myOrigins.Seek(theS);
+    return (pLOr ? *pLOr : EmptyList());
+  }
+
+
+public: //! @name Getting the result shapes
+
+  //! Returns the resulting connected shape
+  const TopoDS_Shape& Shape() const
+  {
+    return myGlued;
+  }
+
+  //! Returns the resulting periodic & repeated shape
+  const TopoDS_Shape& PeriodicShape() const
+  {
+    return myShape;
+  }
+
+
+public: //! @name Clearing the contents of the algorithm from previous runs
+
+  //! Clears the contents of the algorithm.
+  void Clear()
+  {
+    BOPAlgo_Options::Clear();
+    myArguments.Clear();
+    myAllInputsMap.Clear();
+    myPeriodicityMaker.Clear();
+    myOrigins.Clear();
+    myMaterials.Clear();
+    if (!myGlueHistory.IsNull())
+      myGlueHistory->Clear();
+    if (!myHistory.IsNull())
+      myHistory->Clear();
+    myGlued.Nullify();
+    myShape.Nullify();
+  }
+
+
+protected: //! @name Protected methods performing the operation
+
+  //! Checks the validity of input data.
+  Standard_EXPORT void CheckData();
+
+  //! Makes the argument shapes connected (or glued).
+  Standard_EXPORT void MakeConnected();
+
+  //! Associates the materials transitions for the border elements:
+  //! - For input Solids, associates the Faces to Solids;
+  //! - For input Faces, associates the Edges to Faces;
+  //! - For input Edges, associates the Vertices to Edges.
+  Standard_EXPORT void AssociateMaterials();
+
+  //! Fills the map of origins
+  Standard_EXPORT void FillOrigins();
+
+  //! Updates the history, material associations, origins map
+  //! after periodicity operations.
+  Standard_EXPORT void Update();
+
+private:
+
+  //! Returns an empty list.
+  const TopTools_ListOfShape& EmptyList()
+  {
+    static const TopTools_ListOfShape anEmptyList;
+    return anEmptyList;
+  }
+
+protected: //! @name Fields
+
+  // Inputs
+  TopTools_ListOfShape myArguments;          //!< Input shapes for making them connected
+  TopTools_IndexedMapOfShape myAllInputsMap; //!< Map of all BRep sub-elements of the input shapes
+
+  // Tools
+  BOPAlgo_MakePeriodic myPeriodicityMaker;   //!< Tool for making the shape periodic
+
+  // Results
+  NCollection_DataMap
+    <TopoDS_Shape,
+     TopTools_ListOfShape,
+     TopTools_OrientedShapeMapHasher> myMaterials; //!< Map of the materials associations
+                                                   //! for the border elements
+  TopTools_DataMapOfShapeListOfShape myOrigins;    //!< Map of origins
+                                                   //! (allows tracking the shape's ancestors)
+
+  Handle(BRepTools_History) myGlueHistory;         //!< Gluing History
+  Handle(BRepTools_History) myHistory;             //!< Final History of shapes modifications
+                                                   //! (including making the shape periodic and repetitions)
+
+  TopoDS_Shape myGlued;                            //!< The resulting connected (glued) shape
+  TopoDS_Shape myShape;                            //!< The resulting shape
+};
+
+#endif // _BOPAlgo_MakeConnected_HeaderFile
index 50b6cec..f00444d 100644 (file)
@@ -27,6 +27,8 @@ BOPAlgo_CheckResult.cxx
 BOPAlgo_CheckResult.hxx
 BOPAlgo_CheckStatus.hxx
 BOPAlgo_ListOfCheckResult.hxx
+BOPAlgo_MakeConnected.cxx
+BOPAlgo_MakeConnected.hxx
 BOPAlgo_MakePeriodic.cxx
 BOPAlgo_MakePeriodic.hxx
 BOPAlgo_MakerVolume.cxx
index 873c184..1f797ec 100644 (file)
@@ -58,6 +58,7 @@ void  BOPTest::AllCommands(Draw_Interpretor& theCommands)
   BOPTest::UtilityCommands   (theCommands);
   BOPTest::RemoveFeaturesCommands(theCommands);
   BOPTest::PeriodicityCommands(theCommands);
+  BOPTest::MkConnectedCommands(theCommands);
 }
 //=======================================================================
 //function : Factory
index abf338d..8a34659 100644 (file)
@@ -62,6 +62,8 @@ public:
 
   Standard_EXPORT static void PeriodicityCommands (Draw_Interpretor& aDI);
 
+  Standard_EXPORT static void MkConnectedCommands (Draw_Interpretor& aDI);
+
   //! Prints errors and warnings if any and draws attached shapes 
   //! if flag BOPTest_Objects::DrawWarnShapes() is set
   Standard_EXPORT static void ReportAlerts (const Handle(Message_Report)& theReport);
diff --git a/src/BOPTest/BOPTest_MkConnectedCommands.cxx b/src/BOPTest/BOPTest_MkConnectedCommands.cxx
new file mode 100644 (file)
index 0000000..1dbd41e
--- /dev/null
@@ -0,0 +1,413 @@
+// Created on: 04/02/2018
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BOPTest.hxx>
+
+#include <BOPAlgo_MakeConnected.hxx>
+
+#include <BOPTest_DrawableShape.hxx>
+#include <BOPTest_Objects.hxx>
+
+#include <BRep_Builder.hxx>
+
+#include <BRepTest_Objects.hxx>
+
+#include <DBRep.hxx>
+#include <Draw.hxx>
+
+#include <Precision.hxx>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+
+static Standard_Integer MakeConnected(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer MakePeriodic(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer MaterialsOn(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer RepeatShape(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer GetTwins(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer ClearRepetitions(Draw_Interpretor&, Standard_Integer, const char**);
+
+namespace
+{
+  static BOPAlgo_MakeConnected TheMakeConnectedTool;
+}
+
+//=======================================================================
+//function : MkConnectedCommands
+//purpose  : 
+//=======================================================================
+void BOPTest::MkConnectedCommands(Draw_Interpretor& theCommands)
+{
+  static Standard_Boolean done = Standard_False;
+  if (done) return;
+  done = Standard_True;
+  // Chapter's name
+  const char* group = "BOPTest commands";
+  // Commands
+  theCommands.Add("makeconnected", "makeconnected result shape1 shape2 ...\n"
+                  "\t\tMake the given shapes connected (glued).",
+                  __FILE__, MakeConnected, group);
+
+  theCommands.Add("cmakeperiodic", "cmakeperiodic result [-x/y/z period [-trim first]]\n"
+                  "\t\tMake the connected shape periodic in the required directions.\n"
+                  "\t\tresult        - resulting periodic shape;\n"
+                  "\t\t-x/y/z period - option to make the shape periodic in X, Y or Z\n "
+                  "\t\t                direction with the given period;\n"
+                  "\t\t-trim first   - option to trim the shape to fit the required period,\n"
+                  "\t\t                starting the period in first.",
+                  __FILE__, MakePeriodic, group);
+
+  theCommands.Add("cmaterialson", "cmaterialson result +/- shape\n"
+                  "\t\tReturns the original shapes located on the required side of a shape:\n"
+                  "\t\t'+' - on a positive side of a shape (containing the shape with orientation FORWARD)\n"
+                  "\t\t'-' - on a negative side of a shape (containing the shape with orientation REVERSED).",
+                  __FILE__, MaterialsOn, group);
+
+  theCommands.Add("crepeatshape", "crepeatshape result -x/y/z times\n"
+                  "\t\tRepeats the periodic connected shape in periodic directions required number of times.\n"
+                  "\t\tresult       - resulting shape;\n"
+                  "\t\t-x/y/z times - direction for repetition and number of repetitions.",
+                  __FILE__, RepeatShape, group);
+
+  theCommands.Add("cperiodictwins", "cperiodictwins twins shape\n"
+                  "\t\tReturns the twins for the shape located on the opposite side of the periodic shape.",
+                  __FILE__, GetTwins, group);
+
+    theCommands.Add("cclearrepetitions", "cclearrepetitions [result]\n"
+                  "\t\tClears all previous repetitions of the periodic shape.",
+                  __FILE__, ClearRepetitions, group);
+}
+
+//=======================================================================
+//function : MakeConnected
+//purpose  : 
+//=======================================================================
+Standard_Integer MakeConnected(Draw_Interpretor& theDI,
+                               Standard_Integer  theArgc,
+                               const char ** theArgv)
+{
+  if (theArgc < 3)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  TheMakeConnectedTool.Clear();
+
+  for (Standard_Integer i = 2; i < theArgc; ++i)
+  {
+    TopoDS_Shape aS = DBRep::Get(theArgv[i]);
+    if (aS.IsNull())
+    {
+      theDI << "Error: " << theArgv[i] << " is a null shape. Skip it.\n";
+      continue;
+    }
+    TheMakeConnectedTool.AddArgument(aS);
+  }
+
+  TheMakeConnectedTool.SetRunParallel(BOPTest_Objects::RunParallel());
+
+  TheMakeConnectedTool.Perform();
+
+  // Print Error/Warning messages
+  BOPTest::ReportAlerts(TheMakeConnectedTool.GetReport());
+
+  // Set the history of the operation in session
+  BRepTest_Objects::SetHistory(TheMakeConnectedTool.History());
+
+  if (TheMakeConnectedTool.HasErrors())
+    return 0;
+
+  // Draw the result shape
+  const TopoDS_Shape& aResult = TheMakeConnectedTool.Shape();
+  DBRep::Set(theArgv[1], aResult);
+
+  return 0;
+}
+
+//=======================================================================
+//function : MakePeriodic
+//purpose  : 
+//=======================================================================
+Standard_Integer MakePeriodic(Draw_Interpretor& theDI,
+                              Standard_Integer  theArgc,
+                              const char ** theArgv)
+{
+  if (theArgc < 4)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  if (TheMakeConnectedTool.Shape().IsNull() || TheMakeConnectedTool.HasErrors())
+  {
+    theDI << "Make the shapes connected first.\n";
+    return 1;
+  }
+
+  BOPAlgo_MakePeriodic::PeriodicityParams aParams;
+
+  for (Standard_Integer i = 2; i < theArgc;)
+  {
+    Standard_Integer aDirID = -1;
+    if (!strcasecmp(theArgv[i], "-x"))
+      aDirID = 0;
+    else if (!strcasecmp(theArgv[i], "-y"))
+      aDirID = 1;
+    else if (!strcasecmp(theArgv[i], "-z"))
+      aDirID = 2;
+    else
+    {
+      theDI << theArgv[i] << " - Invalid key\n";
+      return 1;
+    }
+
+    char cDirName[2];
+    sprintf(cDirName, "%c", theArgv[i][1]);
+
+    Standard_Real aPeriod = 0;
+    if (theArgc > i + 1)
+      aPeriod = Draw::Atof(theArgv[++i]);
+
+    if (aPeriod <= Precision::Confusion())
+    {
+      theDI << "Period for " << cDirName << " direction is not set\n";
+      return 1;
+    }
+
+    aParams.myPeriodic[aDirID] = Standard_True;
+    aParams.myPeriod[aDirID] = aPeriod;
+
+    ++i;
+    if (theArgc > i + 1)
+    {
+      // Check if trimming is necessary
+      if (!strcmp(theArgv[i], "-trim"))
+      {
+        if (theArgc == (i + 1))
+        {
+          theDI << "Trim bounds for " << cDirName << " direction are not set\n";
+          return 1;
+        }
+        Standard_Real aFirst = Draw::Atof(theArgv[++i]);
+
+        aParams.myIsTrimmed[aDirID] = Standard_False;
+        aParams.myPeriodFirst[aDirID] = aFirst;
+        ++i;
+      }
+    }
+  }
+
+  TheMakeConnectedTool.MakePeriodic(aParams);
+
+  // Print Error/Warning messages
+  BOPTest::ReportAlerts(TheMakeConnectedTool.GetReport());
+
+  // Set the history of the operation in session
+  BRepTest_Objects::SetHistory(TheMakeConnectedTool.History());
+
+  if (TheMakeConnectedTool.HasErrors())
+    return 0;
+
+  // Draw the result shape
+  const TopoDS_Shape& aResult = TheMakeConnectedTool.PeriodicShape();
+  DBRep::Set(theArgv[1], aResult);
+
+  return 0;
+}
+
+//=======================================================================
+//function : RepeatShape
+//purpose  : 
+//=======================================================================
+Standard_Integer RepeatShape(Draw_Interpretor& theDI,
+                             Standard_Integer  theArgc,
+                             const char ** theArgv)
+{
+  if (theArgc < 4)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  if (TheMakeConnectedTool.PeriodicityTool().HasErrors())
+  {
+    theDI << "The shapes have not been made periodic yet.\n";
+    return 1;
+  }
+
+  for (Standard_Integer i = 2; i < theArgc; ++i)
+  {
+    Standard_Integer aDirID = -1;
+    if (!strcasecmp(theArgv[i], "-x"))
+      aDirID = 0;
+    else if (!strcasecmp(theArgv[i], "-y"))
+      aDirID = 1;
+    else if (!strcasecmp(theArgv[i], "-z"))
+      aDirID = 2;
+    else
+    {
+      theDI << theArgv[i] << " - Invalid key\n";
+      return 1;
+    }
+
+    char cDirName[2];
+    sprintf(cDirName, "%c", theArgv[i][1]);
+
+    Standard_Integer aTimes = 0;
+    if (theArgc > i + 1)
+      aTimes = Draw::Atoi(theArgv[++i]);
+
+    if (aTimes == 0)
+    {
+      theDI << "Number of repetitions for " << cDirName << " direction is not set\n";
+      return 1;
+    }
+
+    TheMakeConnectedTool.RepeatShape(aDirID, aTimes);
+  }
+
+  // Print Error/Warning messages
+  BOPTest::ReportAlerts(TheMakeConnectedTool.GetReport());
+
+  // Set the history of the operation in session
+  BRepTest_Objects::SetHistory(TheMakeConnectedTool.History());
+
+  if (TheMakeConnectedTool.HasErrors())
+    return 0;
+
+  // Draw the result shape
+  const TopoDS_Shape& aResult = TheMakeConnectedTool.PeriodicShape();
+  DBRep::Set(theArgv[1], aResult);
+
+  return 0;
+}
+
+//=======================================================================
+//function : MaterialsOn
+//purpose  : 
+//=======================================================================
+Standard_Integer MaterialsOn(Draw_Interpretor& theDI,
+                             Standard_Integer  theArgc,
+                             const char ** theArgv)
+{
+  if (theArgc != 4)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  // Get the shape to get materials
+  TopoDS_Shape aShape = DBRep::Get(theArgv[3]);
+  if (aShape.IsNull())
+  {
+    theDI << "Error: " << theArgv[3] << " is a null shape.\n";
+    return 1;
+  }
+
+  // Get the sign of a shape
+  Standard_Boolean bPositive;
+
+  if (!strcmp("+", theArgv[2]))
+    bPositive = Standard_True;
+  else if (!strcmp("-", theArgv[2]))
+    bPositive = Standard_False;
+  else
+  {
+    theDI << theArgv[2] << " - invalid key.\n";
+    return 1;
+  }
+
+  const TopTools_ListOfShape& aLS = bPositive ?
+    TheMakeConnectedTool.MaterialsOnPositiveSide(aShape) :
+    TheMakeConnectedTool.MaterialsOnNegativeSide(aShape);
+
+  TopoDS_Shape aResult;
+  if (aLS.IsEmpty())
+    theDI << "No materials on this side.\n";
+  else if (aLS.Extent() == 1)
+    aResult = aLS.First();
+  else
+  {
+    BRep_Builder().MakeCompound(TopoDS::Compound(aResult));
+    for (TopTools_ListIteratorOfListOfShape it(aLS); it.More(); it.Next())
+      BRep_Builder().Add(aResult, it.Value());
+  }
+
+  DBRep::Set(theArgv[1], aResult);
+
+  return 0;
+}
+
+//=======================================================================
+//function : GetTwin
+//purpose  : 
+//=======================================================================
+Standard_Integer GetTwins(Draw_Interpretor& theDI,
+                          Standard_Integer  theArgc,
+                          const char ** theArgv)
+{
+  if (theArgc != 3)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  // Get the shape to find twins
+  TopoDS_Shape aShape = DBRep::Get(theArgv[2]);
+  if (aShape.IsNull())
+  {
+    theDI << "Error: " << theArgv[2] << " is a null shape.\n";
+    return 1;
+  }
+
+  const TopTools_ListOfShape& aTwins = TheMakeConnectedTool.PeriodicityTool().GetTwins(aShape);
+
+  TopoDS_Shape aCTwins;
+  if (aTwins.IsEmpty())
+    theDI << "No twins for the shape.\n";
+  else if (aTwins.Extent() == 1)
+    aCTwins = aTwins.First();
+  else
+  {
+    BRep_Builder().MakeCompound(TopoDS::Compound(aCTwins));
+    for (TopTools_ListIteratorOfListOfShape it(aTwins); it.More(); it.Next())
+      BRep_Builder().Add(aCTwins, it.Value());
+  }
+
+  DBRep::Set(theArgv[1], aCTwins);
+
+  return 0;
+}
+
+//=======================================================================
+//function : ClearRepetitions
+//purpose  : 
+//=======================================================================
+Standard_Integer ClearRepetitions(Draw_Interpretor&,
+                                  Standard_Integer theArgc,
+                                  const char **theArgv)
+{
+  // Clear all previous repetitions
+  TheMakeConnectedTool.ClearRepetitions();
+
+  // Set the history of the operation in session
+  BRepTest_Objects::SetHistory(TheMakeConnectedTool.History());
+
+  if (theArgc > 1)
+    DBRep::Set(theArgv[1], TheMakeConnectedTool.PeriodicShape());
+
+  return 0;
+}
index 571745e..f29693e 100644 (file)
@@ -72,8 +72,8 @@ void BOPTest::PeriodicityCommands(Draw_Interpretor& theCommands)
                   "\t\t-x/y/z times - direction for repetition and number of repetitions.",
                   __FILE__, RepeatShape, group);
 
-  theCommands.Add("clearrepetitions", "clearrepetitions\n"
-                  "\t\tClears all previous repetitions of the periodic shape (used without any arguments).",
+  theCommands.Add("clearrepetitions", "clearrepetitions [result]\n"
+                  "\t\tClears all previous repetitions of the periodic shape.",
                   __FILE__, ClearRepetitions, group);
 }
 
@@ -280,8 +280,8 @@ Standard_Integer RepeatShape(Draw_Interpretor& theDI,
 //purpose  : 
 //=======================================================================
 Standard_Integer ClearRepetitions(Draw_Interpretor&,
-                                  Standard_Integer,
-                                  const char **)
+                                  Standard_Integer theArgc,
+                                  const char **theArgv)
 {
   // Clear all previous repetitions
   ThePeriodicityMaker.ClearRepetitions();
@@ -289,5 +289,8 @@ Standard_Integer ClearRepetitions(Draw_Interpretor&,
   // Set the history of the operation in session
   BRepTest_Objects::SetHistory(ThePeriodicityMaker.History());
 
+  if (theArgc > 1)
+    DBRep::Set(theArgv[1], ThePeriodicityMaker.Shape());
+
   return 0;
 }
index a2ceac1..dfac503 100755 (executable)
@@ -6,6 +6,7 @@ BOPTest_CheckCommands.cxx
 BOPTest_DrawableShape.cxx
 BOPTest_DrawableShape.hxx
 BOPTest_LowCommands.cxx
+BOPTest_MkConnectedCommands.cxx
 BOPTest_ObjCommands.cxx
 BOPTest_Objects.cxx
 BOPTest_Objects.hxx
index b90dc67..b949422 100644 (file)
@@ -31,4 +31,5 @@
 031 removefeatures
 032 simplify
 033 opensolid
-034 periodicity
\ No newline at end of file
+034 periodicity
+035 mkconnected
\ No newline at end of file
diff --git a/tests/boolean/mkconnected/A1 b/tests/boolean/mkconnected/A1
new file mode 100644 (file)
index 0000000..023133d
--- /dev/null
@@ -0,0 +1,61 @@
+polyline p 0 0 0 10 0 0 10 0 10 5 0 10 5 0 5 0 0 5 0 0 0
+mkplane f p
+prism b1 f 0 5 0
+box b2 0 0 5 5 5 5
+box b3 0 5 0 10 5 10
+
+# make the shapes connected
+makeconnected c b3 b1 b2
+
+checkshape c
+checknbshapes c -vertex 18 -edge 31 -wire 17 -face 17 -shell 3 -solid 3 -t
+checkprops c -s 900 -v 1000
+
+savehistory h
+
+modified m3 h b3
+checknbshapes m3 -face 7 -t
+
+# make the shape periodic
+cmakeperiodic cp -x 10 -y 10 -z 10
+checknbshapes cp -vertex 26 -edge 42 -wire 20 -face 20 -shell 3 -solid 3 -t
+
+savehistory h
+
+modified m1 h b1
+checknbshapes m1 -face 10 -t
+
+modified m2 h b2
+checknbshapes m2 -ref [nbshapes b2] -t
+
+modified m3 h b3
+checknbshapes m3 -face 8 -t
+
+
+# check material associations
+explode b3 f
+
+# the face b3_3 is REVERSED
+# materials on negative side should be only b3
+# materials on positive side should be b1 and b2
+
+modified mf h b3_3
+
+compound pos 
+compound neg
+
+foreach f [explode mf f] {
+  if {![regexp "No materials on this side" [cmaterialson p + $f]]} {
+    add p pos
+  }
+  if {![regexp "No materials on this side" [cmaterialson n - $f]]} {
+    add n neg
+  }
+}
+
+# check that neg contains b3 only
+checkprops neg -equal b3 -skip
+
+# check that pos contains both 
+compound b1 b2 comp
+checkprops pos -equal comp -skip
diff --git a/tests/boolean/mkconnected/A2 b/tests/boolean/mkconnected/A2
new file mode 100644 (file)
index 0000000..3e53724
--- /dev/null
@@ -0,0 +1,90 @@
+box b1 10 10 5
+box b2 0 0 5 10 10 1
+box b3 0 0 6 3 3 4
+polyline p 3 0 6 3 3 6 0 3 6 0 4 6 4 4 6 4 0 6 3 0 6
+mkplane f p
+prism b4 f  0 0 4
+box b5 0 9 6 4 1 4
+box b6 9 9 6 1 1 4
+box b7 9 0 6 1 3 4
+
+# make the solids connected
+makeconnected c b1 b2 b3 b4 b5 b6 b7
+
+checkshape c
+checknbshapes c -vertex 46 -edge 79 -wire 41 -face 41 -shell 7 -solid 7 -t
+checkprops c -s 888 -v 696
+
+savehistory h
+
+explode b6 f
+modified f h b6_4
+
+cmaterialson pos + f
+if {![regexp "equal shapes" [compare pos b6]]} {
+  puts "Error: incorrect material associations"
+}
+
+if {![regexp "No materials on this side." [cmaterialson neg - f]]} {
+  puts "Error: incorrect material associations"
+}
+
+# make the connected shape periodic
+cmakeperiodic cp -x 10 -y 10
+checkshape cp
+checknbshapes cp -vertex 49 -edge 83 -wire 42 -face 42 -shell 7 -solid 7 -t
+checkprops cp -s 888 -v 696
+
+# get modifications of the fifth solid
+savehistory h
+
+modified m5 h b5
+checknbshapes m5 -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -t
+checkprops m5 -s 48 -v 16
+
+
+# repeat shape
+crepeatshape res1 -x -1 -y -1 -x 1 -y 1
+
+checknbshapes res1 -vertex 496 -edge 947 -wire 564 -face 564 -shell 112 -solid 112 -t
+checkprops res1 -s 14208 -v 11136
+
+
+savehistory h
+modified f h b6_4
+
+cmaterialson pos + f
+cmaterialson neg - f
+
+if {![regexp "equal shapes" [compare pos b6]]} {
+  puts "Error: incorrect material associations"
+}
+
+if {![regexp "equal shapes" [compare neg b7]]} {
+  puts "Error: incorrect material associations"
+}
+
+
+# make the connected shape periodic with period grater than the unit cell
+cmakeperiodic cp -x 12 -trim -1 -y 12 -trim -1
+
+checknbshapes cp -ref [nbshapes c] -t
+checkprops cp -equal c
+
+crepeatshape res2 -x -1 -y -1 -x 1 -y 1
+
+checknbshapes res2 -vertex 736 -edge 1264 -wire 656 -face 656 -shell 112 -solid 112 -t
+checkprops res2 -s 14208 -v 11136
+
+savehistory h
+
+modified f h b6_4
+
+cmaterialson pos + f
+if {![regexp "equal shapes" [compare pos b6]]} {
+  puts "Error: incorrect material associations"
+}
+
+if {![regexp "No materials on this side." [cmaterialson neg - f]]} {
+  puts "Error: incorrect material associations"
+}
diff --git a/tests/boolean/mkconnected/A3 b/tests/boolean/mkconnected/A3
new file mode 100644 (file)
index 0000000..9acb82b
--- /dev/null
@@ -0,0 +1,30 @@
+restore [locate_data_file bug29692_s26.brep] s
+
+# rebuild the compound ensuring that each material is valid
+compound materials
+
+foreach c [explode s] {
+  set ss [explode $c]
+  if {[llength $ss] > 1} {
+    eval makeconnected r $ss
+    add r materials
+  } else {
+    add $ss materials
+  }
+}
+
+eval makeconnected connected [explode materials]
+
+checkshape connected
+if {![regexp "OK" [bopcheck connected]]} {
+  puts "Error: Unable to make connected"
+}
+checknbshapes connected -vertex 44 -edge 80 -wire 49 -face 47 -shell 9 -solid 9 -t
+checkprops connected -s 1.11312e+007 -v 3.0528e+008
+
+cmakeperiodic result -x 2400 -y 240
+
+checkshape result
+# no new splits expected
+checknbshapes result -ref [nbshapes connected -t] -t
+checkprops result -equal connected
diff --git a/tests/boolean/mkconnected/A4 b/tests/boolean/mkconnected/A4
new file mode 100644 (file)
index 0000000..144d4f9
--- /dev/null
@@ -0,0 +1,53 @@
+restore [locate_data_file bug29692_broken_periodicity.brep] s
+
+# rebuild the compound ensuring that each material is valid
+compound materials
+
+foreach c [explode s] {
+  set ss [explode $c]
+  if {[llength $ss] > 1} {
+    eval makeconnected r $ss
+    add r materials
+  } else {
+    add $ss materials
+  }
+}
+
+eval makeconnected connected [explode materials]
+
+checkshape connected
+if {![regexp "OK" [bopcheck connected]]} {
+  puts "Error: Unable to make connected"
+}
+checknbshapes connected -vertex 252 -edge 464 -wire 257 -face 257 -shell 44 -solid 44 -t
+checkprops connected -s 6.88455e+006 -v 9.48813e+007
+
+cmakeperiodic cp -x 373.352380466498 -y 2262.7416997969599
+
+checkshape cp
+checknbshapes cp -vertex 268 -edge 488 -wire 265 -face 265 -shell 44 -solid 44 -t
+checkprops cp -s 6.88455e+006 -v 9.48813e+007
+
+# repeat shape
+crepeatshape result -x 1 -y 1
+
+checknbshapes result -vertex 811 -edge 1594 -wire 960 -face 960 -shell 176 -solid 176 -t
+checkprops result -s 2.75382e+007 -v 3.79525e+008
+
+savehistory h
+
+explode materials_3 f
+
+generated gf h materials_3_1
+checknbshapes gf -face 4 -t
+
+foreach f [explode gf f] {
+  foreach sign {+ -} {
+    if {![regexp "No materials on this side" [cmaterialson m $sign $f]]} {
+      if {![regexp "equal shapes" [compare m materials_3]]} {
+        puts "Error: Incorrect materials association"
+      }
+    }
+  }
+}
+
diff --git a/tests/boolean/mkconnected/A5 b/tests/boolean/mkconnected/A5
new file mode 100644 (file)
index 0000000..ab9abb2
--- /dev/null
@@ -0,0 +1,63 @@
+box b1 5 5 10
+box b2 5 0 0 5 5 5
+box b3 0 5 0 5 5 5
+
+makeconnected r b1 b2 b3
+checknbshapes r -wire 18 -face 18 -shell 3 -solid 3 -t
+
+cmakeperiodic rp -x 10 -y 10
+checknbshapes rp -wire 20 -face 20 -shell 3 -solid 3 -t
+
+savehistory h
+
+explode b2 f
+modified m2 h b2_2
+cperiodictwins m2_twin m2
+
+cmaterialson m2_pos + m2
+cmaterialson m2_neg - m2_twin
+
+if {![regexp "same shapes" [compare m2_pos b2]]} {
+  puts "Error: incorrect material associations"
+}
+
+if {![regexp "same shapes" [compare m2_neg b1]]} {
+  puts "Error: incorrect material associations"
+}
+
+
+crepeatshape r -x 1 -y 1
+checknbshapes r -wire 76 -face 76 -shell 12 -solid 12 -t
+
+savehistory h
+generated g2 h b2_2
+checknbshapes g2 -face 4 -t
+
+cclearrepetitions r
+checknbshapes r -wire 20 -face 20 -shell 3 -solid 3 -t
+
+savehistory h
+
+modified m2 h b2_2
+cperiodictwins m2_twin m2
+
+cmaterialson m2_pos + m2
+cmaterialson m2_neg - m2_twin
+
+if {![regexp "same shapes" [compare m2_pos b2]]} {
+  puts "Error: incorrect material associations"
+}
+
+if {![regexp "same shapes" [compare m2_neg b1]]} {
+  puts "Error: incorrect material associations"
+}
+
+crepeatshape r -y 1
+checknbshapes r -wire 39 -face 39 -shell 6 -solid 6 -t
+
+savehistory h
+
+modified m2 h b2_2
+cperiodictwins m2_twin m2
+
+checknbshapes m2_twin -face 3 -t