BRepBuilderAPI_MakeWire - actions on a non-connectable edge [possible logical error]

Hello. 

I have been reading a documentation for MakeWire class ( https://www.opencascade.com/doc/occt-7.0.0/refman/html/class_b_rep_builder_a_p_i___make_wire.html#a8a6bc22ee4601968fe013021875f06b9 ). It says: 

Given edges are added in a sequence. Each of them must be connectable to the wire under construction, and so must satisfy the following condition (unless it is the first edge of the wire): one of its vertices must be geometrically coincident with one of the vertices of the wire (provided that the highest tolerance factor is assigned to the two vertices). It could also be the same vertex. Warning If an edge is not connectable to the wire under construction it is not added. The function Error will return BRepBuilderAPI_DisconnectedWire, the function IsDone will return false and the function Wire will raise an error, until a new connectable edge is added.

Let's say, I am adding edges one-by-one, and the last edge to add is not connectable. MakeWire instance was valid and ready to be displayed, even without the unconnectable edge. But now the new edge was not added to the MakeWire instance, AND it is not possible to obtain a Wire without that edge, because error is raised!

How, in this case, to obtain a Wire from previous step, before the unconnectable Edge was added? That edge was the last one to add. Should I re-add the last successfully added edge (which already exist in the wire)? 

Kirill Gavrilov's picture

> How, in this case, to obtain a Wire from previous step, before the unconnectable Edge was added?
> That edge was the last one to add. Should I re-add the last successfully added edge (which already exist in the wire)? 

You misunderstand the purpose of this tool.
BRepBuilderAPI_MakeWire is just a handy tool which builds a valid Wire (with some trivial healing) on a valid input.
It is not expected to be filled in with an arbitrary / invalid sequence of input data!

Ivan P's picture

Okay. So, BRepBuilderAPI_MakeWire expects only a valid input and it fails on invalid input.

But what to do if a data source of information about edges cannot be guaranteed to be 100% valid (for example, information about edges is being resolved from user's dxf)? Does OpenCascade offer another more fail-safe approach for arbitrary data?

Benjamin Bihler's picture

You could iterate over your edges before connecting them and check whether their vertices are geometrically incident. If not then you could fix that or refuse to continue.

Benjamin

Shing Liu's picture

I think you can try the class ShapeAnalysis_WireOrder to get the edges order to sort them for a valid input.

Guido van Hilst not specified's picture

Hello,

I think the best way to make a wire(s) from un-connected edges is to use: ShapeAnalysis_FreeBounds::ConnectEdgesToWires

​It tries to make a longest possible wire(s) from unconnected edges (see "shared" paramater to use unconnected edges)

Here is an example: WiresFromEdges

​Docs: FreeBounds

​Best regards,

Guido

Ivan P's picture

I'll repost your code here, for completeness:

    
        //https://www.opencascade.com/content/brepbuilderapimakewire-actions-non-connectable-edge-possible-logical-error#comment-20574

        //Hint: Select a class(or double click on class name) and press F1 for help

        //Mandatory function
        public override void Execute()
        {
            //Some points
            OCgp_Pnt p1 =Pnt(8,2,0);
            OCgp_Pnt p2 =Pnt(5,1,0);
            OCgp_Pnt p3 =Pnt(7,6,0);
            OCgp_Pnt p4 =Pnt(4,4,0);
            OCgp_Pnt p5 =Pnt(9,4,0);
            OCgp_Pnt p6 =Pnt(10,1,0);
            
          
            //make some edges from points(notice the order is not good)
            List<OCTopoDS_Edge> edges = new List<OCTopoDS_Edge>();
            edges.Add(Edge(p4,p3));
            edges.Add(Edge(p1,p5));
            edges.Add(Edge(p2,p6));
            edges.Add(Edge(p3,p5));
            edges.Add(Edge(p1,p6));
            
            
          
            // connect the edges to a single wire (see function below)
            List<OCTopoDS_Wire> wires = ConnectEdgesToWires(edges);
            
            Context.Log("Nr of wires = " + wires.Count);
            Context.Log(wires[0].Dump());
            Context.AddShape(wires[0], Color.Blue);
          
          
        }

        
 		OCTopoDS_Edge Edge(OCgp_Pnt p1 ,OCgp_Pnt p2)
        {
             return new OCBRepBuilderAPI_MakeEdge(p1,p2).Edge();
        }

		OCgp_Pnt Pnt(double x, double y, double z)
        {
             return new OCgp_Pnt(x,y,z);
        }


        public static List<OCTopoDS_Wire> ConnectEdgesToWires(
            IEnumerable<OCTopoDS_Edge> edges,
            double tolerance = 0.001,
            bool shared = false)
        {
            List<OCTopoDS_Wire> wiresOut = new List<OCTopoDS_Wire>();

            OCTopTools_HSequenceOfShape Edges = new OCTopTools_HSequenceOfShape();
            foreach (OCTopoDS_Edge edge in edges)
            {
                Edges.Append(edge);
            }

            OCTopTools_HSequenceOfShape Wires = new OCTopTools_HSequenceOfShape();

            OCShapeAnalysis_FreeBounds.ConnectEdgesToWires(Edges, tolerance, shared, Wires);

            int length = Wires.Length();

            for (int i = 1; i <= length; i++)
            {
                wiresOut.Add(Wires.Value(i).AsWire());
            }

            return wiresOut;
        }