+//================================================================================
+/*!
+ * \brief Makes a medium node if nodes reside different edges
+ */
+//================================================================================
+
+const SMDS_MeshNode* SMESH_MesherHelper::getMediumNodeOnComposedWire(const SMDS_MeshNode* n1,
+ const SMDS_MeshNode* n2,
+ bool force3d)
+{
+ gp_Pnt middle = 0.5 * XYZ(n1) + 0.5 * XYZ(n2);
+ SMDS_MeshNode* n12 = AddNode( middle.X(), middle.Y(), middle.Z() );
+
+ // To find position on edge and 3D position for n12,
+ // project <middle> to 2 edges and select projection most close to <middle>
+
+ double u = 0, distMiddleProj = Precision::Infinite();
+ int iOkEdge = 0;
+ TopoDS_Edge edges[2];
+ for ( int is2nd = 0; is2nd < 2; ++is2nd )
+ {
+ // get an edge
+ const SMDS_MeshNode* n = is2nd ? n2 : n1;
+ TopoDS_Shape shape = GetSubShapeByNode( n, GetMeshDS() );
+ if ( shape.IsNull() || shape.ShapeType() != TopAbs_EDGE )
+ continue;
+
+ // project to get U of projection and distance from middle to projection
+ TopoDS_Edge edge = edges[ is2nd ] = TopoDS::Edge( shape );
+ double node2MiddleDist = middle.Distance( XYZ(n) );
+ double foundU = GetNodeU( edge, n ), foundDist = node2MiddleDist;
+ CheckNodeU( edge, n12, foundU, 2*BRep_Tool::Tolerance(edge), /*force=*/true, &foundDist );
+ if ( foundDist < node2MiddleDist )
+ {
+ distMiddleProj = foundDist;
+ u = foundU;
+ iOkEdge = is2nd;
+ }
+ }
+ if ( Precision::IsInfinite( distMiddleProj ))
+ {
+ // both projections failed; set n12 on the edge of n1 with U of a common vertex
+ TopoDS_Vertex vCommon;
+ if ( TopExp::CommonVertex( edges[0], edges[1], vCommon ))
+ u = BRep_Tool::Parameter( vCommon, edges[0] );
+ else
+ {
+ double f,l, u0 = GetNodeU( edges[0], n1 );
+ BRep_Tool::Range( edges[0],f,l );
+ u = ( fabs(u0-f) < fabs(u0-l) ) ? f : l;
+ }
+ iOkEdge = 0;
+ distMiddleProj = 0;
+ }
+
+ // move n12 to position of a successfull projection
+ double tol = BRep_Tool::Tolerance(edges[ iOkEdge ]);
+ if ( !force3d && distMiddleProj > 2*tol )
+ {
+ TopLoc_Location loc; double f,l;
+ Handle(Geom_Curve) curve = BRep_Tool::Curve( edges[iOkEdge],loc,f,l );
+ gp_Pnt p = curve->Value( u );
+ GetMeshDS()->MoveNode( n12, p.X(), p.Y(), p.Z() );
+ }
+
+ GetMeshDS()->SetNodeOnEdge(n12, edges[iOkEdge], u);
+
+ myTLinkNodeMap.insert( make_pair( SMESH_TLink(n1,n2), n12 ));
+
+ return n12;
+}
+