// Make a TopoDS_Wire from a list of TopoDS_Edges TopoDS_Wire edgesToWire(std::vector<TopoDS_Edge> Edges) { TopoDS_Wire occwire; std::vector<TopoDS_Edge>::iterator iEdge; BRepBuilderAPI_MakeWire mkWire; for (iEdge = Edges.begin(); iEdge != Edges.end(); ++iEdge){ mkWire.Add(*iEdge); if (!mkWire.IsDone()) { Base::Console().Message("FT2FC Trace edgesToWire failed to add wire\n"); } } occwire = mkWire.Wire(); BRepLib::BuildCurves3d(occwire); return(occwire); }
// Returns the wing profile lower and upper wire fused TopoDS_Wire CCPACSWingProfile::GetSplitWire() { Update(); // rebuild closed wire BRepBuilderAPI_MakeWire closedWireBuilder; closedWireBuilder.Add(profileAlgo->GetLowerWire()); closedWireBuilder.Add(profileAlgo->GetUpperWire()); if (!profileAlgo->GetTrailingEdge().IsNull()) { closedWireBuilder.Add(profileAlgo->GetTrailingEdge()); } closedWireBuilder.Build(); if (!closedWireBuilder.IsDone()) { throw CTiglError("Error creating closed wing profile"); } return closedWireBuilder.Wire(); }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { IfcSchema::IfcCurve* basis_curve = l->BasisCurve(); bool isConic = basis_curve->is(IfcSchema::Type::IfcConic); double parameterFactor = isConic ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT); Handle(Geom_Curve) curve; if ( !convert_curve(basis_curve,curve) ) return false; bool trim_cartesian = l->MasterRepresentation() == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN; IfcEntityList::ptr trims1 = l->Trim1(); IfcEntityList::ptr trims2 = l->Trim2(); bool trimmed1 = false; bool trimmed2 = false; unsigned sense_agreement = l->SenseAgreement() ? 0 : 1; double flts[2]; gp_Pnt pnts[2]; bool has_flts[2] = {false,false}; bool has_pnts[2] = {false,false}; BRepBuilderAPI_MakeWire w; for ( IfcEntityList::it it = trims1->begin(); it != trims1->end(); it ++ ) { IfcUtil::IfcBaseClass* i = *it; if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] ); has_pnts[sense_agreement] = true; } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { const double value = *((IfcSchema::IfcParameterValue*)i); flts[sense_agreement] = value * parameterFactor; has_flts[sense_agreement] = true; } } for ( IfcEntityList::it it = trims2->begin(); it != trims2->end(); it ++ ) { IfcUtil::IfcBaseClass* i = *it; if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] ); has_pnts[1-sense_agreement] = true; } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { const double value = *((IfcSchema::IfcParameterValue*)i); flts[1-sense_agreement] = value * parameterFactor; has_flts[1-sense_agreement] = true; } } trim_cartesian &= has_pnts[0] && has_pnts[1]; bool trim_cartesian_failed = !trim_cartesian; if ( trim_cartesian ) { if ( pnts[0].Distance(pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE) ) { Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity); return false; } ShapeFix_ShapeTolerance FTol; TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(pnts[0]); TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(pnts[1]); FTol.SetTolerance(v1, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); FTol.SetTolerance(v2, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); BRepBuilderAPI_MakeEdge e (curve,v1,v2); if ( ! e.IsDone() ) { BRepBuilderAPI_EdgeError err = e.Error(); if ( err == BRepBuilderAPI_PointProjectionFailed ) { Logger::Message(Logger::LOG_WARNING,"Point projection failed for:",l->entity); trim_cartesian_failed = true; } } else { w.Add(e.Edge()); } } if ( (!trim_cartesian || trim_cartesian_failed) && (has_flts[0] && has_flts[1]) ) { // The Geom_Line is constructed from a gp_Pnt and gp_Dir, whereas the IfcLine // is defined by an IfcCartesianPoint and an IfcVector with Magnitude. Because // the vector is normalised when passed to Geom_Line constructor the magnitude // needs to be factored in with the IfcParameterValue here. if ( basis_curve->is(IfcSchema::Type::IfcLine) ) { IfcSchema::IfcLine* line = static_cast<IfcSchema::IfcLine*>(basis_curve); const double magnitude = line->Dir()->Magnitude(); flts[0] *= magnitude; flts[1] *= magnitude; } if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) { IfcSchema::IfcEllipse* ellipse = static_cast<IfcSchema::IfcEllipse*>(basis_curve); double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT); double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT); const bool rotated = y > x; if (rotated) { flts[0] -= M_PI / 2.; flts[1] -= M_PI / 2.; } } if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) { w.Add(BRepBuilderAPI_MakeEdge(curve)); } else { BRepBuilderAPI_MakeEdge e (curve,flts[0],flts[1]); w.Add(e.Edge()); } } else if ( trim_cartesian_failed && (has_pnts[0] && has_pnts[1]) ) { w.Add(BRepBuilderAPI_MakeEdge(pnts[0],pnts[1])); } if ( w.IsDone() ) { wire = w.Wire(); return true; } else { return false; } }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IFillet1d aCI (aFunction); Handle(GEOM_Function) aRefShape = aCI.GetShape(); TopoDS_Shape aShape = aRefShape->GetValue(); if (aShape.IsNull()) return 0; if (aShape.ShapeType() != TopAbs_WIRE) Standard_ConstructionError::Raise("Wrong arguments: polyline as wire must be given"); TopoDS_Wire aWire = TopoDS::Wire(aShape); double rad = aCI.GetR(); if ( rad < Precision::Confusion()) return 0; // collect vertices for make fillet TopTools_ListOfShape aVertexList; TopTools_MapOfShape mapShape; int aLen = aCI.GetLength(); if ( aLen > 0 ) { for (int ind = 1; ind <= aLen; ind++) { TopoDS_Shape aShapeVertex; if (GEOMImpl_ILocalOperations::GetSubShape (aWire, aCI.GetVertex(ind), aShapeVertex)) if (mapShape.Add(aShapeVertex)) aVertexList.Append( aShapeVertex ); } } else { // get all vertices from wire TopExp_Explorer anExp( aWire, TopAbs_VERTEX ); for ( ; anExp.More(); anExp.Next() ) { if (mapShape.Add(anExp.Current())) aVertexList.Append( anExp.Current() ); } } if (aVertexList.IsEmpty()) Standard_ConstructionError::Raise("Invalid input no vertices to make fillet"); //INFO: this algorithm implemented in assumption that user can select both // vertices of some edges to make fillet. In this case we should remember // already modified initial edges to take care in next fillet step TopTools_DataMapOfShapeShape anEdgeToEdgeMap; //iterates on vertices, and make fillet on each couple of edges //collect result fillet edges in list TopTools_ListOfShape aListOfNewEdge; // remember relation between initial and modified map TopTools_IndexedDataMapOfShapeListOfShape aMapVToEdges; TopExp::MapShapesAndAncestors( aWire, TopAbs_VERTEX, TopAbs_EDGE, aMapVToEdges ); TopTools_ListIteratorOfListOfShape anIt( aVertexList ); for ( ; anIt.More(); anIt.Next() ) { TopoDS_Vertex aV = TopoDS::Vertex( anIt.Value() ); if ( aV.IsNull() || !aMapVToEdges.Contains( aV ) ) continue; const TopTools_ListOfShape& aVertexEdges = aMapVToEdges.FindFromKey( aV ); if ( aVertexEdges.Extent() != 2 ) continue; // no input data to make fillet TopoDS_Edge anEdge1 = TopoDS::Edge( aVertexEdges.First() ); TopoDS_Edge anEdge2 = TopoDS::Edge( aVertexEdges.Last() ); // check if initial edges already modified in previous fillet operation if ( anEdgeToEdgeMap.IsBound( anEdge1 ) ) anEdge1 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge1 )); if ( anEdgeToEdgeMap.IsBound( anEdge2 ) ) anEdge2 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge2 )); if ( anEdge1.IsNull() || anEdge2.IsNull() || anEdge1.IsSame( anEdge2 ) ) continue; //no input data to make fillet // create plane on 2 edges gp_Pln aPlane; if ( !takePlane(anEdge1, anEdge2, aV, aPlane) ) continue; // seems edges does not belong to same plane or parallel (fillet can not be build) GEOMImpl_Fillet1d aFilletAlgo(anEdge1, anEdge2, aPlane); if ( !aFilletAlgo.Perform(rad) ) continue; // can not create fillet with given radius // take fillet result in given vertex TopoDS_Edge aModifE1, aModifE2; TopoDS_Edge aNewE = aFilletAlgo.Result(BRep_Tool::Pnt(aV), aModifE1, aModifE2); if (aNewE.IsNull()) continue; // no result found // add new created edges and take modified edges aListOfNewEdge.Append( aNewE ); // check if face edges modified, // if yes, than map to original edges (from vertex-edges list), because edges can be modified before if (aModifE1.IsNull() || !anEdge1.IsSame( aModifE1 )) addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.First()), aModifE1 ); if (aModifE2.IsNull() || !anEdge2.IsSame( aModifE2 )) addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.Last()), aModifE2 ); } if ( anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty() ) { StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius"); return 0; } // create new wire instead of original for ( TopExp_Explorer anExp( aWire, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { TopoDS_Shape anEdge = anExp.Current(); if ( !anEdgeToEdgeMap.IsBound( anEdge ) ) aListOfNewEdge.Append( anEdge ); else if (!anEdgeToEdgeMap.Find( anEdge ).IsNull()) aListOfNewEdge.Append( anEdgeToEdgeMap.Find( anEdge ) ); } GEOMImpl_IShapesOperations::SortShapes( aListOfNewEdge ); BRepBuilderAPI_MakeWire aWireTool; aWireTool.Add( aListOfNewEdge ); aWireTool.Build(); if (!aWireTool.IsDone()) return 0; aWire = aWireTool.Wire(); aFunction->SetValue(aWire); log.SetTouched(Label()); return 1; }
//======================================================================= // profile // command to build a profile //======================================================================= Sketcher_Profile::Sketcher_Profile(const char* aCmd) { enum {line, circle, point, none} move; Standard_Integer i = 1; Standard_Real x0, y0, x, y, dx, dy; x0 = y0 = x = y = dy = 0; dx = 1; Standard_Boolean first, stayfirst, face, close; first = Standard_True; stayfirst = face = close = Standard_False; Standard_Integer reversed = 0; Standard_Integer control_Tolerance = 0; TopoDS_Shape S; TopoDS_Vertex MP; BRepBuilderAPI_MakeWire MW; gp_Ax3 DummyHP(gp::XOY()); gp_Pln P(DummyHP); TopLoc_Location TheLocation; Handle(Geom_Surface) Surface; myOK = Standard_False; myError = 0; //TCollection_AsciiString aCommand(CORBA::string_dup(aCmd)); TCollection_AsciiString aCommand ((char*)aCmd); TCollection_AsciiString aToken = aCommand.Token(":", 1); int n = 0; // porting to WNT TColStd_Array1OfAsciiString aTab (0, aCommand.Length() - 1); if ( aCommand.Length() ) { while(aToken.Length() != 0) { if(aCommand.Token(":", n + 1).Length() > 0) aTab(n) = aCommand.Token(":", n + 1); aToken = aCommand.Token(":", ++n); } n = n - 1; } if ( aTab.Length() && aTab(0).Length() ) while(i < n) { Standard_Real length = 0, radius = 0, angle = 0; move = point; int n1 = 0; TColStd_Array1OfAsciiString a (0, aTab(0).Length()); aToken = aTab(i).Token(" ", 1); while (aToken.Length() != 0) { if (aTab(i).Token(" ", n1 + 1).Length() > 0) a(n1) = aTab(i).Token(" ", n1 + 1); aToken = aTab(i).Token(" ", ++n1); } n1 = n1 - 1; switch(a(0).Value(1)) { case 'F': { if (n1 != 3) goto badargs; if (!first) { MESSAGE("profile : The F instruction must precede all moves"); return; } x0 = x = a(1).RealValue(); y0 = y = a(2).RealValue(); stayfirst = Standard_True; break; } case 'O': { if (n1 != 4) goto badargs; P.SetLocation(gp_Pnt(a(1).RealValue(), a(2).RealValue(), a(3).RealValue())); stayfirst = Standard_True; break; } case 'P': { if (n1 != 7) goto badargs; gp_Vec vn(a(1).RealValue(), a(2).RealValue(), a(3).RealValue()); gp_Vec vx(a(4).RealValue(), a(5).RealValue(), a(6).RealValue()); if (vn.Magnitude() <= Precision::Confusion() || vx.Magnitude() <= Precision::Confusion()) { MESSAGE("profile : null direction"); return; } gp_Ax2 ax(P.Location(), vn, vx); P.SetPosition(ax); stayfirst = Standard_True; break; } case 'X': { if (n1 != 2) goto badargs; length = a(1).RealValue(); if (a(0) == "XX") length -= x; dx = 1; dy = 0; move = line; break; } case 'Y': { if (n1 != 2) goto badargs; length = a(1).RealValue(); if (a(0) == "YY") length -= y; dx = 0; dy = 1; move = line; break; } case 'L': { if (n1 != 2) goto badargs; length = a(1).RealValue(); if (Abs(length) > Precision::Confusion()) move = line; else move = none; break; } case 'T': { if (n1 != 3) goto badargs; Standard_Real vx = a(1).RealValue(); Standard_Real vy = a(2).RealValue(); if (a(0) == "TT") { vx -= x; vy -= y; } length = Sqrt(vx * vx + vy * vy); if (length > Precision::Confusion()) { move = line; dx = vx / length; dy = vy / length; } else move = none; break; } case 'R': { if (n1 != 2) goto badargs; angle = a(1).RealValue() * PI180; if (a(0) == "RR") { dx = Cos(angle); dy = Sin(angle); } else { Standard_Real c = Cos(angle); Standard_Real s = Sin(angle); Standard_Real t = c * dx - s * dy; dy = s * dx + c * dy; dx = t; } break; } case 'D': { if (n1 != 3) goto badargs; Standard_Real vx = a(1).RealValue(); Standard_Real vy = a(2).RealValue(); length = Sqrt(vx * vx + vy * vy); if (length > Precision::Confusion()) { dx = vx / length; dy = vy / length; } else move = none; break; } case 'C': { if (n1 != 3) goto badargs; radius = a(1).RealValue(); if (Abs(radius) > Precision::Confusion()) { angle = a(2).RealValue() * PI180; move = circle; } else move = none; break; } case 'A': // TAngential arc by end point { if (n1 != 3) goto badargs; Standard_Real vx = a(1).RealValue(); Standard_Real vy = a(2).RealValue(); if (a(0) == "AA") { vx -= x; vy -= y; } Standard_Real det = dx * vy - dy * vx; if ( Abs(det) > Precision::Confusion()) { Standard_Real c = (dx * vx + dy * vy) / Sqrt((dx * dx + dy * dy) * (vx * vx + vy * vy)); // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi] radius = (vx * vx + vy * vy)* Sqrt(dx * dx + dy * dy) // radius = distance between start and end point / 2 * sin(alpha) / (2.0 * det); // radius is > 0 or < 0 if (Abs(radius) > Precision::Confusion()) { angle = 2.0 * acos(c); // angle in [0,2Pi] move = circle; } else move = none; break; } else move = none; break; } case 'U': // Arc by end point and radiUs { if (n1 != 5) goto badargs; Standard_Real vx = a(1).RealValue(); Standard_Real vy = a(2).RealValue(); radius = a(3).RealValue(); reversed = a(4).IntegerValue(); if (a(0) == "UU") { // Absolute vx -= x; vy -= y; } Standard_Real length = Sqrt(vx * vx + vy * vy); if ( (4.0 - (vx * vx + vy * vy) / (radius * radius) >= 0.0 ) && (length > Precision::Confusion()) ) { Standard_Real c = 0.5 * Sqrt(4.0 - (vx * vx + vy * vy) / (radius * radius)); // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2] angle = 2.0 * acos(c); // angle in [0,Pi] if ( reversed == 2 ) angle = angle - 2 * PI; dx = 0.5 * ( vy * 1.0/radius + vx * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius))); dy = - 0.5 * ( vx * 1.0/radius - vy * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius))); move = circle; } else{ move = none; } break; } case 'E': // Arc by end point and cEnter { if (n1 != 7) goto badargs; Standard_Real vx = a(1).RealValue(); Standard_Real vy = a(2).RealValue(); Standard_Real vxc = a(3).RealValue(); Standard_Real vyc = a(4).RealValue(); reversed = a(5).IntegerValue(); control_Tolerance = a(6).IntegerValue(); if (a(0) == "EE") { // Absolute vx -= x; vy -= y; vxc -= x; vyc -= y; } radius = Sqrt( vxc * vxc + vyc * vyc ); Standard_Real det = vx * vyc - vy * vxc; Standard_Real length = Sqrt(vx * vx + vy * vy); Standard_Real length2 = Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc)); Standard_Real length3 = Sqrt(vxc * vxc + vyc * vyc); Standard_Real error = Abs(length2 - radius); myError = error; if ( error > Precision::Confusion() ){ MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error); } if ( error > Precision::Confusion() && control_Tolerance == 1) // Don't create the arc if the end point move = none; // is too far from it else if ( (length > Precision::Confusion()) && (length2 > Precision::Confusion()) && (length3 > Precision::Confusion()) ) { Standard_Real c = ( radius * radius - (vx * vxc + vy * vyc) ) / ( radius * Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc)) ) ; // Cosine of arc angle angle = acos(c); // angle in [0,Pi] if ( reversed == 2 ) angle = angle - 2 * PI; if (det < 0) angle = -angle; dx = vyc / radius; dy = -vxc / radius; move = circle; } else { move = none; } break; } case 'I': { if (n1 != 2) goto badargs; length = a(1).RealValue(); if (a(0) == "IX") { if (Abs(dx) < Precision::Confusion()) { MESSAGE("profile : cannot intersect, arg "<<i-1); return; } length = (length - x) / dx; } else if (a(0) == "IY") { if (Abs(dy) < Precision::Confusion()) { MESSAGE("profile : cannot intersect, arg "<<i-1); return; } length = (length - y) / dy; } if (Abs(length) > Precision::Confusion()) move = line; else move = none; break; } case 'W': { if (a(0) == "WW") close = Standard_True; else if(a(0) == "WF") { close = Standard_True; face = Standard_True; } i = n - 1; break; } default: { MESSAGE("profile : unknown code " << a(i)); return; } } again : switch (move) { case line : { if (length < 0) { length = -length; dx = -dx; dy = -dy; } Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy)); BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(l,P),0,length); if (!ME.IsDone()) return; MW.Add(ME); x += length*dx; y += length*dy; break; } case circle : { Standard_Boolean sense = Standard_True; if (radius < 0) { radius = -radius; sense = !sense; dx = -dx; dy = -dy; } gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx)); if (angle < 0) { angle = -angle; sense = !sense; } Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense); BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(c,P),0,angle); if (!ME.IsDone()) return; MW.Add(ME); gp_Pnt2d p; gp_Vec2d v; c->D1(angle,p,v); x = p.X(); y = p.Y(); dx = v.X() / radius; dy = v.Y() / radius; break; } case point: { MP = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, 0.0)); break; } case none: { i = n - 1; break; } } // update first first = stayfirst; stayfirst = Standard_False; if(!(dx == 0 && dy == 0)) myLastDir.SetCoord(dx, dy, 0.0); else return; myLastPoint.SetX(x); myLastPoint.SetY(y); // next segment.... i++; if ((i == n) && close) { // the closing segment dx = x0 - x; dy = y0 - y; length = Sqrt(dx * dx + dy * dy); move = line; if (length > Precision::Confusion()) { dx = dx / length; dy = dy / length; goto again; } } } // get the result, face or wire if (move == none) { return; } else if (move == point) { S = MP; } else if (face) { if (!MW.IsDone()) { return; } BRepBuilderAPI_MakeFace MF (P, MW.Wire()); if (!MF.IsDone()) { return; } S = MF; } else { if (!MW.IsDone()) { return; } S = MW; } if(!TheLocation.IsIdentity()) S.Move(TheLocation); myShape = S; myOK = true; return; badargs : MESSAGE("profile : bad number of arguments"); return; }
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) { Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve(); bool isConic = basis_curve->is(Ifc2x3::Type::IfcConic); double parameterFactor = isConic ? IfcGeom::GetValue(GV_PLANEANGLE_UNIT) : IfcGeom::GetValue(GV_LENGTH_UNIT); Handle(Geom_Curve) curve; if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false; bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN; IfcUtil::IfcAbstractSelect::list trims1 = l->Trim1(); IfcUtil::IfcAbstractSelect::list trims2 = l->Trim2(); bool trimmed1 = false; bool trimmed2 = false; unsigned sense_agreement = l->SenseAgreement() ? 0 : 1; double flts[2]; gp_Pnt pnts[2]; bool has_flts[2] = {false,false}; bool has_pnts[2] = {false,false}; BRepBuilderAPI_MakeWire w; for ( IfcUtil::IfcAbstractSelect::it it = trims1->begin(); it != trims1->end(); it ++ ) { const IfcUtil::IfcAbstractSelect::ptr i = *it; if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) { IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[sense_agreement] ); has_pnts[sense_agreement] = true; } else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) { const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue(); flts[sense_agreement] = value * parameterFactor; has_flts[sense_agreement] = true; } } for ( IfcUtil::IfcAbstractSelect::it it = trims2->begin(); it != trims2->end(); it ++ ) { const IfcUtil::IfcAbstractSelect::ptr i = *it; if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) { IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[1-sense_agreement] ); has_pnts[1-sense_agreement] = true; } else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) { const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue(); flts[1-sense_agreement] = value * parameterFactor; has_flts[1-sense_agreement] = true; } } trim_cartesian &= has_pnts[0] && has_pnts[1]; bool trim_cartesian_failed = !trim_cartesian; if ( trim_cartesian ) { if ( pnts[0].Distance(pnts[1]) < GetValue(GV_WIRE_CREATION_TOLERANCE) ) { Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity); return false; } ShapeFix_ShapeTolerance FTol; TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(pnts[0]); TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(pnts[1]); FTol.SetTolerance(v1, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); FTol.SetTolerance(v2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); BRepBuilderAPI_MakeEdge e (curve,v1,v2); if ( ! e.IsDone() ) { BRepBuilderAPI_EdgeError err = e.Error(); if ( err == BRepBuilderAPI_PointProjectionFailed ) { Logger::Message(Logger::LOG_WARNING,"Point projection failed for:",l->entity); trim_cartesian_failed = true; } } else { w.Add(e.Edge()); } } if ( (!trim_cartesian || trim_cartesian_failed) && (has_flts[0] && has_flts[1]) ) { if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) { w.Add(BRepBuilderAPI_MakeEdge(curve)); } else { BRepBuilderAPI_MakeEdge e (curve,flts[0],flts[1]); w.Add(e.Edge()); } } else if ( trim_cartesian_failed && (has_pnts[0] && has_pnts[1]) ) { w.Add(BRepBuilderAPI_MakeEdge(pnts[0],pnts[1])); } if ( w.IsDone() ) { wire = w.Wire(); return true; } else { return false; } }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_ChamferDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IChamfer aCI (aFunction); Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; Handle(GEOM_Function) aRefShape = aCI.GetShape(); TopoDS_Shape aShapeBase = aRefShape->GetValue(); if (aType == CHAMFER_SHAPE_EDGES_2D) { BRepFilletAPI_MakeFillet2d fill; TopoDS_Face aFace; Standard_Boolean aWireFlag = Standard_False; if (aShapeBase.ShapeType() == TopAbs_FACE) aFace = TopoDS::Face(aShapeBase); else if (aShapeBase.ShapeType() == TopAbs_WIRE) { TopoDS_Wire aWire = TopoDS::Wire(aShapeBase); BRepBuilderAPI_MakeFace aMF(aWire); aMF.Build(); if (!aMF.IsDone()) { StdFail_NotDone::Raise("Cannot build initial face from given wire"); } aFace = aMF.Face(); aWireFlag = Standard_True; } else StdFail_NotDone::Raise("Base shape is neither a face or a wire !"); fill.Init(aFace); double aD1_2D = aCI.GetD1(); double aD2_2D = aCI.GetD2(); TopoDS_Shape aShapeFace1, aShapeFace2; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.Get2DEdge1(), aShapeFace1) && GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.Get2DEdge2(), aShapeFace2)) { fill.AddChamfer(TopoDS::Edge(aShapeFace1), TopoDS::Edge(aShapeFace2), aD1_2D, aD2_2D); } else StdFail_NotDone::Raise("Cannot get 2d egde from sub-shape index!"); fill.Build(); if (!fill.IsDone()) { StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters"); } if (aWireFlag) { BRepBuilderAPI_MakeWire MW; TopExp_Explorer exp (fill.Shape(), TopAbs_EDGE); for (; exp.More(); exp.Next()) MW.Add(TopoDS::Edge(exp.Current())); MW.Build(); if (!MW.IsDone()) StdFail_NotDone::Raise("Resulting wire cannot be built"); aShape = MW.Shape(); } else aShape = fill.Shape(); } else { // Check the shape type. It have to be shell // or solid, or compsolid, or compound of these shapes. if (!isGoodForChamfer(aShapeBase)) { StdFail_NotDone::Raise ("Wrong shape. Must be shell or solid, or compsolid or compound of these shapes"); } BRepFilletAPI_MakeChamfer fill (aShapeBase); if (aType == CHAMFER_SHAPE_ALL) { // symmetric chamfer on all edges double aD = aCI.GetD(); TopTools_IndexedDataMapOfShapeListOfShape M; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M); for (int i = 1; i <= M.Extent(); i++) { TopoDS_Edge E = TopoDS::Edge(M.FindKey(i)); TopoDS_Face F = TopoDS::Face(M.FindFromIndex(i).First()); if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E) && M.FindFromIndex(i).Extent() == 2) fill.Add(aD, E, F); } }else if (aType == CHAMFER_SHAPE_EDGE || aType == CHAMFER_SHAPE_EDGE_AD) { // chamfer on edges, common to two faces, with D1 on the first face TopoDS_Shape aFace1, aFace2; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace1(), aFace1) && GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace2(), aFace2)) { TopoDS_Face F = TopoDS::Face(aFace1); // fill map of edges of the second face TopTools_MapOfShape aMap; TopExp_Explorer Exp2 (aFace2, TopAbs_EDGE); for (; Exp2.More(); Exp2.Next()) { aMap.Add(Exp2.Current()); } // find edges of the first face, common with the second face TopExp_Explorer Exp (aFace1, TopAbs_EDGE); for (; Exp.More(); Exp.Next()) { if (aMap.Contains(Exp.Current())) { TopoDS_Edge E = TopoDS::Edge(Exp.Current()); if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E)) { if ( aType == CHAMFER_SHAPE_EDGE ) { double aD1 = aCI.GetD1(); double aD2 = aCI.GetD2(); fill.Add(aD1, aD2, E, F); } else { double aD = aCI.GetD(); double anAngle = aCI.GetAngle(); if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) ) fill.AddDA(aD, anAngle, E, F); } } } } } } else if (aType == CHAMFER_SHAPE_FACES || aType == CHAMFER_SHAPE_FACES_AD) { // chamfer on all edges of the selected faces, with D1 on the selected face // (on first selected face, if the edge belongs to two selected faces) int aLen = aCI.GetLength(); int ind = 1; TopTools_MapOfShape aMap; TopTools_IndexedDataMapOfShapeListOfShape M; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M); for (; ind <= aLen; ind++) { TopoDS_Shape aShapeFace; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace(ind), aShapeFace)) { TopoDS_Face F = TopoDS::Face(aShapeFace); TopExp_Explorer Exp (F, TopAbs_EDGE); for (; Exp.More(); Exp.Next()) { if (!aMap.Contains(Exp.Current())) { TopoDS_Edge E = TopoDS::Edge(Exp.Current()); if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E) && M.FindFromKey(E).Extent() == 2) if (aType == CHAMFER_SHAPE_FACES) { double aD1 = aCI.GetD1(); double aD2 = aCI.GetD2(); fill.Add(aD1, aD2, E, F); } else { double aD = aCI.GetD(); double anAngle = aCI.GetAngle(); if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) ) fill.AddDA(aD, anAngle, E, F); } } } } } } else if (aType == CHAMFER_SHAPE_EDGES || aType == CHAMFER_SHAPE_EDGES_AD) { // chamfer on selected edges with lenght param D1 & D2. int aLen = aCI.GetLength(); int ind = 1; TopTools_MapOfShape aMap; TopTools_IndexedDataMapOfShapeListOfShape M; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M); for (; ind <= aLen; ind++) { TopoDS_Shape aShapeEdge; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetEdge(ind), aShapeEdge)) { TopoDS_Edge E = TopoDS::Edge(aShapeEdge); const TopTools_ListOfShape& aFacesList = M.FindFromKey(E); TopoDS_Face F = TopoDS::Face( aFacesList.First() ); if (aType == CHAMFER_SHAPE_EDGES) { double aD1 = aCI.GetD1(); double aD2 = aCI.GetD2(); fill.Add(aD1, aD2, E, F); } else { double aD = aCI.GetD(); double anAngle = aCI.GetAngle(); if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) ) fill.AddDA(aD, anAngle, E, F); } } } } else { } fill.Build(); if (!fill.IsDone()) { StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters"); } aShape = fill.Shape(); } if (aShape.IsNull()) return 0; // Check shape validity BRepCheck_Analyzer ana (aShape, false); if (!ana.IsValid()) { // 08.07.2008 added by skl during fixing bug 19761 from Mantis ShapeFix_ShapeTolerance aSFT; aSFT.LimitTolerance(aShape, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE); Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape); aSfs->Perform(); aShape = aSfs->Shape(); // fix SameParameter flag BRepLib::SameParameter(aShape, 1.E-5, Standard_True); ana.Init(aShape); if (!ana.IsValid()) { Standard_CString anErrStr("Chamfer algorithm has produced an invalid shape result"); #ifdef THROW_ON_INVALID_SH Standard_ConstructionError::Raise(anErrStr); #else MESSAGE(anErrStr); //further processing can be performed here //... //in case of failure of automatic treatment //mark the corresponding GEOM_Object as problematic TDF_Label aLabel = aFunction->GetOwnerEntry(); if (!aLabel.IsRoot()) { Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel); if (!aMainObj.IsNull()) aMainObj->SetDirty(Standard_True); } #endif } } aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }