OCCTesselation *OCCEdge::tesselate(double angular, double curvature) { OCCTesselation *ret = new OCCTesselation(); try { Standard_Real start, end; OCCStruct3f vert; TopLoc_Location loc = this->getEdge().Location(); gp_Trsf location = loc.Transformation(); const Handle(Geom_Curve)& curve = BRep_Tool::Curve(this->getEdge(), start, end); const GeomAdaptor_Curve& aCurve(curve); GCPnts_TangentialDeflection TD(aCurve, start, end, angular, curvature); for (Standard_Integer i = 1; i <= TD.NbPoints(); i++) { gp_Pnt pnt = TD.Value(i).Transformed(location); vert.x = (float)pnt.X(); vert.y = (float)pnt.Y(); vert.z = (float)pnt.Z(); ret->vertices.push_back(vert); } ret->ranges.push_back(0); ret->ranges.push_back(ret->vertices.size()); } catch(Standard_Failure &err) { return NULL; } return ret; }
void PointOnFacesProjector::prepare(const TopoDS_Shape& faces) { d->clear(); // Build the UB tree for binary search of points internal::UBTreeOfNodeIndicesFiller_t ubTreeFiller(d->m_ubTree, Standard_False); for (TopExp_Explorer exp(faces, TopAbs_FACE); exp.More(); exp.Next()) { const TopoDS_Face face = TopoDS::Face(exp.Current()); if (!face.IsNull()) { TopLoc_Location loc; const Handle_Poly_Triangulation& triangulation = BRep_Tool::Triangulation(face, loc); if (!triangulation.IsNull()) { d->insertMapping(triangulation, face); const gp_Trsf& trsf = loc.Transformation(); const TColgp_Array1OfPnt& nodes = triangulation->Nodes(); for (int i = nodes.Lower(); i <= nodes.Upper(); ++i) { const gp_Pnt iNode(nodes(i).Transformed(trsf)); Bnd_Box ibb; ibb.Set(iNode); ubTreeFiller.Add(std::make_pair(i, triangulation), ibb); } } } } ubTreeFiller.Fill(); }
App::DocumentObjectExecReturn *Mirroring::execute(void) { App::DocumentObject* link = Source.getValue(); if (!link) return new App::DocumentObjectExecReturn("No object linked"); if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a Part object"); Part::Feature *source = static_cast<Part::Feature*>(link); Base::Vector3f base = Base.getValue(); Base::Vector3f norm = Normal.getValue(); try { const TopoDS_Shape& shape = source->Shape.getValue(); gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z)); gp_Trsf mat; mat.SetMirror(ax2); TopLoc_Location loc = shape.Location(); gp_Trsf placement = loc.Transformation(); mat = placement * mat; BRepBuilderAPI_Transform mkTrf(shape, mat); this->Shape.setValue(mkTrf.Shape()); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }
void ChCascadeDoc::ScanCascadeShapes(callback_CascadeDoc& mcallback) { TopLoc_Location rootloc; rootloc.Identity(); Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool((*doc)->Main()); TDF_LabelSequence root_labels; shapeTool->GetFreeShapes(root_labels); for (Standard_Integer i = 1; i <= root_labels.Length(); i++) { TDF_Label label = root_labels.Value(i); int level = 0; recurse_CascadeDoc(label, shapeTool, rootloc, level, mcallback); } }
void ChCascadeDoc::FromChronoToCascade(const ChFrame<>& from_coord, TopLoc_Location& to_coord) { const ChVector<>& mpos = from_coord.GetPos(); gp_Vec mtr(mpos.x(), mpos.y(), mpos.z()); const ChMatrix33<>& from_mat = from_coord.GetA(); ((gp_Trsf)(to_coord.Transformation())) .SetValues(from_mat(0, 0), from_mat(0, 1), from_mat(0, 2), mpos.x(), from_mat(1, 0), from_mat(1, 1), from_mat(1, 2), mpos.y(), from_mat(2, 0), from_mat(2, 1), from_mat(2, 2), mpos.z()); //0, 0); }
void GEOM_ShadingFace:: OCC2VTK(const TopoDS_Face& theFace, vtkPolyData* thePolyData, vtkPoints* thePts) { TopLoc_Location aLoc; Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(theFace,aLoc); if(aPoly.IsNull()) return; else{ gp_Trsf myTransf; Standard_Boolean identity = true; if(!aLoc.IsIdentity()){ identity = false; myTransf = aLoc.Transformation(); } Standard_Integer i; int aNbOfNodes = thePts->GetNumberOfPoints(); const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); Standard_Integer nbNodesInFace = aPoly->NbNodes(); for(i = 1; i <= nbNodesInFace; i++) { gp_Pnt P = Nodes(i); if(!identity) P.Transform(myTransf); thePts->InsertNextPoint(P.X(),P.Y(),P.Z()); } const Poly_Array1OfTriangle& Triangles = aPoly->Triangles(); Standard_Integer nbTriInFace = aPoly->NbTriangles(); for(i = 1; i <= nbTriInFace; i++){ // Get the triangle Standard_Integer N1,N2,N3; Triangles(i).Get(N1,N2,N3); N1 += aNbOfNodes - 1; N2 += aNbOfNodes - 1; N3 += aNbOfNodes - 1; vtkIdType anIds[3] = {N1, N2, N3}; thePolyData->InsertNextCell(VTK_TRIANGLE,3,anIds); } } }
void ChCascadeDoc::FromCascadeToChrono(const TopLoc_Location& from_coord, ChFrame<>& to_coord) { gp_XYZ mtr = from_coord.Transformation().TranslationPart(); to_coord.SetPos(ChVector<>(mtr.X(), mtr.Y(), mtr.Z())); gp_Mat mro = from_coord.Transformation().VectorialPart(); ChMatrix33<> to_mat; to_mat(0, 0) = mro(1, 1); to_mat(0, 1) = mro(1, 2); to_mat(0, 2) = mro(1, 3); to_mat(1, 0) = mro(2, 1); to_mat(1, 1) = mro(2, 2); to_mat(1, 2) = mro(2, 3); to_mat(2, 0) = mro(3, 1); to_mat(2, 1) = mro(3, 2); to_mat(2, 2) = mro(3, 3); to_coord.SetRot(to_mat); }
OCCTesselation *OCCWire::tesselate(double angular, double curvature) { OCCTesselation *ret = new OCCTesselation(); try { Standard_Real start, end; OCCStruct3f dtmp; // explore wire edges in connected order int lastSize = 0; BRepTools_WireExplorer exWire; for (exWire.Init(this->getWire()); exWire.More(); exWire.Next()) { const TopoDS_Edge& edge = exWire.Current(); TopLoc_Location loc = edge.Location(); gp_Trsf location = loc.Transformation(); const Handle(Geom_Curve)& curve = BRep_Tool::Curve(edge, start, end); const GeomAdaptor_Curve& aCurve(curve); GCPnts_TangentialDeflection TD(aCurve, start, end, angular, curvature); ret->ranges.push_back(ret->vertices.size()); for (Standard_Integer i = 1; i <= TD.NbPoints(); i++) { gp_Pnt pnt = TD.Value(i).Transformed(location); dtmp.x = (float)pnt.X(); dtmp.y = (float)pnt.Y(); dtmp.z = (float)pnt.Z(); ret->vertices.push_back(dtmp); } ret->ranges.push_back(ret->vertices.size() - lastSize); lastSize = ret->vertices.size(); } } catch(Standard_Failure &err) { return NULL; } return ret; }
void ChCascadeDoc::FromChronoToCascade(const ChFrame<>& from_coord, TopLoc_Location& to_coord) { ChVector<> mpos = ((ChFrame<>&)from_coord).GetPos(); gp_Vec mtr(mpos.x, mpos.y, mpos.z); ChMatrix33<>* from_mat = ((ChFrame<>&)from_coord).GetA(); ((gp_Trsf)(to_coord.Transformation()) ).SetValues( (*from_mat)(0,0) ,(*from_mat)(0,1), (*from_mat)(0,2), mpos.x , (*from_mat)(1,0) ,(*from_mat)(1,1), (*from_mat)(1,2), mpos.y , (*from_mat)(2,0) ,(*from_mat)(2,1), (*from_mat)(2,2), mpos.z , 0,0); }
virtual bool ForShape(TopoDS_Shape& mshape, TopLoc_Location& mloc, char* mname, int mlevel, TDF_Label& mlabel) { for (int i=0; i<mlevel; i++) GetLog()<< " "; GetLog() << "-Name :" << mname; if (mlevel==0) GetLog() << " (root)"; GetLog() << "\n"; for (int i=0; i<mlevel; i++) GetLog()<< " "; gp_XYZ mtr = mloc.Transformation().TranslationPart(); GetLog() << " pos at: "<< mtr.X() <<" "<< mtr.Y() << " "<<mtr.Z() <<" (absolute) \n"; for (int i=0; i<mlevel; i++) GetLog()<< " "; gp_XYZ mtr2 = mshape.Location().Transformation().TranslationPart(); GetLog() << " pos at: "<< mtr2.X() <<" "<< mtr2.Y() << " "<<mtr2.Z() <<" (.Location)\n"; return true; }
void ShapeGeometryBuilder::edgeConstruct(const TopoDS_Edge &edgeIn) { TopoDS_Face face = TopoDS::Face(edgeToFace.FindFromKey(edgeIn).First()); if (face.IsNull()) throw std::runtime_error("face is null in edge construction"); TopLoc_Location location; Handle(Poly_Triangulation) triangulation; triangulation = BRep_Tool::Triangulation(face, location); const Handle(Poly_PolygonOnTriangulation) &segments = BRep_Tool::PolygonOnTriangulation(edgeIn, triangulation, location); if (segments.IsNull()) throw std::runtime_error("edge triangulation is null in edge construction"); gp_Trsf transformation; bool identity = true; if(!location.IsIdentity()) { identity = false; transformation = location.Transformation(); } const TColStd_Array1OfInteger& indexes = segments->Nodes(); const TColgp_Array1OfPnt& nodes = triangulation->Nodes(); osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array *>(edgeGeometry->getVertexArray()); osg::Vec4Array *colors = dynamic_cast<osg::Vec4Array *>(edgeGeometry->getColorArray()); osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt (GL_LINE_STRIP, indexes.Length()); osg::BoundingSphere bSphere; for (int index(indexes.Lower()); index < indexes.Upper() + 1; ++index) { gp_Pnt point = nodes(indexes(index)); if(!identity) point.Transform(transformation); vertices->push_back(osg::Vec3(point.X(), point.Y(), point.Z())); colors->push_back(edgeGeometry->getColor()); (*indices)[index - 1] = vertices->size() - 1; if (!bSphere.valid()) //for first one. { bSphere.center() = vertices->back(); bSphere.radius() = 0.0; } else bSphere.expandBy(vertices->back()); } edgeGeometry->addPrimitiveSet(indices.get()); boost::uuids::uuid id = seerShape->findShapeIdRecord(edgeIn).id; std::size_t lastPrimitiveIndex = edgeGeometry->getNumPrimitiveSets() - 1; if (!idPSetWrapperEdge->hasId(id)) { IdPSetRecord record; record.id = id; record.primitiveSetIndex = lastPrimitiveIndex; record.bSphere = bSphere; idPSetWrapperEdge->idPSetContainer.insert(record); } else //ensure that edges have the same primitive index between lod calls. //asserts here prior to having lod implemented is probably duplicate ids //for different geometry. assert(lastPrimitiveIndex == idPSetWrapperEdge->findPSetFromId(id)); }
App::DocumentObjectExecReturn *Revolution::execute(void) { App::DocumentObject* link = Sketch.getValue(); if (!link) return new App::DocumentObjectExecReturn("No sketch linked"); if (!link->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject"); Part::Part2DObject* pcSketch=static_cast<Part::Part2DObject*>(link); TopoDS_Shape shape = pcSketch->Shape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); // this is a workaround for an obscure OCC bug which leads to empty tessellations // for some faces. Making an explicit copy of the linked shape seems to fix it. // The error only happens when re-computing the shape. if (!this->Shape.getValue().IsNull()) { BRepBuilderAPI_Copy copy(shape); shape = copy.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); } TopExp_Explorer ex; std::vector<TopoDS_Wire> wires; for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { wires.push_back(TopoDS::Wire(ex.Current())); } if (wires.empty()) // there can be several wires return new App::DocumentObjectExecReturn("Linked shape object is not a wire"); // get the Sketch plane Base::Placement SketchPlm = pcSketch->Placement.getValue(); // get reference axis App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues(); if (pcReferenceAxis && pcReferenceAxis == pcSketch) { bool hasValidAxis=false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = pcSketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = pcSketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < pcSketch->getAxisCount()) { hasValidAxis = true; axis = pcSketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; Base::Vector3d base=axis.getBase(); Base::Vector3d dir=axis.getDirection(); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); } } // get revolve axis Base::Vector3f b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); Base::Vector3f v = Axis.getValue(); gp_Dir dir(v.x,v.y,v.z); // get the support of the Sketch if any App::DocumentObject* pcSupport = pcSketch->Support.getValue(); Part::Feature *SupportObject = 0; if (pcSupport && pcSupport->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) SupportObject = static_cast<Part::Feature*>(pcSupport); TopoDS_Shape aFace = makeFace(wires); if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // Rotate the face by half the angle to get revolution symmetric to sketch plane if (Midplane.getValue()) { gp_Trsf mov; mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians<double>(Angle.getValue()) * (-1.0) / 2.0); TopLoc_Location loc(mov); aFace.Move(loc); } this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); // Reverse angle if selected double angle = Base::toRadians<double>(Angle.getValue()); if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); try { // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), angle); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); // if the sketch has a support fuse them to get one result object (PAD!) if (SupportObject) { const TopoDS_Shape& support = SupportObject->Shape.getValue(); if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { // set the additive shape property for later usage in e.g. pattern this->AddShape.setValue(result); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion with support failed"); result = mkFuse.Shape(); } } this->Shape.setValue(result); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }
void ShapeGeometryBuilder::faceConstruct(const TopoDS_Face &faceIn) { TopLoc_Location location; Handle(Poly_Triangulation) triangulation; triangulation = BRep_Tool::Triangulation(faceIn, location); if (triangulation.IsNull()) throw std::runtime_error("null triangulation in face construction"); bool signalOrientation(false); if (faceIn.Orientation() == TopAbs_FORWARD) signalOrientation = true; gp_Trsf transformation; bool identity = true; if(!location.IsIdentity()) { identity = false; transformation = location.Transformation(); } //vertices. const TColgp_Array1OfPnt& nodes = triangulation->Nodes(); osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array *>(faceGeometry->getVertexArray()); osg::Vec3Array *normals = dynamic_cast<osg::Vec3Array *>(faceGeometry->getNormalArray()); osg::Vec4Array *colors = dynamic_cast<osg::Vec4Array *>(faceGeometry->getColorArray()); std::size_t offset = vertices->size(); for (int index(nodes.Lower()); index < nodes.Upper() + 1; ++index) { gp_Pnt point = nodes.Value(index); if(!identity) point.Transform(transformation); vertices->push_back(osg::Vec3(point.X(), point.Y(), point.Z())); normals->push_back(osg::Vec3(0.0, 0.0, 0.0)); colors->push_back(faceGeometry->getColor()); } const Poly_Array1OfTriangle& triangles = triangulation->Triangles(); osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt (GL_TRIANGLES, triangulation->NbTriangles() * 3); for (int index(triangles.Lower()); index < triangles.Upper() + 1; ++index) { int N1, N2, N3; triangles(index).Get(N1, N2, N3); int factor = (index - 1) * 3; if (!signalOrientation) { (*indices)[factor] = N3 - 1 + offset; (*indices)[factor + 1] = N2 - 1 + offset; (*indices)[factor + 2] = N1 - 1 + offset; } else { (*indices)[factor] = N1 - 1 + offset; (*indices)[factor + 1] = N2 - 1 + offset; (*indices)[factor + 2] = N3 - 1 + offset; } //store primitiveset index and vertex indes into map. PSetVertexRecord record; record.primitiveSetIndex = faceGeometry->getNumPrimitiveSets(); record.vertexIndex = (*indices)[factor]; pSetTriangleWrapper->pSetVertexContainer.insert(record); record.vertexIndex = (*indices)[factor + 1]; pSetTriangleWrapper->pSetVertexContainer.insert(record); record.vertexIndex = (*indices)[factor + 2]; pSetTriangleWrapper->pSetVertexContainer.insert(record); //now that we are combining faces into one geometry, osgUtil SmoothingVisitor //wants to 'average' out normals across faces. so we go back to manual calculation //of surface normals. osg::Vec3 pointOne(vertices->at((*indices)[factor])); osg::Vec3 pointTwo(vertices->at((*indices)[factor + 1])); osg::Vec3 pointThree(vertices->at((*indices)[factor + 2])); osg::Vec3 axisOne(pointTwo - pointOne); osg::Vec3 axisTwo(pointThree - pointOne); osg::Vec3 currentNormal(axisOne ^ axisTwo); if (currentNormal.isNaN()) continue; currentNormal.normalize(); osg::Vec3 tempNormal; tempNormal = (*normals)[(*indices)[factor]]; tempNormal += currentNormal; tempNormal.normalize(); (*normals)[(*indices)[factor]] = tempNormal; tempNormal = (*normals)[(*indices)[factor + 1]]; tempNormal += currentNormal; tempNormal.normalize(); (*normals)[(*indices)[factor + 1]] = tempNormal; tempNormal = (*normals)[(*indices)[factor + 2]]; tempNormal += currentNormal; tempNormal.normalize(); (*normals)[(*indices)[factor + 2]] = tempNormal; } faceGeometry->addPrimitiveSet(indices.get()); boost::uuids::uuid id = seerShape->findShapeIdRecord(faceIn).id; std::size_t lastPrimitiveIndex = faceGeometry->getNumPrimitiveSets() - 1; if (!idPSetWrapperFace->hasId(id)) { IdPSetRecord record; record.id = id; record.primitiveSetIndex = lastPrimitiveIndex; idPSetWrapperFace->idPSetContainer.insert(record); } else //ensure that the faces have the same primitive index between lod calls. assert(lastPrimitiveIndex == idPSetWrapperFace->findPSetFromId(id)); }
App::DocumentObjectExecReturn *Revolution::execute(void) { // Validate parameters double angle = Angle.getValue(); if (angle < Precision::Confusion()) return new App::DocumentObjectExecReturn("Angle of revolution too small"); if (angle > 360.0) return new App::DocumentObjectExecReturn("Angle of revolution too large"); angle = Base::toRadians<double>(angle); // Reverse angle if selected if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); std::vector<TopoDS_Wire> wires; try { wires = getSketchWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } TopoDS_Shape support; try { support = getSupportShape(); } catch (const Base::Exception&) { // ignore, because support isn't mandatory support = TopoDS_Shape(); } // update Axis from ReferenceAxis updateAxis(); // get revolve axis Base::Vector3d b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); Base::Vector3d v = Axis.getValue(); gp_Dir dir(v.x,v.y,v.z); try { TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // Rotate the face by half the angle to get Revolution symmetric to sketch plane if (Midplane.getValue()) { gp_Trsf mov; mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians<double>(Angle.getValue()) * (-1.0) / 2.0); TopLoc_Location loc(mov); sketchshape.Move(loc); } this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); support.Move(invObjLoc); sketchshape.Move(invObjLoc); // Check distance between sketchshape and axis - to avoid failures and crashes if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(sketchshape))) return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); result = refineShapeIfActive(result); // set the additive shape property for later usage in e.g. pattern this->AddShape.setValue(result); // if the sketch has a support fuse them to get one result object (PAD!) if (!support.IsNull()) { // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(support, result); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion with support failed"); result = mkFuse.Shape(); result = refineShapeIfActive(result); } this->Shape.setValue(result); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
static bool recurse_CascadeDoc(TDF_Label label, Handle_XCAFDoc_ShapeTool& shapeTool, TopLoc_Location& parentloc, int level, ChCascadeDoc::callback_CascadeDoc& mcallback) { TDF_LabelSequence child_labels; Standard_Boolean is_assembly; is_assembly = shapeTool->GetComponents(label, child_labels, 0); char mstring[200] = "no name"; Standard_PCharacter mchastr = mstring; // access name Handle_TDataStd_Name N; if (label.FindAttribute(TDataStd_Name::GetID(), N)) { N->Get().ToUTF8CString(mchastr); } TDF_Label reflabel; Standard_Boolean isref = shapeTool->GetReferredShape(label, reflabel); if (isref) // ..maybe it references some shape: the name is stored there... { Handle_TDataStd_Name N; if (reflabel.FindAttribute(TDataStd_Name::GetID(), N)) { N->Get().ToUTF8CString(mchastr); } } TopLoc_Location mloc = shapeTool->GetLocation(label); TopLoc_Location absloc = parentloc.Multiplied(mloc); // access shape and position TopoDS_Shape rShape; rShape = shapeTool->GetShape(label); if (!rShape.IsNull()) { // === call the callback! === if (!mcallback.ForShape(rShape, absloc, mstring, level, label)) return false; // (skip children recursion if returned false) } // Recurse all children !!! if (is_assembly) { for (Standard_Integer j = 1; j <= child_labels.Length(); j++) { TDF_Label clabel = child_labels.Value(j); recurse_CascadeDoc(clabel, shapeTool, absloc, (level + 1), mcallback); } } // If it is a reference, Recurse all children of reference if (isref) { TDF_LabelSequence refchild_labels; Standard_Boolean refis_assembly; refis_assembly = shapeTool->GetComponents(reflabel, refchild_labels, 0); for (Standard_Integer j = 1; j <= refchild_labels.Length(); j++) { TDF_Label clabel = refchild_labels.Value(j); recurse_CascadeDoc(clabel, shapeTool, absloc, (level + 1), mcallback); } } return true; }
App::DocumentObjectExecReturn *RuledSurface::execute(void) { try { App::DocumentObjectExecReturn* ret; // get the first input shape TopoDS_Shape S1; ret = getShape(Curve1, S1); if (ret) return ret; // get the second input shape TopoDS_Shape S2; ret = getShape(Curve2, S2); if (ret) return ret; // check for expected type if (S1.IsNull() || S2.IsNull()) return new App::DocumentObjectExecReturn("Linked shapes are empty."); if (S1.ShapeType() != TopAbs_EDGE && S1.ShapeType() != TopAbs_WIRE) return new App::DocumentObjectExecReturn("Linked shape is neither edge nor wire."); if (S2.ShapeType() != TopAbs_EDGE && S2.ShapeType() != TopAbs_WIRE) return new App::DocumentObjectExecReturn("Linked shape is neither edge nor wire."); // https://forum.freecadweb.org/viewtopic.php?f=8&t=24052 // // if both shapes are sub-elements of one common shape then the fill algorithm // leads to problems if the shape has set a placement // The workaround is to reset the placement before calling BRepFill and then // applying the placement to the output shape TopLoc_Location Loc; if (Curve1.getValue() == Curve2.getValue()) { Loc = S1.Location(); if (!Loc.IsIdentity() && Loc == S2.Location()) { S1.Location(TopLoc_Location()); S2.Location(TopLoc_Location()); } } // make both shapes to have the same type Standard_Boolean isWire = Standard_False; if (S1.ShapeType() == TopAbs_WIRE) isWire = Standard_True; if (isWire) { if (S2.ShapeType() == TopAbs_EDGE) S2 = BRepLib_MakeWire(TopoDS::Edge(S2)); } else { // S1 is an edge, if S2 is a wire convert S1 to a wire, too if (S2.ShapeType() == TopAbs_WIRE) { S1 = BRepLib_MakeWire(TopoDS::Edge(S1)); isWire = Standard_True; } } if (Orientation.getValue() == 0) { // Automatic Handle(Adaptor3d_HCurve) a1; Handle(Adaptor3d_HCurve) a2; if (!isWire) { BRepAdaptor_Curve adapt1(TopoDS::Edge(S1)); BRepAdaptor_Curve adapt2(TopoDS::Edge(S2)); a1 = new BRepAdaptor_HCurve(adapt1); a2 = new BRepAdaptor_HCurve(adapt2); } else { BRepAdaptor_CompCurve adapt1(TopoDS::Wire(S1)); BRepAdaptor_CompCurve adapt2(TopoDS::Wire(S2)); a1 = new BRepAdaptor_HCompCurve(adapt1); a2 = new BRepAdaptor_HCompCurve(adapt2); } if (!a1.IsNull() && !a2.IsNull()) { // get end points of 1st curve Standard_Real first, last; first = a1->FirstParameter(); last = a1->LastParameter(); if (S1.Closed()) last = (first + last)/2; gp_Pnt p1 = a1->Value(first); gp_Pnt p2 = a1->Value(last); if (S1.Orientation() == TopAbs_REVERSED) { std::swap(p1, p2); } // get end points of 2nd curve first = a2->FirstParameter(); last = a2->LastParameter(); if (S2.Closed()) last = (first + last)/2; gp_Pnt p3 = a2->Value(first); gp_Pnt p4 = a2->Value(last); if (S2.Orientation() == TopAbs_REVERSED) { std::swap(p3, p4); } // Form two triangles (P1,P2,P3) and (P4,P3,P2) and check their normals. // If the dot product is negative then it's assumed that the resulting face // is twisted, hence the 2nd edge is reversed. gp_Vec v1(p1, p2); gp_Vec v2(p1, p3); gp_Vec n1 = v1.Crossed(v2); gp_Vec v3(p4, p3); gp_Vec v4(p4, p2); gp_Vec n2 = v3.Crossed(v4); if (n1.Dot(n2) < 0) { S2.Reverse(); } } } else if (Orientation.getValue() == 2) { // Reverse S2.Reverse(); } TopoDS_Shape ruledShape; if (!isWire) { ruledShape = BRepFill::Face(TopoDS::Edge(S1), TopoDS::Edge(S2)); } else { ruledShape = BRepFill::Shell(TopoDS::Wire(S1), TopoDS::Wire(S2)); } // re-apply the placement in case we reset it if (!Loc.IsIdentity()) ruledShape.Move(Loc); Loc = ruledShape.Location(); if (!Loc.IsIdentity()) { // reset the placement of the shape because the Placement // property will be changed ruledShape.Location(TopLoc_Location()); Base::Matrix4D transform; TopoShape::convertToMatrix(Loc.Transformation(), transform); this->Placement.setValue(Base::Placement(transform)); } this->Shape.setValue(ruledShape); return App::DocumentObject::StdReturn; } catch (Standard_Failure& e) { return new App::DocumentObjectExecReturn(e.GetMessageString()); } catch (...) { return new App::DocumentObjectExecReturn("General error in RuledSurface::execute()"); } }
App::DocumentObjectExecReturn *Groove::execute(void) { // Validate parameters double angle = Angle.getValue(); if (angle < Precision::Confusion()) return new App::DocumentObjectExecReturn("Angle of groove too small"); if (angle > 360.0) return new App::DocumentObjectExecReturn("Angle of groove too large"); angle = Base::toRadians<double>(angle); // Reverse angle if selected if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); Part::Part2DObject* sketch = 0; std::vector<TopoDS_Wire> wires; TopoDS_Shape support; try { sketch = getVerifiedSketch(); wires = getSketchWires(); support = getSupportShape(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } // get the Sketch plane Base::Placement SketchPlm = sketch->Placement.getValue(); // get reference axis App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues(); if (pcReferenceAxis && pcReferenceAxis == sketch) { bool hasValidAxis=false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; Base::Vector3d base=axis.getBase(); Base::Vector3d dir=axis.getDirection(); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); } } // get revolve axis Base::Vector3f b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); Base::Vector3f v = Axis.getValue(); gp_Dir dir(v.x,v.y,v.z); try { TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // Rotate the face by half the angle to get Groove symmetric to sketch plane if (Midplane.getValue()) { gp_Trsf mov; mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians<double>(Angle.getValue()) * (-1.0) / 2.0); TopLoc_Location loc(mov); sketchshape.Move(loc); } this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); support.Move(invObjLoc); sketchshape.Move(invObjLoc); // Check distance between sketchshape and axis - to avoid failures and crashes if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(sketchshape))) return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); // set the subtractive shape property for later usage in e.g. pattern this->SubShape.setValue(result); // cut out groove to get one result object BRepAlgoAPI_Cut mkCut(support, result); // Let's check if the fusion has been successful if (!mkCut.IsDone()) throw Base::Exception("Cut out of support failed"); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape solRes = this->getSolid(mkCut.Shape()); if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); this->Shape.setValue(solRes); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
App::DocumentObjectExecReturn *Pad::execute(void) { // Validate parameters double L = Length.getValue(); if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Length of pad too small"); double L2 = Length2.getValue(); if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Second length of pad too small"); Part::Part2DObject* sketch = 0; std::vector<TopoDS_Wire> wires; try { sketch = getVerifiedSketch(); wires = getSketchWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } TopoDS_Shape support; try { support = getSupportShape(); } catch (const Base::Exception&) { // ignore, because support isn't mandatory support = TopoDS_Shape(); } // get the Sketch plane Base::Placement SketchPos = sketch->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchVector(0,0,1); SketchOrientation.multVec(SketchVector,SketchVector); this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); try { support.Move(invObjLoc); gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Pad: Creating a face from sketch failed"); sketchshape.Move(invObjLoc); TopoDS_Shape prism; std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace") { TopoDS_Face supportface = getSupportFace(); supportface.Move(invObjLoc); if (Reversed.getValue()) dir.Reverse(); // Find a valid face to extrude up to TopoDS_Face upToFace; if (method == "UpToFace") { getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } getUpToFace(upToFace, support, supportface, sketchshape, method, dir); // A support object is always required and we need to use BRepFeat_MakePrism // Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid // because the feature does not add any material. This only happens with the "2" option, though // Note: It might be possible to pass a shell or a compound containing multiple faces // as the Until parameter of Perform() BRepFeat_MakePrism PrismMaker; PrismMaker.Init(support, sketchshape, supportface, dir, 2, 1); PrismMaker.Perform(upToFace); if (!PrismMaker.IsDone()) return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!"); prism = PrismMaker.Shape(); } else { generatePrism(prism, sketchshape, method, dir, L, L2, Midplane.getValue(), Reversed.getValue()); } if (prism.IsNull()) return new App::DocumentObjectExecReturn("Pad: Resulting shape is empty"); // set the additive shape property for later usage in e.g. pattern this->AddShape.setValue(prism); // if the sketch has a support fuse them to get one result object if (!support.IsNull()) { // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(support, prism); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) return new App::DocumentObjectExecReturn("Pad: Fusion with support failed"); TopoDS_Shape result = mkFuse.Shape(); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape solRes = this->getSolid(result); // lets check if the result is a solid if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pad: Resulting shape is not a solid"); this->Shape.setValue(solRes); } else { this->Shape.setValue(prism); } return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
//======================================================================= //function : MakeScaledPrism //purpose : //======================================================================= TopoDS_Shape GEOMImpl_PrismDriver::MakeScaledPrism (const TopoDS_Shape& theShapeBase, const gp_Vec& theVector, const Standard_Real theScaleFactor, const gp_Pnt& theCDG, bool isCDG) { TopoDS_Shape aShape; BRep_Builder B; // 1. aCDG = geompy.MakeCDG(theBase) gp_Pnt aCDG = theCDG; if (!isCDG) { gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(theShapeBase); aCDG = aPos.Location(); } TopoDS_Shape aShapeCDG_1 = BRepBuilderAPI_MakeVertex(aCDG).Shape(); // Process case of several given shapes if (theShapeBase.ShapeType() == TopAbs_COMPOUND || theShapeBase.ShapeType() == TopAbs_SHELL) { int nbSub = 0; TopoDS_Shape aShapeI; TopoDS_Compound aCompound; B.MakeCompound(aCompound); TopoDS_Iterator It (theShapeBase, Standard_True, Standard_True); for (; It.More(); It.Next()) { nbSub++; aShapeI = MakeScaledPrism(It.Value(), theVector, theScaleFactor, aCDG, true); B.Add(aCompound, aShapeI); } if (nbSub == 1) aShape = aShapeI; else if (nbSub > 1) aShape = GEOMImpl_GlueDriver::GlueFaces(aCompound, Precision::Confusion(), Standard_True); return aShape; } // 2. Scale = geompy.MakeScaleTransform(theBase, aCDG, theScaleFactor) // Bug 6839: Check for standalone (not included in faces) degenerated edges TopTools_IndexedDataMapOfShapeListOfShape aEFMap; TopExp::MapShapesAndAncestors(theShapeBase, TopAbs_EDGE, TopAbs_FACE, aEFMap); Standard_Integer i, nbE = aEFMap.Extent(); for (i = 1; i <= nbE; i++) { TopoDS_Shape anEdgeSh = aEFMap.FindKey(i); if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeSh))) { const TopTools_ListOfShape& aFaces = aEFMap.FindFromIndex(i); if (aFaces.IsEmpty()) Standard_ConstructionError::Raise ("Scaling aborted : cannot scale standalone degenerated edge"); } } // Perform Scaling gp_Trsf aTrsf; aTrsf.SetScale(aCDG, theScaleFactor); BRepBuilderAPI_Transform aBRepTrsf (theShapeBase, aTrsf, Standard_False); TopoDS_Shape aScale = aBRepTrsf.Shape(); // 3. aBase2 = geompy.MakeTranslationVectorDistance(Scale, theVec, theH) gp_Trsf aTrsf3; aTrsf3.SetTranslation(theVector); TopLoc_Location aLocOrig = aScale.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); TopLoc_Location aLocRes (aTrsf3 * aTrsfOrig); TopoDS_Shape aBase2 = aScale.Located(aLocRes); // 4. aCDG_2 = geompy.MakeTranslationVectorDistance(aCDG, theVec, theH) gp_Pnt aCDG_2 = aCDG.Translated(theVector); TopoDS_Shape aShapeCDG_2 = BRepBuilderAPI_MakeVertex(aCDG_2).Shape(); // 5. Vector = geompy.MakeVector(aCDG, aCDG_2) TopoDS_Shape aShapeVec = BRepBuilderAPI_MakeEdge(aCDG, aCDG_2).Shape(); TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec); TopoDS_Wire aWirePath = BRepBuilderAPI_MakeWire(anEdge); // 6. aPrism = geompy.MakePipeWithDifferentSections([theBase, aBase2], [aCDG, aCDG_2], Vector, False, False) Handle(TopTools_HSequenceOfShape) aBases = new TopTools_HSequenceOfShape; aBases->Append(theShapeBase); aBases->Append(aBase2); Handle(TopTools_HSequenceOfShape) aLocs = new TopTools_HSequenceOfShape; aLocs->Append(aShapeCDG_1); aLocs->Append(aShapeCDG_2); aShape = GEOMImpl_PipeDriver::CreatePipeWithDifferentSections(aWirePath, aBases, aLocs, false, false); // 7. Make a solid, if possible if (theShapeBase.ShapeType() == TopAbs_FACE) { BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0); TopExp_Explorer expF (aShape, TopAbs_FACE); Standard_Integer ifa = 0; for (; expF.More(); expF.Next()) { aSewing.Add(expF.Current()); ifa++; } if (ifa > 0) { aSewing.Perform(); TopoDS_Shape aShell; TopoDS_Shape sh = aSewing.SewedShape(); if (sh.ShapeType() == TopAbs_FACE && ifa == 1) { // case for creation of shell from one face TopoDS_Shell ss; B.MakeShell(ss); B.Add(ss,sh); aShell = ss; } else { TopExp_Explorer exp (sh, TopAbs_SHELL); Standard_Integer ish = 0; for (; exp.More(); exp.Next()) { aShell = exp.Current(); ish++; } if (ish != 1) aShell = sh; } BRepCheck_Shell chkShell (TopoDS::Shell(aShell)); if (chkShell.Closed() == BRepCheck_NoError) { TopoDS_Solid Sol; B.MakeSolid(Sol); B.Add(Sol, aShell); BRepClass3d_SolidClassifier SC (Sol); SC.PerformInfinitePoint(Precision::Confusion()); if (SC.State() == TopAbs_IN) { B.MakeSolid(Sol); B.Add(Sol, aShell.Reversed()); } aShape = Sol; } } } return aShape; }
void BuildMesh(osg::Geode *geode, const TopoDS_Face &face, const osg::Vec4 &color, double deflection) { osg::ref_ptr<deprecated_osg::Geometry> triGeom = new deprecated_osg::Geometry(); osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(); osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array(); TopLoc_Location location; BRepMesh::Mesh(face, deflection); const Handle_Poly_Triangulation &triFace = BRep_Tool::Triangulation(face, location); Standard_Integer nTriangles = triFace->NbTriangles(); gp_Pnt vertex1; gp_Pnt vertex2; gp_Pnt vertex3; Standard_Integer nVertexIndex1 = 0; Standard_Integer nVertexIndex2 = 0; Standard_Integer nVertexIndex3 = 0; const TColgp_Array1OfPnt &nodes = triFace->Nodes(); const Poly_Array1OfTriangle &triangles = triFace->Triangles(); for (Standard_Integer i = 1; i <= nTriangles; i++) { const Poly_Triangle &aTriangle = triangles.Value(i); aTriangle.Get(nVertexIndex1, nVertexIndex2, nVertexIndex3); vertex1 = nodes.Value(nVertexIndex1).Transformed(location.Transformation()); vertex2 = nodes.Value(nVertexIndex2).Transformed(location.Transformation()); vertex3 = nodes.Value(nVertexIndex3).Transformed(location.Transformation()); gp_XYZ vector12(vertex2.XYZ() - vertex1.XYZ()); gp_XYZ vector13(vertex3.XYZ() - vertex1.XYZ()); gp_XYZ normal = vector12.Crossed(vector13); Standard_Real rModulus = normal.Modulus(); if (rModulus > gp::Resolution()) { normal.Normalize(); } else { normal.SetCoord(0., 0., 0.); } if (face.Orientation() != TopAbs_FORWARD) { normal.Reverse(); } vertices->push_back(osg::Vec3(vertex1.X(), vertex1.Y(), vertex1.Z())); vertices->push_back(osg::Vec3(vertex2.X(), vertex2.Y(), vertex2.Z())); vertices->push_back(osg::Vec3(vertex3.X(), vertex3.Y(), vertex3.Z())); normals->push_back(osg::Vec3(normal.X(), normal.Y(), normal.Z())); } triGeom->setVertexArray(vertices); triGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertices->size())); triGeom->setNormalArray(normals); triGeom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_PRIMITIVE); osg::ref_ptr<osg::Vec4Array> colArr = new osg::Vec4Array(); colArr->push_back(color); triGeom->setColorArray(colArr, osg::Array::BIND_OVERALL); geode->addDrawable(triGeom); }
void ViewProviderTransformed::recomputeFeature(void) { PartDesign::Transformed* pcTransformed = static_cast<PartDesign::Transformed*>(getObject()); pcTransformed->getDocument()->recomputeFeature(pcTransformed); const std::vector<App::DocumentObjectExecReturn*> log = pcTransformed->getDocument()->getRecomputeLog(); PartDesign::Transformed::rejectedMap rejected_trsf = pcTransformed->getRejectedTransformations(); unsigned rejected = 0; for (PartDesign::Transformed::rejectedMap::const_iterator r = rejected_trsf.begin(); r != rejected_trsf.end(); r++) rejected += r->second.size(); QString msg = QString::fromLatin1("%1"); if (rejected > 0) { msg = QString::fromLatin1("<font color='orange'>%1<br/></font>\r\n%2"); if (rejected == 1) msg = msg.arg(QObject::tr("One transformed shape does not intersect support")); else { msg = msg.arg(QObject::tr("%1 transformed shapes do not intersect support")); msg = msg.arg(rejected); } } if (log.size() > 0) { msg = msg.arg(QString::fromLatin1("<font color='red'>%1<br/></font>")); msg = msg.arg(QString::fromStdString(log.back()->Why)); } else { msg = msg.arg(QString::fromLatin1("<font color='green'>%1<br/></font>")); msg = msg.arg(QObject::tr("Transformation succeeded")); } signalDiagnosis(msg); // Clear all the rejected stuff while (pcRejectedRoot->getNumChildren() > 7) { SoSeparator* sep = static_cast<SoSeparator*>(pcRejectedRoot->getChild(7)); SoMultipleCopy* rejectedTrfms = static_cast<SoMultipleCopy*>(sep->getChild(2)); rejectedTrfms ->removeAllChildren(); sep->removeChild(1); sep->removeChild(0); pcRejectedRoot ->removeChild(7); } for (PartDesign::Transformed::rejectedMap::const_iterator o = rejected_trsf.begin(); o != rejected_trsf.end(); o++) { if (o->second.empty()) continue; TopoDS_Shape shape; if ((o->first)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) { PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(o->first); shape = feature->AddSubShape.getShape().getShape(); } if (shape.IsNull()) continue; // Display the rejected transformations in red TopoDS_Shape cShape(shape); try { // calculating the deflection value Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; { Bnd_Box bounds; BRepBndLib::Add(cShape, bounds); bounds.SetGap(0.0); bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); } Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure // Note: This DOES have an effect on cShape #if OCC_VERSION_HEX >= 0x060600 Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, AngDeflectionRads,Standard_True); #else BRepMesh_IncrementalMesh(cShape,deflection); #endif // We must reset the location here because the transformation data // are set in the placement property TopLoc_Location aLoc; cShape.Location(aLoc); // count triangles and nodes in the mesh int nbrTriangles=0, nbrNodes=0; TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); // Note: we must also count empty faces if (!mesh.IsNull()) { nbrTriangles += mesh->NbTriangles(); nbrNodes += mesh->NbNodes(); } } // create memory for the nodes and indexes SoCoordinate3* rejectedCoords = new SoCoordinate3(); rejectedCoords ->point .setNum(nbrNodes); SoNormal* rejectedNorms = new SoNormal(); rejectedNorms ->vector .setNum(nbrNodes); SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet(); rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); // get the raw memory for fast fill up SbVec3f* verts = rejectedCoords ->point .startEditing(); SbVec3f* norms = rejectedNorms ->vector .startEditing(); int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); // preset the normal vector with null vector for (int i=0; i < nbrNodes; i++) norms[i]= SbVec3f(0.0,0.0,0.0); int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); if (mesh.IsNull()) continue; // getting the transformation of the shape/face gp_Trsf myTransf; Standard_Boolean identity = true; if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } // getting size of node and triangle array of this face int nbNodesInFace = mesh->NbNodes(); int nbTriInFace = mesh->NbTriangles(); // check orientation TopAbs_Orientation orient = actFace.Orientation(); // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); for (int g=1; g <= nbTriInFace; g++) { // Get the triangle Standard_Integer N1,N2,N3; Triangles(g).Get(N1,N2,N3); // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { Standard_Integer tmp = N1; N1 = N2; N2 = tmp; } // get the 3 points of this triangle gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); // transform the vertices to the place of the face if (!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); } // calculating per vertex normals // Calculate triangle normal gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); gp_Vec Normal = (v2-v1)^(v3-v1); // add the triangle normal to the vertex normal for all points of this triangle norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); // set the vertices verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); // set the index vector with the 3 point indexes and the end delimiter index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; } // counting up the per Face offsets FaceNodeOffset += nbNodesInFace; FaceTriaOffset += nbTriInFace; } // normalize all normals for (int i=0; i < nbrNodes; i++) norms[i].normalize(); // end the editing of the nodes rejectedCoords ->point .finishEditing(); rejectedNorms ->vector .finishEditing(); rejectedFaceSet ->coordIndex .finishEditing(); // fill in the transformation matrices SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); rejectedTrfms->matrix.setNum((o->second).size()); SbMatrix* mats = rejectedTrfms->matrix.startEditing(); std::list<gp_Trsf>::const_iterator trsf = (o->second).begin(); for (unsigned int i=0; i < (o->second).size(); i++,trsf++) { Base::Matrix4D mat; Part::TopoShape::convertToMatrix(*trsf,mat); mats[i] = convert(mat); } rejectedTrfms->matrix.finishEditing(); rejectedTrfms->addChild(rejectedFaceSet); SoSeparator* sep = new SoSeparator(); sep->addChild(rejectedCoords); sep->addChild(rejectedNorms); sep->addChild(rejectedTrfms); pcRejectedRoot->addChild(sep); } catch (...) { Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", pcTransformed->getNameInDocument()); } } }
App::DocumentObjectExecReturn *Draft::execute(void) { // Get parameters // Base shape Part::TopoShape TopShape; try { TopShape = getBaseShape(); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } // Faces where draft should be applied // Note: Cannot be const reference currently because of BRepOffsetAPI_DraftAngle::Remove() bug, see below std::vector<std::string> SubVals = Base.getSubValuesStartsWith("Face"); if (SubVals.size() == 0) return new App::DocumentObjectExecReturn("No faces specified"); // Draft angle double angle = Angle.getValue() / 180.0 * M_PI; // Pull direction gp_Dir pullDirection; App::DocumentObject* refDirection = PullDirection.getValue(); if (refDirection != NULL) { if (refDirection->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { PartDesign::Line* line = static_cast<PartDesign::Line*>(refDirection); Base::Vector3d d = line->getDirection(); pullDirection = gp_Dir(d.x, d.y, d.z); } else if (refDirection->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { std::vector<std::string> subStrings = PullDirection.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No pull direction reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refDirection); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract pull direction reference edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Pull direction reference edge must be linear"); pullDirection = adapt.Line().Direction(); } else { throw Base::Exception("Pull direction reference must be an edge or a datum line"); } } else { throw Base::Exception("Pull direction reference must be an edge of a feature or a datum line"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); pullDirection.Transform(invObjLoc.Transformation()); } // Neutral plane gp_Pln neutralPlane; App::DocumentObject* refPlane = NeutralPlane.getValue(); if (refPlane == NULL) { // Try to guess a neutral plane from the first selected face // Get edges of first selected face TopoDS_Shape face = TopShape.getSubShape(SubVals[0].c_str()); TopTools_IndexedMapOfShape mapOfEdges; TopExp::MapShapes(face, TopAbs_EDGE, mapOfEdges); bool found = false; for (int i = 1; i <= mapOfEdges.Extent(); i++) { // Note: What happens if mapOfEdges(i) is the degenerated edge of a cone? // But in that case the draft is not possible anyway! BRepAdaptor_Curve c(TopoDS::Edge(mapOfEdges(i))); gp_Pnt p1 = c.Value(c.FirstParameter()); gp_Pnt p2 = c.Value(c.LastParameter()); if (c.IsClosed()) { // Edge is a circle or a circular arc (other types are not allowed for drafting) neutralPlane = gp_Pln(p1, c.Circle().Axis().Direction()); found = true; break; } else { // Edge is linear // Find midpoint of edge and create auxiliary plane through midpoint normal to edge gp_Pnt pm = c.Value((c.FirstParameter() + c.LastParameter()) / 2.0); Handle(Geom_Plane) aux = new Geom_Plane(pm, gp_Dir(p2.X() - p1.X(), p2.Y() - p1.Y(), p2.Z() - p1.Z())); // Intersect plane with face. Is there no easier way? BRepAdaptor_Surface adapt(TopoDS::Face(face), Standard_False); Handle(Geom_Surface) sf = adapt.Surface().Surface(); GeomAPI_IntSS intersector(aux, sf, Precision::Confusion()); if (!intersector.IsDone()) continue; Handle(Geom_Curve) icurve = intersector.Line(1); if (!icurve->IsKind(STANDARD_TYPE(Geom_Line))) continue; // TODO: How to extract the line from icurve without creating an edge first? TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(icurve); BRepAdaptor_Curve c(edge); neutralPlane = gp_Pln(pm, c.Line().Direction()); found = true; break; } } if (!found) throw Base::Exception("No neutral plane specified and none can be guessed"); } else { if (refPlane->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) { PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(refPlane); Base::Vector3d b = plane->getBasePoint(); Base::Vector3d n = plane->getNormal(); neutralPlane = gp_Pln(gp_Pnt(b.x, b.y, b.z), gp_Dir(n.x, n.y, n.z)); } else if (refPlane->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { neutralPlane = Feature::makePlnFromPlane(refPlane); } else if (refPlane->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { std::vector<std::string> subStrings = NeutralPlane.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No neutral plane reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refPlane); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_FACE) { TopoDS_Face refFace = TopoDS::Face(ref); if (refFace.IsNull()) throw Base::Exception("Failed to extract neutral plane reference face"); BRepAdaptor_Surface adapt(refFace); if (adapt.GetType() != GeomAbs_Plane) throw Base::Exception("Neutral plane reference face must be planar"); neutralPlane = adapt.Plane(); } else if (ref.ShapeType() == TopAbs_EDGE) { if (refDirection != NULL) { // Create neutral plane through edge normal to pull direction TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract neutral plane reference edge"); BRepAdaptor_Curve c(refEdge); if (c.GetType() != GeomAbs_Line) throw Base::Exception("Neutral plane reference edge must be linear"); double a = c.Line().Angle(gp_Lin(c.Value(c.FirstParameter()), pullDirection)); if (std::fabs(a - M_PI_2) > Precision::Confusion()) throw Base::Exception("Neutral plane reference edge must be normal to pull direction"); neutralPlane = gp_Pln(c.Value(c.FirstParameter()), pullDirection); } else { throw Base::Exception("Neutral plane reference can only be an edge if pull direction is defined"); } } else { throw Base::Exception("Neutral plane reference must be a face"); } } else { throw Base::Exception("Neutral plane reference must be face of a feature or a datum plane"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); neutralPlane.Transform(invObjLoc.Transformation()); } if (refDirection == NULL) { // Choose pull direction normal to neutral plane pullDirection = neutralPlane.Axis().Direction(); } // Reversed pull direction bool reversed = Reversed.getValue(); if (reversed) angle *= -1.0; this->positionByBaseFeature(); // create an untransformed copy of the base shape Part::TopoShape baseShape(TopShape); baseShape.setTransform(Base::Matrix4D()); try { BRepOffsetAPI_DraftAngle mkDraft; // Note: // LocOpe_SplitDrafts can split a face with a wire and apply draft to both parts // Not clear though whether the face must have free boundaries // LocOpe_DPrism can create a stand-alone draft prism. The sketch can only have a single // wire, though. // BRepFeat_MakeDPrism requires a support for the operation but will probably support multiple // wires in the sketch bool success; do { success = true; mkDraft.Init(baseShape.getShape()); for (std::vector<std::string>::iterator it=SubVals.begin(); it != SubVals.end(); ++it) { TopoDS_Face face = TopoDS::Face(baseShape.getSubShape(it->c_str())); // TODO: What is the flag for? mkDraft.Add(face, pullDirection, angle, neutralPlane); if (!mkDraft.AddDone()) { // Note: the function ProblematicShape returns the face on which the error occurred // Note: mkDraft.Remove() stumbles on a bug in Draft_Modification::Remove() and is // therefore unusable. See http://forum.freecadweb.org/viewtopic.php?f=10&t=3209&start=10#p25341 // The only solution is to discard mkDraft and start over without the current face // mkDraft.Remove(face); Base::Console().Error("Adding face failed on %s. Omitted\n", it->c_str()); success = false; SubVals.erase(it); break; } } } while (!success); mkDraft.Build(); if (!mkDraft.IsDone()) return new App::DocumentObjectExecReturn("Failed to create draft"); TopoDS_Shape shape = mkDraft.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is null"); this->Shape.setValue(getSolid(shape)); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle(Standard_Failure) e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }
App::DocumentObjectExecReturn *Pocket::execute(void) { // Handle legacy features, these typically have Type set to 3 (previously NULL, now UpToFace), // empty FaceName (because it didn't exist) and a value for Length if (std::string(Type.getValueAsString()) == "UpToFace" && (UpToFace.getValue() == NULL && Length.getValue() > Precision::Confusion())) Type.setValue("Length"); // Validate parameters double L = Length.getValue(); if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Pocket: Length of pocket too small"); Part::Part2DObject* sketch = 0; std::vector<TopoDS_Wire> wires; TopoDS_Shape support; try { sketch = getVerifiedSketch(); wires = getSketchWires(); support = getSupportShape(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } // get the Sketch plane Base::Placement SketchPos = sketch->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchVector(0,0,1); SketchOrientation.multVec(SketchVector,SketchVector); // turn around for pockets SketchVector *= -1; this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); try { support.Move(invObjLoc); gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Creating a face from sketch failed"); sketchshape.Move(invObjLoc); std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToFace") { TopoDS_Face supportface = getSupportFace(); supportface.Move(invObjLoc); // Find a valid face to extrude up to TopoDS_Face upToFace; if (method == "UpToFace") { getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } getUpToFace(upToFace, support, supportface, sketchshape, method, dir); // Special treatment because often the created stand-alone prism is invalid (empty) because // BRepFeat_MakePrism(..., 2, 1) is buggy BRepFeat_MakePrism PrismMaker; PrismMaker.Init(support, sketchshape, supportface, dir, 0, 1); PrismMaker.Perform(upToFace); if (!PrismMaker.IsDone()) return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not extrude the sketch!"); TopoDS_Shape prism = PrismMaker.Shape(); prism = refineShapeIfActive(prism); // And the really expensive way to get the SubShape... BRepAlgoAPI_Cut mkCut(support, prism); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not get SubShape!"); // FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!! TopoDS_Shape result = refineShapeIfActive(mkCut.Shape()); this->SubShape.setValue(result); this->Shape.setValue(prism); } else { TopoDS_Shape prism; generatePrism(prism, sketchshape, method, dir, L, 0.0, Midplane.getValue(), Reversed.getValue()); if (prism.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is empty"); // set the subtractive shape property for later usage in e.g. pattern prism = refineShapeIfActive(prism); this->SubShape.setValue(prism); // Cut the SubShape out of the support BRepAlgoAPI_Cut mkCut(support, prism); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Pocket: Cut out of support failed"); TopoDS_Shape result = mkCut.Shape(); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape solRes = this->getSolid(result); if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is not a solid"); solRes = refineShapeIfActive(solRes); remapSupportShape(solRes); this->Shape.setValue(solRes); } return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face" && (std::string(Type.getValueAsString()) == "UpToFirst" || std::string(Type.getValueAsString()) == "UpToFace")) return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed " "for making a pocket up to a face."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
const std::list<gp_Trsf> PolarPattern::getTransformations(const std::vector<App::DocumentObject*>) { float angle = Angle.getValue(); if (angle < Precision::Confusion()) throw Base::Exception("Pattern angle too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); double offset; if (std::abs(angle - 360.0) < Precision::Confusion()) offset = Base::toRadians<double>(angle) / occurrences; // Because e.g. two occurrences in 360 degrees need to be 180 degrees apart else offset = Base::toRadians<double>(angle) / (occurrences - 1); App::DocumentObject* refObject = Axis.getValue(); if (refObject == NULL) throw Base::Exception("No axis reference specified"); if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::Exception("Axis reference must be edge of a feature"); std::vector<std::string> subStrings = Axis.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No axis reference specified"); gp_Pnt axbase; gp_Dir axdir; if (refObject->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* refSketch = static_cast<Part::Part2DObject*>(refObject); Base::Axis axis; if (subStrings[0] == "H_Axis") axis = refSketch->getAxis(Part::Part2DObject::H_Axis); else if (subStrings[0] == "V_Axis") axis = refSketch->getAxis(Part::Part2DObject::V_Axis); else if (subStrings[0] == "N_Axis") axis = refSketch->getAxis(Part::Part2DObject::N_Axis); else if (subStrings[0].size() > 4 && subStrings[0].substr(0,4) == "Axis") { int AxId = std::atoi(subStrings[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < refSketch->getAxisCount()) axis = refSketch->getAxis(AxId); } axis *= refSketch->Placement.getValue(); axbase = gp_Pnt(axis.getBase().x, axis.getBase().y, axis.getBase().z); axdir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); } else { Part::Feature* refFeature = static_cast<Part::Feature*>(refObject); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract axis edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Axis edge must be a straight line"); axbase = adapt.Value(adapt.FirstParameter()); axdir = adapt.Line().Direction(); } else { throw Base::Exception("Axis reference must be an edge"); } } TopLoc_Location invObjLoc = this->getLocation().Inverted(); axbase.Transform(invObjLoc.Transformation()); axdir.Transform(invObjLoc.Transformation()); gp_Ax2 axis(axbase, axdir); if (reversed) axis.SetDirection(axis.Direction().Reversed()); // Note: The original feature is NOT included in the list of transformations! Therefore // we start with occurrence number 1, not number 0 std::list<gp_Trsf> transformations; gp_Trsf trans; transformations.push_back(trans); // identity transformation for (int i = 1; i < occurrences; i++) { trans.SetRotation(axis.Axis(), i * offset); transformations.push_back(trans); } return transformations; }
SALOME_WNT_EXPORT int Export( const TopoDS_Shape& theShape, const TCollection_AsciiString& theFileName, const TCollection_AsciiString& theFormatName) { MESSAGE("Export OBJ into file " << theFileName.ToCString()); std::ofstream fout(theFileName.ToCString()); Standard_Real Umin, Umax, Vmin, Vmax, dUmax, dVmax; TopExp_Explorer ExpFace; StdPrs_ToolShadedShape SST; //Triangulate BRepMesh::Mesh(theShape, DEFAULT_DEVIATION); Standard_Integer ShapeId = 1; Standard_Integer baseV = 0; Standard_Integer baseN = 0; Standard_Integer baseT = 0; for(ExpFace.Init(theShape, TopAbs_FACE); ExpFace.More(); ExpFace.Next()) { TopoDS_Face myFace = TopoDS::Face(ExpFace.Current()); TopLoc_Location aLocation; Handle(Poly_Triangulation) myT = BRep_Tool::Triangulation(myFace, aLocation); if (!myT.IsNull()) { Poly_Connect pc(myT); //write vertex buffer const TColgp_Array1OfPnt& Nodes = myT->Nodes(); for (int i = Nodes.Lower(); i <= Nodes.Upper(); i++) { gp_Pnt p = Nodes(i).Transformed(aLocation.Transformation()); fout << "v " << p.X() << " " << p.Y() << " " << p.Z() << std::endl; } fout << std::endl; //write normal buffer TColgp_Array1OfDir myNormal(Nodes.Lower(), Nodes.Upper()); SST.Normal(myFace, pc, myNormal); //myNormal.Length(); for (int i = myNormal.Lower(); i <= myNormal.Upper(); i++) { gp_Dir d = myNormal(i).Transformed(aLocation.Transformation()); fout << "vn " << d.X() << " " << d.Y() << " " << d.Z() << std::endl; } fout << std::endl; //write uvcoord buffer BRepTools::UVBounds(myFace,Umin, Umax, Vmin, Vmax); dUmax = (Umax - Umin); dVmax = (Vmax - Vmin); const TColgp_Array1OfPnt2d& UVNodes = myT->UVNodes(); for (int i = UVNodes.Lower(); i <= UVNodes.Upper(); i++) { gp_Pnt2d d = UVNodes(i); Standard_Real u = (-UOrigin+(URepeat*(d.X()-Umin))/dUmax)/ScaleU; Standard_Real v = (-VOrigin+(VRepeat*(d.Y()-Vmin))/dVmax)/ScaleV; fout << "vt " << u << " " << v << " 0" << std::endl; } fout << std::endl; //write triangle buffer if (Interface_Static::IVal("write.obj.groups")) fout << "g face_" << ShapeId++ << std::endl; Standard_Integer n1 , n2 , n3; const Poly_Array1OfTriangle& triangles = myT->Triangles(); for (int nt = 1; nt <= myT->NbTriangles(); nt++) { if (SST.Orientation(myFace) == TopAbs_REVERSED) triangles(nt).Get(n1,n3,n2); else triangles(nt).Get(n1,n2,n3); if (TriangleIsValid (Nodes(n1),Nodes(n2),Nodes(n3)) ) { fout << "f " <<n1 + baseV<<"/"<<n1 + baseT<<"/"<<n1 + baseN<<" " <<n2 + baseV<<"/"<<n2 + baseT<<"/"<<n2 + baseN<<" " <<n3 + baseV<<"/"<<n3 + baseT<<"/"<<n3 + baseN<<" " <<std::endl; } } fout << std::endl; baseV += Nodes.Length(); baseN += myNormal.Length(); baseT += UVNodes.Length(); } } fout << std::flush; fout.close(); return 1; }
void BuildShapeMesh(osg::Geode *geode, const TopoDS_Shape &shape, const osg::Vec4 &color, double deflection) { bool bSetNormal = true; osg::ref_ptr<deprecated_osg::Geometry> triGeom = new deprecated_osg::Geometry(); osg::ref_ptr<osg::Vec3Array> theVertices = new osg::Vec3Array(); osg::ref_ptr<osg::Vec3Array> theNormals = new osg::Vec3Array(); BRepMesh::Mesh(shape, deflection); TopExp_Explorer faceExplorer; for (faceExplorer.Init(shape, TopAbs_FACE); faceExplorer.More(); faceExplorer.Next()) { TopLoc_Location theLocation; TopoDS_Face theFace = TopoDS::Face(faceExplorer.Current()); if (theFace.IsNull()) continue; const Handle_Poly_Triangulation &theTriangulation = BRep_Tool::Triangulation(theFace, theLocation); BRepLProp_SLProps theProp(BRepAdaptor_Surface(theFace), 1, Precision::Confusion()); Standard_Integer nTriangles = theTriangulation->NbTriangles(); for (Standard_Integer i = 1; i <= nTriangles; i++) { const Poly_Triangle& theTriangle = theTriangulation->Triangles().Value(i); gp_Pnt theVertex1 = theTriangulation->Nodes().Value(theTriangle(1)); gp_Pnt theVertex2 = theTriangulation->Nodes().Value(theTriangle(2)); gp_Pnt theVertex3 = theTriangulation->Nodes().Value(theTriangle(3)); const gp_Pnt2d &theUV1 = theTriangulation->UVNodes().Value(theTriangle(1)); const gp_Pnt2d &theUV2 = theTriangulation->UVNodes().Value(theTriangle(2)); const gp_Pnt2d &theUV3 = theTriangulation->UVNodes().Value(theTriangle(3)); theVertex1.Transform(theLocation.Transformation()); theVertex2.Transform(theLocation.Transformation()); theVertex3.Transform(theLocation.Transformation()); // find the normal for the triangle mesh. gp_Vec V12(theVertex1, theVertex2); gp_Vec V13(theVertex1, theVertex3); gp_Vec theNormal = V12 ^ V13; gp_Vec theNormal1 = theNormal; gp_Vec theNormal2 = theNormal; gp_Vec theNormal3 = theNormal; if (theNormal.Magnitude() > Precision::Confusion()) { theNormal.Normalize(); theNormal1.Normalize(); theNormal2.Normalize(); theNormal3.Normalize(); } theProp.SetParameters(theUV1.X(), theUV1.Y()); if (theProp.IsNormalDefined()) { theNormal1 = theProp.Normal(); } theProp.SetParameters(theUV2.X(), theUV2.Y()); if (theProp.IsNormalDefined()) { theNormal2 = theProp.Normal(); } theProp.SetParameters(theUV3.X(), theUV3.Y()); if (theProp.IsNormalDefined()) { theNormal3 = theProp.Normal(); } if (theFace.Orientation() == TopAbs_REVERSED) { theNormal.Reverse(); theNormal1.Reverse(); theNormal2.Reverse(); theNormal3.Reverse(); } theVertices->push_back(osg::Vec3(theVertex1.X(), theVertex1.Y(), theVertex1.Z())); theVertices->push_back(osg::Vec3(theVertex2.X(), theVertex2.Y(), theVertex2.Z())); theVertices->push_back(osg::Vec3(theVertex3.X(), theVertex3.Y(), theVertex3.Z())); if (bSetNormal) { theNormals->push_back(osg::Vec3(theNormal1.X(), theNormal1.Y(), theNormal1.Z())); theNormals->push_back(osg::Vec3(theNormal2.X(), theNormal2.Y(), theNormal2.Z())); theNormals->push_back(osg::Vec3(theNormal3.X(), theNormal3.Y(), theNormal3.Z())); } else { theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z())); theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z())); theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z())); } } } triGeom->setVertexArray(theVertices.get()); triGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, theVertices->size())); triGeom->setNormalArray(theNormals); triGeom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_VERTEX); osg::ref_ptr<osg::Vec4Array> colArr = new osg::Vec4Array(); colArr->push_back(color); triGeom->setColorArray(colArr, osg::Array::BIND_OVERALL); geode->addDrawable(triGeom); }
const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>) { std::string stdDirection = StdDirection.getValue(); float distance = Length.getValue(); if (distance < Precision::Confusion()) throw Base::Exception("Pattern length too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); gp_Dir dir; double offset = distance / (occurrences - 1); if (!stdDirection.empty()) { // Note: The placement code commented out below had the defect of working always on the // absolute X,Y,Z direction, not on the relative coordinate system of the Body feature. // It requires positionBySupport() to be called in Transformed::Execute() AFTER // the call to getTransformations() // New code thanks to logari81 if (stdDirection == "X") { //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0)); dir = gp_Dir(1,0,0); } else if (stdDirection == "Y") { //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,1,0)); dir = gp_Dir(0,1,0); } else if(stdDirection == "Z") { //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,0,1)); dir = gp_Dir(0,0,1); } else { throw Base::Exception("Invalid direction (must be X, Y or Z)"); } } else { App::DocumentObject* refObject = Direction.getValue(); if (refObject == NULL) throw Base::Exception("No direction specified"); if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::Exception("Direction reference must be edge or face of a feature"); std::vector<std::string> subStrings = Direction.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No direction reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refObject); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_FACE) { TopoDS_Face refFace = TopoDS::Face(ref); if (refFace.IsNull()) throw Base::Exception("Failed to extract direction plane"); BRepAdaptor_Surface adapt(refFace); if (adapt.GetType() != GeomAbs_Plane) throw Base::Exception("Direction face must be planar"); dir = adapt.Plane().Axis().Direction(); //gp_Dir d = adapt.Plane().Axis().Direction(); //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z())); } else if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract direction edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Direction edge must be a straight line"); //gp_Dir d = adapt.Line().Direction(); //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z())); dir = adapt.Line().Direction(); } else { throw Base::Exception("Direction reference must be edge or face"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); dir.Transform(invObjLoc.Transformation()); } // get the support placement // TODO: Check for NULL pointer /*Part::Feature* supportFeature = static_cast<Part::Feature*>(originals.front()); if (supportFeature == NULL) throw Base::Exception("Cannot work on invalid support shape"); Base::Placement supportPlacement = supportFeature->Placement.getValue(); dir *= supportPlacement; gp_Vec direction(dir.getDirection().x, dir.getDirection().y, dir.getDirection().z);*/ gp_Vec direction(dir.X(), dir.Y(), dir.Z()); if (reversed) direction.Reverse(); // Note: The original feature is NOT included in the list of transformations! Therefore // we start with occurrence number 1, not number 0 std::list<gp_Trsf> transformations; gp_Trsf trans; transformations.push_back(trans); // identity transformation for (int i = 1; i < occurrences; i++) { trans.SetTranslation(direction * i * offset); transformations.push_back(trans); } return transformations; }
void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape) { // Clear selection Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::None); action.apply(this->faceset); action.apply(this->lineset); action.apply(this->nodeset); TopoDS_Shape cShape(inputShape); if (cShape.IsNull()) { coords ->point .setNum(0); norm ->vector .setNum(0); faceset ->coordIndex .setNum(0); faceset ->partIndex .setNum(0); lineset ->coordIndex .setNum(0); VisualTouched = false; return; } // time measurement and book keeping Base::TimeInfo start_time; int nbrTriangles=0,nbrNodes=0,nbrNorms=0,nbrFaces=0,nbrEdges=0,nbrLines=0; std::set<int> faceEdges; try { // calculating the deflection value Bnd_Box bounds; BRepBndLib::Add(cShape, bounds); bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure BRepMesh_IncrementalMesh myMesh(cShape,deflection); // We must reset the location here because the transformation data // are set in the placement property TopLoc_Location aLoc; cShape.Location(aLoc); // count triangles and nodes in the mesh TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); // Note: we must also count empty faces if (!mesh.IsNull()) { nbrTriangles += mesh->NbTriangles(); nbrNodes += mesh->NbNodes(); nbrNorms += mesh->NbNodes(); } TopExp_Explorer xp; for (xp.Init(Ex.Current(),TopAbs_EDGE);xp.More();xp.Next()) faceEdges.insert(xp.Current().HashCode(INT_MAX)); nbrFaces++; } // get an indexed map of edges TopTools_IndexedMapOfShape M; TopExp::MapShapes(cShape, TopAbs_EDGE, M); std::set<int> edgeIdxSet; std::vector<int32_t> indxVector; std::vector<int32_t> edgeVector; // count and index the edges for (int i=1; i <= M.Extent(); i++) { edgeIdxSet.insert(i); nbrEdges++; const TopoDS_Edge& aEdge = TopoDS::Edge(M(i)); TopLoc_Location aLoc; // handling of the free edge that are not associated to a face // Note: The assumption that if for an edge BRep_Tool::Polygon3D // returns a valid object is wrong. This e.g. happens for ruled // surfaces which gets created by two edges or wires. // So, we have to store the hashes of the edges associated to a face. // If the hash of a given edge is not in this list we know it's really // a free edge. int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); if (!aPoly.IsNull()) { int nbNodesInEdge = aPoly->NbNodes(); nbrNodes += nbNodesInEdge; } } } // reserve some memory indxVector.reserve(nbrEdges*8); // handling of the vertices TopTools_IndexedMapOfShape V; TopExp::MapShapes(cShape, TopAbs_VERTEX, V); nbrNodes += V.Extent(); // create memory for the nodes and indexes coords ->point .setNum(nbrNodes); norm ->vector .setNum(nbrNorms); faceset ->coordIndex .setNum(nbrTriangles*4); faceset ->partIndex .setNum(nbrFaces); // get the raw memory for fast fill up SbVec3f* verts = coords ->point .startEditing(); SbVec3f* norms = norm ->vector .startEditing(); int32_t* index = faceset ->coordIndex .startEditing(); int32_t* parts = faceset ->partIndex .startEditing(); // preset the normal vector with null vector for (int i=0;i < nbrNorms;i++) norms[i]= SbVec3f(0.0,0.0,0.0); int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); if (mesh.IsNull()) continue; // getting the transformation of the shape/face gp_Trsf myTransf; Standard_Boolean identity = true; if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } // getting size of node and triangle array of this face int nbNodesInFace = mesh->NbNodes(); int nbTriInFace = mesh->NbTriangles(); // check orientation TopAbs_Orientation orient = actFace.Orientation(); // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle Standard_Integer N1,N2,N3; Triangles(g).Get(N1,N2,N3); // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { Standard_Integer tmp = N1; N1 = N2; N2 = tmp; } // get the 3 points of this triangle gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); // transform the vertices to the place of the face if (!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); } // calculating per vertex normals // Calculate triangle normal gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); gp_Vec Normal = (v2-v1)^(v3-v1); // add the triangle normal to the vertex normal for all points of this triangle norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); // set the vertices verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); // set the index vector with the 3 point indexes and the end delimiter index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; } parts[ii] = nbTriInFace; // new part // handling the edges lying on this face TopExp_Explorer Exp; for(Exp.Init(actFace,TopAbs_EDGE);Exp.More();Exp.Next()) { const TopoDS_Edge &actEdge = TopoDS::Edge(Exp.Current()); // get the overall index of this edge int idx = M.FindIndex(actEdge); edgeVector.push_back((int32_t)idx-1); // already processed this index ? if (edgeIdxSet.find(idx)!=edgeIdxSet.end()) { // this holds the indices of the edge's triangulation to the current polygon Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(actEdge, mesh, aLoc); if (aPoly.IsNull()) continue; // polygon does not exist // getting the indexes of the edge polygon const TColStd_Array1OfInteger& indices = aPoly->Nodes(); for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { int inx = indices(i); indxVector.push_back(FaceNodeOffset+inx-1); // usually the coordinates for this edge are already set by the // triangles of the face this edge belongs to. However, there are // rare cases where some points are only referenced by the polygon // but not by any triangle. Thus, we must apply the coordinates to // make sure that everything is properly set. gp_Pnt p(Nodes(inx)); if (!identity) p.Transform(myTransf); verts[FaceNodeOffset+inx-1].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z())); } indxVector.push_back(-1); // remove the handled edge index from the set edgeIdxSet.erase(idx); } } edgeVector.push_back(-1); // counting up the per Face offsets FaceNodeOffset += nbNodesInFace; FaceTriaOffset += nbTriInFace; } // handling of the free edges for (int i=1; i <= M.Extent(); i++) { const TopoDS_Edge& aEdge = TopoDS::Edge(M(i)); Standard_Boolean identity = true; gp_Trsf myTransf; TopLoc_Location aLoc; // handling of the free edge that are not associated to a face int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); if (!aPoly.IsNull()) { if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } const TColgp_Array1OfPnt& aNodes = aPoly->Nodes(); int nbNodesInEdge = aPoly->NbNodes(); gp_Pnt pnt; for (Standard_Integer j=1;j <= nbNodesInEdge;j++) { pnt = aNodes(j); if (!identity) pnt.Transform(myTransf); verts[FaceNodeOffset+j-1].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z())); indxVector.push_back(FaceNodeOffset+j-1); } indxVector.push_back(-1); FaceNodeOffset += nbNodesInEdge; } } } nodeset->startIndex.setValue(FaceNodeOffset); for (int i=0; i<V.Extent(); i++) { const TopoDS_Vertex& aVertex = TopoDS::Vertex(V(i+1)); gp_Pnt pnt = BRep_Tool::Pnt(aVertex); verts[FaceNodeOffset+i].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z())); } // normalize all normals for (int i = 0; i< nbrNorms ;i++) norms[i].normalize(); // preset the index vector size nbrLines = indxVector.size(); lineset ->coordIndex .setNum(nbrLines); int32_t* lines = lineset ->coordIndex .startEditing(); int l=0; for (std::vector<int32_t>::const_iterator it=indxVector.begin();it!=indxVector.end();++it,l++) lines[l] = *it; // end the editing of the nodes coords ->point .finishEditing(); norm ->vector .finishEditing(); faceset ->coordIndex .finishEditing(); faceset ->partIndex .finishEditing(); lineset ->coordIndex .finishEditing(); } catch (...) { Base::Console().Error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument()); } // printing some informations Base::Console().Log("ViewProvider update time: %f s\n",Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo())); Base::Console().Log("Shape tria info: Faces:%d Edges:%d Nodes:%d Triangles:%d IdxVec:%d\n",nbrFaces,nbrEdges,nbrNodes,nbrTriangles,nbrLines); VisualTouched = false; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_RotateDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); if (aFunction.IsNull()) return 0; GEOMImpl_IRotate RI(aFunction); gp_Trsf aTrsf; gp_Pnt aCP, aP1, aP2; Standard_Integer aType = aFunction->GetType(); Handle(GEOM_Function) anOriginalFunction = RI.GetOriginal(); if (anOriginalFunction.IsNull()) return 0; TopoDS_Shape aShape, anOriginal = anOriginalFunction->GetValue(); if (anOriginal.IsNull()) return 0; if (aType == ROTATE || aType == ROTATE_COPY) { Handle(GEOM_Function) anAxis = RI.GetAxis(); if (anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if (A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir aDir(gp_Vec(aP1, aP2)); gp_Ax1 anAx1(aP1, aDir); Standard_Real anAngle = RI.GetAngle(); if (fabs(anAngle) < Precision::Angular()) anAngle += 2*PI; // NPAL19665,19769 aTrsf.SetRotation(anAx1, anAngle); //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False); //aShape = aTransformation.Shape(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug aTrsfOrig.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfOrig); aShape = anOriginal.Located(aLocRes); } else if (aType == ROTATE_THREE_POINTS || aType == ROTATE_THREE_POINTS_COPY) { Handle(GEOM_Function) aCentPoint = RI.GetCentPoint(); Handle(GEOM_Function) aPoint1 = RI.GetPoint1(); Handle(GEOM_Function) aPoint2 = RI.GetPoint2(); if(aCentPoint.IsNull() || aPoint1.IsNull() || aPoint2.IsNull()) return 0; TopoDS_Shape aCV = aCentPoint->GetValue(); TopoDS_Shape aV1 = aPoint1->GetValue(); TopoDS_Shape aV2 = aPoint2->GetValue(); if(aCV.IsNull() || aCV.ShapeType() != TopAbs_VERTEX) return 0; if(aV1.IsNull() || aV1.ShapeType() != TopAbs_VERTEX) return 0; if(aV2.IsNull() || aV2.ShapeType() != TopAbs_VERTEX) return 0; aCP = BRep_Tool::Pnt(TopoDS::Vertex(aCV)); aP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1)); aP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2)); gp_Vec aVec1 (aCP, aP1); gp_Vec aVec2 (aCP, aP2); gp_Dir aDir (aVec1 ^ aVec2); gp_Ax1 anAx1 (aCP, aDir); Standard_Real anAngle = aVec1.Angle(aVec2); if (fabs(anAngle) < Precision::Angular()) anAngle += 2*PI; // NPAL19665 aTrsf.SetRotation(anAx1, anAngle); //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False); //aShape = aTransformation.Shape(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug aTrsfOrig.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfOrig); aShape = anOriginal.Located(aLocRes); } else if (aType == ROTATE_1D) { //Get direction Handle(GEOM_Function) anAxis = RI.GetAxis(); if(anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if(A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir D(gp_Vec(aP1, aP2)); gp_Ax1 AX1(aP1, D); Standard_Integer nbtimes = RI.GetNbIter1(); Standard_Real angle = 360.0/nbtimes; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound( aCompound ); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); for (int i = 0; i < nbtimes; i++ ) { if (i == 0) { // NPAL19665 B.Add(aCompound, anOriginal); } else { aTrsf.SetRotation(AX1, i*angle/* * PI180 */); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug gp_Trsf aTrsfNew (aTrsfOrig); aTrsfNew.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfNew); B.Add(aCompound, anOriginal.Located(aLocRes)); } //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aBRepTransformation(anOriginal, aTrsf, Standard_False); //B.Add(aCompound, aBRepTransformation.Shape()); } aShape = aCompound; } else if (aType == ROTATE_2D) { //Get direction Handle(GEOM_Function) anAxis = RI.GetAxis(); if(anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if(A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir D(gp_Vec(aP1, aP2)); gp_Ax1 AX1(aP1, D); gp_Trsf aTrsf1; gp_Trsf aTrsf2; gp_Trsf aTrsf3; gp_XYZ aDir2 = RI.GetDir2(); // can be set by previous execution if (aDir2.Modulus() < gp::Resolution()) { // Calculate direction as vector from the axis to the shape's center gp_Pnt P1; GProp_GProps System; if (anOriginal.ShapeType() == TopAbs_VERTEX) { P1 = BRep_Tool::Pnt(TopoDS::Vertex( anOriginal )); } else if ( anOriginal.ShapeType() == TopAbs_EDGE || anOriginal.ShapeType() == TopAbs_WIRE ) { BRepGProp::LinearProperties(anOriginal, System); P1 = System.CentreOfMass(); } else if ( anOriginal.ShapeType() == TopAbs_FACE || anOriginal.ShapeType() == TopAbs_SHELL ) { BRepGProp::SurfaceProperties(anOriginal, System); P1 = System.CentreOfMass(); } else { BRepGProp::VolumeProperties(anOriginal, System); P1 = System.CentreOfMass(); } Handle(Geom_Line) Line = new Geom_Line(AX1); GeomAPI_ProjectPointOnCurve aPrjTool( P1, Line ); gp_Pnt P2 = aPrjTool.NearestPoint(); if ( P1.IsEqual(P2, Precision::Confusion() ) ) return 0; aDir2 = gp_XYZ(P1.X()-P2.X(), P1.Y()-P2.Y(), P1.Z()-P2.Z()); // Attention: this abnormal action is done for good working of // TransformLikeOther(), used by RestoreSubShapes functionality RI.SetDir2(aDir2); } gp_Vec Vec (aDir2); Vec.Normalize(); gp_Vec elevVec(D); elevVec.Normalize(); Standard_Integer nbtimes2 = RI.GetNbIter2(); Standard_Integer nbtimes1 = RI.GetNbIter1(); Standard_Real step = RI.GetStep(); Standard_Real elevationstep = RI.GetElevationStep(); Standard_Real ang = RI.GetAngle(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); gp_Vec aVec; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound( aCompound ); Standard_Real DX, DY, DZ; for (int i = 0; i < nbtimes2; i++ ) { if (i != 0) { DX = i * step * Vec.X(); DY = i * step * Vec.Y(); DZ = i * step * Vec.Z(); aVec.SetCoord( DX, DY, DZ ); aTrsf1.SetTranslation(aVec); } for (int j = 0; j < nbtimes1; j++ ) { if (j == 0) { // NPAL19665 TopLoc_Location aLocRes (aTrsf1 * aTrsfOrig); B.Add(aCompound, anOriginal.Located(aLocRes)); } else { DX = j * elevationstep * elevVec.X(); DY = j * elevationstep * elevVec.Y(); DZ = j * elevationstep * elevVec.Z(); aVec.SetCoord( DX, DY, DZ ); aTrsf3.SetTranslation(aVec); aTrsf2.SetRotation(AX1, j*ang /* * PI180 */ ); //TopLoc_Location aLocRes (aTrsf2 * aTrsf1 * aTrsfOrig); // gp_Trsf::Multiply() has a bug gp_Trsf aTrsfNew (aTrsfOrig); aTrsfNew.PreMultiply(aTrsf1); aTrsfNew.PreMultiply(aTrsf2); aTrsfNew.PreMultiply(aTrsf3); TopLoc_Location aLocRes (aTrsfNew); B.Add(aCompound, anOriginal.Located(aLocRes)); } //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aBRepTrsf1 (anOriginal, aTrsf1, Standard_False); //BRepBuilderAPI_Transform aBRepTrsf2 (aBRepTrsf1.Shape(), aTrsf2, Standard_False); //B.Add(aCompound, aBRepTrsf2.Shape()); } } aShape = aCompound; } else return 0; if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
void PovTools::transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace ) { TopLoc_Location aLoc; // doing the meshing and checking the result //BRepMesh_IncrementalMesh MESH(aFace,fDeflection); Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); if (aPoly.IsNull()) { Base::Console().Log("Empty face trianglutaion\n"); nbNodesInFace =0; nbTriInFace = 0; vertices = 0l; cons = 0l; return; } // getting the transformation of the shape/face gp_Trsf myTransf; Standard_Boolean identity = true; if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } Standard_Integer i; // getting size and create the array nbNodesInFace = aPoly->NbNodes(); nbTriInFace = aPoly->NbTriangles(); *vertices = new gp_Vec[nbNodesInFace]; *vertexnormals = new gp_Vec[nbNodesInFace]; for (i=0; i < nbNodesInFace; i++) { (*vertexnormals)[i]= gp_Vec(0.0,0.0,0.0); } *cons = new long[3*(nbTriInFace)+1]; // check orientation TopAbs_Orientation orient = aFace.Orientation(); // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = aPoly->Triangles(); const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); for (i=1; i<=nbTriInFace; i++) { // Get the triangle Standard_Integer N1,N2,N3; Triangles(i).Get(N1,N2,N3); // change orientation of the triangles if ( orient != TopAbs_FORWARD ) { Standard_Integer tmp = N1; N1 = N2; N2 = tmp; } gp_Pnt V1 = Nodes(N1); gp_Pnt V2 = Nodes(N2); gp_Pnt V3 = Nodes(N3); // transform the vertices to the place of the face if (!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); } // Calculate triangle normal gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); gp_Vec Normal = (v2-v1)^(v3-v1); //Standard_Real Area = 0.5 * Normal.Magnitude(); // add the triangle normal to the vertex normal for all points of this triangle (*vertexnormals)[N1-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); (*vertexnormals)[N2-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); (*vertexnormals)[N3-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); (*vertices)[N1-1].SetX((float)(V1.X())); (*vertices)[N1-1].SetY((float)(V1.Y())); (*vertices)[N1-1].SetZ((float)(V1.Z())); (*vertices)[N2-1].SetX((float)(V2.X())); (*vertices)[N2-1].SetY((float)(V2.Y())); (*vertices)[N2-1].SetZ((float)(V2.Z())); (*vertices)[N3-1].SetX((float)(V3.X())); (*vertices)[N3-1].SetY((float)(V3.Y())); (*vertices)[N3-1].SetZ((float)(V3.Z())); int j = i - 1; N1--; N2--; N3--; (*cons)[3*j] = N1; (*cons)[3*j+1] = N2; (*cons)[3*j+2] = N3; } // normalize all vertex normals for (i=0; i < nbNodesInFace; i++) { gp_Dir clNormal; try { Handle(Geom_Surface) Surface = BRep_Tool::Surface(aFace); gp_Pnt vertex((*vertices)[i].XYZ()); // gp_Pnt vertex((*vertices)[i][0], (*vertices)[i][1], (*vertices)[i][2]); GeomAPI_ProjectPointOnSurf ProPntSrf(vertex, Surface); Standard_Real fU, fV; ProPntSrf.Parameters(1, fU, fV); GeomLProp_SLProps clPropOfFace(Surface, fU, fV, 2, gp::Resolution()); clNormal = clPropOfFace.Normal(); gp_Vec temp = clNormal; //Base::Console().Log("unterschied:%.2f",temp.dot((*vertexnormals)[i])); if ( temp * (*vertexnormals)[i] < 0 ) temp = -temp; (*vertexnormals)[i] = temp; } catch (...) { } (*vertexnormals)[i].Normalize(); } }