#include "SketchFeature.h" #include "SketchObject.h" #include "SketchLine.h" #include "SketchRectangle.h" #include "SketchCircle.h" #include #include #include #include #include #include #include #include #include #include SketchFeature::SketchFeature(const QString& name) : Feature(name) { } SketchFeature::~SketchFeature() { qDeleteAll(m_objects); } QString SketchFeature::type() const { return "Sketch"; } void SketchFeature::setPlane(SketchPlane plane) { m_plane = plane; } SketchFeature::SketchPlane SketchFeature::plane() const { return m_plane; } const TopoDS_Shape& SketchFeature::shape() const { return m_shape; } void SketchFeature::buildShape() { m_shape.Nullify(); QList lineEdges; QList faces; for (SketchObject* obj : m_objects) { if (auto line = dynamic_cast(obj)) { lineEdges.append(BRepBuilderAPI_MakeEdge(line->startPoint(), line->endPoint()).Edge()); } else if (auto rect = dynamic_cast(obj)) { const gp_Pnt& c1 = rect->corner1(); const gp_Pnt& c2 = rect->corner2(); gp_Pnt other_corner1, other_corner2; if (m_plane == SketchPlane::XY) { other_corner1.SetCoord(c1.X(), c2.Y(), c1.Z()); other_corner2.SetCoord(c2.X(), c1.Y(), c1.Z()); } else if (m_plane == SketchPlane::XZ) { other_corner1.SetCoord(c1.X(), c1.Y(), c2.Z()); other_corner2.SetCoord(c2.X(), c1.Y(), c1.Z()); } else { // YZ other_corner1.SetCoord(c1.X(), c1.Y(), c2.Z()); other_corner2.SetCoord(c1.X(), c2.Y(), c1.Z()); } TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(c1, other_corner1).Edge(); TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(other_corner1, c2).Edge(); TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(c2, other_corner2).Edge(); TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(other_corner2, c1).Edge(); BRepBuilderAPI_MakeWire wireBuilder(e1, e2, e3, e4); if (wireBuilder.IsDone()) { BRepBuilderAPI_MakeFace faceBuilder(wireBuilder.Wire()); if (faceBuilder.IsDone()) { faces.append(faceBuilder.Face()); } } } else if (auto circle = dynamic_cast(obj)) { const gp_Pnt& center = circle->center(); double radius = circle->radius(); gp_Dir normal; switch (m_plane) { case SketchPlane::XY: normal = gp::DZ(); break; case SketchPlane::XZ: normal = gp::DY(); break; case SketchPlane::YZ: normal = gp::DX(); break; } gp_Ax2 axis(center, normal); gp_Circ circ(axis, radius); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(circ).Edge(); BRepBuilderAPI_MakeWire wireBuilder(edge); if(wireBuilder.IsDone()) { BRepBuilderAPI_MakeFace faceBuilder(wireBuilder.Wire()); if (faceBuilder.IsDone()) { faces.append(faceBuilder.Face()); } } } } if (!lineEdges.isEmpty()) { BRepBuilderAPI_MakeWire wireBuilder; for (const auto& edge : lineEdges) { wireBuilder.Add(edge); } if (wireBuilder.IsDone()) { TopoDS_Shape wiresShape = wireBuilder.Shape(); TopExp_Explorer explorer(wiresShape, TopAbs_WIRE); for (; explorer.More(); explorer.Next()) { TopoDS_Wire wire = TopoDS::Wire(explorer.Current()); if (wire.Closed()) { BRepBuilderAPI_MakeFace faceBuilder(wire); if (faceBuilder.IsDone()) { faces.append(faceBuilder.Face()); } } } } } if (faces.isEmpty()) { return; } if (faces.size() == 1) { m_shape = faces.first(); } else { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); for (const auto& face : faces) { builder.Add(compound, face); } m_shape = compound; } } void SketchFeature::addObject(SketchObject* object) { m_objects.append(object); } const QList& SketchFeature::objects() const { return m_objects; } void SketchFeature::read(const QJsonObject& json) { Feature::read(json); if (json.contains("plane") && json["plane"].isString()) { QString planeStr = json["plane"].toString(); if (planeStr == "XY") m_plane = SketchPlane::XY; else if (planeStr == "XZ") m_plane = SketchPlane::XZ; else if (planeStr == "YZ") m_plane = SketchPlane::YZ; } if (json.contains("objects") && json["objects"].isArray()) { QJsonArray objectsArray = json["objects"].toArray(); qDeleteAll(m_objects); m_objects.clear(); for (const QJsonValue& value : objectsArray) { QJsonObject objectJson = value.toObject(); if (objectJson.contains("type") && objectJson["type"].isString()) { QString type = objectJson["type"].toString(); if (type == "Line") { auto line = new SketchLine(); line->read(objectJson); m_objects.append(line); } else if (type == "Rectangle") { auto rect = new SketchRectangle(); rect->read(objectJson); m_objects.append(rect); } } } } } void SketchFeature::write(QJsonObject& json) const { Feature::write(json); QString planeStr; switch (m_plane) { case SketchPlane::XY: planeStr = "XY"; break; case SketchPlane::XZ: planeStr = "XZ"; break; case SketchPlane::YZ: planeStr = "YZ"; break; } json["plane"] = planeStr; QJsonArray objectsArray; for (const auto& object : m_objects) { QJsonObject objectJson; object->write(objectJson); objectsArray.append(objectJson); } json["objects"] = objectsArray; }