Compare commits
4 Commits
master
...
6e729183ef
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e729183ef | |||
| d5d430e80d | |||
| 95b4db5191 | |||
| e2dfdf1600 |
@@ -158,6 +158,9 @@ void ApplicationController::addCircle(const gp_Pnt& center, double radius)
|
||||
|
||||
void ApplicationController::endSketch()
|
||||
{
|
||||
if (m_activeSketch) {
|
||||
m_activeSketch->buildShape();
|
||||
}
|
||||
m_activeSketch = nullptr;
|
||||
setActiveTool(ToolType::None);
|
||||
emit sketchModeEnded();
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
#include "SketchObject.h"
|
||||
#include "SketchLine.h"
|
||||
#include "SketchRectangle.h"
|
||||
#include "SketchCircle.h"
|
||||
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
|
||||
#include <QJsonArray>
|
||||
|
||||
@@ -35,6 +46,101 @@ const TopoDS_Shape& SketchFeature::shape() const
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
void SketchFeature::buildShape()
|
||||
{
|
||||
m_shape.Nullify();
|
||||
QList<TopoDS_Edge> lineEdges;
|
||||
QList<TopoDS_Face> faces;
|
||||
|
||||
for (SketchObject* obj : m_objects) {
|
||||
if (auto line = dynamic_cast<SketchLine*>(obj)) {
|
||||
lineEdges.append(BRepBuilderAPI_MakeEdge(line->startPoint(), line->endPoint()).Edge());
|
||||
} else if (auto rect = dynamic_cast<SketchRectangle*>(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<SketchCircle*>(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);
|
||||
|
||||
@@ -26,6 +26,8 @@ public:
|
||||
|
||||
const TopoDS_Shape& shape() const;
|
||||
|
||||
void buildShape();
|
||||
|
||||
void addObject(SketchObject* object);
|
||||
const QList<SketchObject*>& objects() const;
|
||||
|
||||
|
||||
@@ -30,6 +30,13 @@
|
||||
#include <QVector>
|
||||
#include <map>
|
||||
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
|
||||
struct PntComparator {
|
||||
bool operator()(const gp_Pnt& a, const gp_Pnt& b) const {
|
||||
// A tolerance is needed for floating point comparisons
|
||||
@@ -649,6 +656,41 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw faces
|
||||
if (!sketch->shape().IsNull()) {
|
||||
BRepMesh_IncrementalMesh(sketch->shape(), 0.1); // Linear deflection
|
||||
|
||||
QVector<GLfloat> faceVertices;
|
||||
TopExp_Explorer explorer(sketch->shape(), TopAbs_FACE);
|
||||
for (; explorer.More(); explorer.Next()) {
|
||||
TopoDS_Face face = TopoDS::Face(explorer.Current());
|
||||
TopLoc_Location location;
|
||||
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, location);
|
||||
|
||||
if (!triangulation.IsNull()) {
|
||||
for (int i = 1; i <= triangulation->NbTriangles(); ++i) {
|
||||
const Poly_Triangle& triangle = triangulation->Triangle(i);
|
||||
gp_Pnt p1 = triangulation->Node(triangle.Value(1)).Transformed(location);
|
||||
gp_Pnt p2 = triangulation->Node(triangle.Value(2)).Transformed(location);
|
||||
gp_Pnt p3 = triangulation->Node(triangle.Value(3)).Transformed(location);
|
||||
faceVertices << p1.X() << p1.Y() << p1.Z();
|
||||
faceVertices << p2.X() << p2.Y() << p2.Z();
|
||||
faceVertices << p3.X() << p3.Y() << p3.Z();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!faceVertices.isEmpty()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
m_shaderProgram->setUniformValue(m_colorLoc, QVector4D(0.5f, 0.5f, 1.0f, 0.5f));
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(faceVertices.constData(), faceVertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_TRIANGLES, 0, faceVertices.size() / 3);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user