Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(occara): Implement Rust bindings for creating the OpenCASCADE bottle example #4

Merged
merged 44 commits into from
Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
605c850
feat: implement first part of occara
maximmaxim345 Mar 17, 2024
ddce043
docs: add readme
maximmaxim345 Mar 20, 2024
7345e97
feat: add support for axis2d
maximmaxim345 Mar 20, 2024
2a95c7c
feat: add make_cylinder
maximmaxim345 Mar 20, 2024
9a0c4e3
feat: add fuse
maximmaxim345 Mar 21, 2024
f0f2ee1
feat: add functions for selecting highest plane in shape
maximmaxim345 Mar 21, 2024
1776aba
feat: add ThickSolidBuilder
maximmaxim345 Mar 21, 2024
25cac0a
refactor: rename MakeWire to WireBuilder
maximmaxim345 Mar 21, 2024
87a8031
refactor: rename Axis2d to PlaneAxis
maximmaxim345 Mar 21, 2024
f89fcd2
feat: add 2d geometric primitives and CylindricalSurface
maximmaxim345 Mar 21, 2024
389c9a4
feat: add TrimmedCurve2D and Ellipse2D
maximmaxim345 Mar 21, 2024
967b3d1
feat: add build_curves3d and Edge::new_with_surface
maximmaxim345 Mar 21, 2024
ee80691
feat: add Loft
maximmaxim345 Mar 21, 2024
a21a95e
feat: add Compound
maximmaxim345 Mar 21, 2024
e47cd3f
refactor: rename ThickSolid to Shell
maximmaxim345 Mar 21, 2024
be583a2
fix: clippy spam of auto generated bindings
maximmaxim345 Mar 21, 2024
f694570
test: move make bottle (c++) into integration test
maximmaxim345 Mar 21, 2024
782ddfc
refactor: remove unused bindings
maximmaxim345 Mar 21, 2024
a874fa7
fix: apply clippy suggestions
maximmaxim345 Mar 21, 2024
5a00822
refactor: rename facesToRemove to snake case
maximmaxim345 Mar 22, 2024
c9329c5
fix: make Shell.fuse() const
maximmaxim345 Mar 22, 2024
480a9bf
refactor: rename check_compatibility to ensure_wire_compatibility
maximmaxim345 Mar 22, 2024
e2aa1b2
refactor: remove unused c++ headers
maximmaxim345 Mar 22, 2024
60fad65
docs: reword description
maximmaxim345 Mar 22, 2024
e78b3ee
refactor: remove uneccessary throw
maximmaxim345 Mar 22, 2024
9b592ca
refactor: rename make_cylinder to Shape::cylinder
maximmaxim345 Mar 22, 2024
fec0548
refactor: remove "name_" prefix from functions
maximmaxim345 Mar 22, 2024
bfaa324
docs: add comment explaining make_bottle_cpp
maximmaxim345 Mar 22, 2024
69733c1
docs: move C++ autocomplete instructions to README
maximmaxim345 Mar 22, 2024
a790b54
refactor: remove unneccessary clone
maximmaxim345 Mar 22, 2024
64aafa0
refactor: use ffi namespace
maximmaxim345 Mar 22, 2024
63746ef
refactor: organize C++ code
maximmaxim345 Mar 22, 2024
57e3097
refactor: make cylinder a static member function of Shape
maximmaxim345 Mar 22, 2024
4bd5ac9
chore: remove unecessary test
maximmaxim345 Mar 22, 2024
eb30a25
refactor: replace C++ constructors with factory methods
maximmaxim345 Mar 22, 2024
48a0c4e
feat: implement Clone for all types
maximmaxim345 Mar 22, 2024
3626c6b
feat: add SpaceAxis
maximmaxim345 Mar 23, 2024
c96c2a4
feat: add Curve2D and Surface types
maximmaxim345 Mar 23, 2024
2d5aa3b
refactor: new_with_surface now takes in any 2d curve and surface
maximmaxim345 Mar 23, 2024
adb6675
refactor: Transformation.apply is now generic
maximmaxim345 Mar 23, 2024
1ffd361
refactor: make trim work on all 2D curves
maximmaxim345 Mar 23, 2024
77e4586
refactor: simplify Vertex
maximmaxim345 Mar 23, 2024
65395fc
fix: add missing forward declarations
maximmaxim345 Mar 23, 2024
134f59e
refactor: compound api
maximmaxim345 Mar 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/occara/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "occara"
description = "High-level Rust bindings to the OpenCASCADE B-Rep library"
version = "0.1.0"
edition = "2021"

Expand All @@ -16,3 +17,6 @@ cxx-build = { version = "1.0.118", features = ["parallel"] }
walkdir = "2.4.0"
autocxx-build = "0.26.0"
miette = { version = "5", features = ["fancy"] }

[dev-dependencies]
ordered-float = "4.2.0"
19 changes: 19 additions & 0 deletions crates/occara/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# occara

occara provides high-level Rust bindings for the OpenCASCADE B-Rep library. It is internally used by CADara to manipulate 3D models.

## Structure

occara consists of:
- A higher-level C++ wrapper around OpenCASCADE, written in an easily parse-able subset of C++. This allows performance critical CADara-specific code to directly use optimized OpenCASCADE data structures, avoiding overhead from the C++ to Rust bridge.
- Rust bindings for the C++ wrapper, automatically generated using autocxx
- A thin Rust library layer to provide a safe, idiomatic Rust API

## Status & Todos
- Error handling is not implemented yet. The C++ wrapper should catch all exceptions and pass them to Rust, since autocxx does not support C++ exceptions.
- This library does not feature all OpenCASCADE functionality yet. It is being developed incrementally as needed by CADara.
- in the future, this API could be made accessible to CADara plugins. This would enable plugins to implement custom CAD operations and functionality, while being sandboxed from the core CADara application for security and stability.

## Development

To get autocomplete to work on the C++ code, run `touch cpp` and `bear -- cargo build` in this crates directory. This will generate a compile_commands.json file. ('touch cpp' will ensure that the C++ code is recompiled)
18 changes: 4 additions & 14 deletions crates/occara/cpp/MakeBottle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@

#include <TopTools_ListOfShape.hxx>

std::unique_ptr<TopoDS_Shape> MakeBottle(const Standard_Real theWidth,
const Standard_Real theHeight,
const Standard_Real theThickness) {
occara::shape::Shape MakeBottle(const Standard_Real theWidth,
const Standard_Real theHeight,
const Standard_Real theThickness) {
// Profile : Define Support Points
gp_Pnt aPnt1(-theWidth / 2., 0, 0);
gp_Pnt aPnt2(-theWidth / 2., -theThickness / 4., 0);
Expand Down Expand Up @@ -223,15 +223,5 @@ std::unique_ptr<TopoDS_Shape> MakeBottle(const Standard_Real theWidth,
aBuilder.Add(aRes, myBody);
aBuilder.Add(aRes, myThreading);

// Print the resulting shape
TopExp_Explorer explorer;
for (explorer.Init(aRes, TopAbs_ShapeEnum::TopAbs_FACE); explorer.More();
explorer.Next()) {
const TopoDS_Shape &currentShape = explorer.Current();
// Print information about the current shape
std::cout << "Shape Type: " << currentShape.ShapeType() << std::endl;
// You can add more details here depending on what you want to print
}

return std::make_unique<TopoDS_Shape>(TopoDS_Shape(aRes));
return occara::shape::Shape{TopoDS_Shape(aRes)};
}
185 changes: 185 additions & 0 deletions crates/occara/cpp/geom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#include "geom.hpp"
#include "GCE2d_MakeSegment.hxx"

namespace occara::geom {

// Point

Point Point::create(Standard_Real x, Standard_Real y, Standard_Real z) {
return Point{gp_Pnt(x, y, z)};
}

Point Point::clone() const { return *this; }

void Point::get_coordinates(Standard_Real &x, Standard_Real &y,
Standard_Real &z) const {
x = point.X();
y = point.Y();
z = point.Z();
}

double Point::x() const { return point.X(); }
double Point::y() const { return point.Y(); }
double Point::z() const { return point.Z(); }

// Point2D

Point2D Point2D::create(Standard_Real x, Standard_Real y) {
return Point2D{gp_Pnt2d(x, y)};
}

Point2D Point2D::clone() const { return *this; }

void Point2D::get_coordinates(Standard_Real &x, Standard_Real &y) const {
x = point.X();
y = point.Y();
}

double Point2D::x() const { return point.X(); }
double Point2D::y() const { return point.Y(); }

// Vector

Vector Vector::create(Standard_Real x, Standard_Real y, Standard_Real z) {
return Vector{gp_Vec(x, y, z)};
}

Vector Vector::clone() const { return *this; }

// Direction

Direction Direction::create(Standard_Real x, Standard_Real y, Standard_Real z) {
return Direction{gp_Dir(x, y, z)};
}

Direction Direction::clone() const { return *this; }

// Direction2D

Direction2D Direction2D::create(Standard_Real x, Standard_Real y) {
return Direction2D{gp_Dir2d(x, y)};
}

Direction2D Direction2D::clone() const { return *this; }

// Axis

Axis Axis::create(const Point &origin, const Direction &direction) {
return Axis{gp_Ax1(origin.point, direction.direction)};
}

Axis Axis::clone() const { return *this; }

// Axis2D

Axis2D Axis2D::create(const Point2D &origin, const Direction2D &direction) {
return Axis2D{gp_Ax2d(origin.point, direction.direction)};
}

Axis2D Axis2D::clone() const { return *this; }

// PlaneAxis

PlaneAxis PlaneAxis::create(const Point &origin, const Direction &direction) {
return PlaneAxis{gp_Ax2(origin.point, direction.direction)};
}

PlaneAxis PlaneAxis::clone() const { return *this; }

// SpaceAxis

SpaceAxis SpaceAxis::create(const Point &origin, const Direction &direction) {
return SpaceAxis{gp_Ax3(origin.point, direction.direction)};
}

SpaceAxis SpaceAxis::clone() const { return *this; }

// TrimmedCurve

TrimmedCurve TrimmedCurve::arc_of_circle(const Point &p1, const Point &p2,
const Point &p3) {
return TrimmedCurve{GC_MakeArcOfCircle(p1.point, p2.point, p3.point)};
}

TrimmedCurve TrimmedCurve::line(const Point &p1, const Point &p2) {
return TrimmedCurve{GC_MakeSegment(p1.point, p2.point)};
}

TrimmedCurve TrimmedCurve::clone() const { return *this; }

// TrimmedCurve2D

TrimmedCurve2D TrimmedCurve2D::line(const Point2D &p1, const Point2D &p2) {
return TrimmedCurve2D{GCE2d_MakeSegment(p1.point, p2.point)};
}

TrimmedCurve2D TrimmedCurve2D::clone() const { return *this; }

// Curve2D
Curve2D Curve2D::from_trimmed_curve2d(const TrimmedCurve2D &curve) {
return Curve2D{const_cast<TrimmedCurve2D &>(curve).curve};
}

Curve2D Curve2D::clone() const { return *this; }

TrimmedCurve2D Curve2D::trim(Standard_Real u1, Standard_Real u2) const {
return TrimmedCurve2D{new Geom2d_TrimmedCurve(curve, u1, u2)};
}

// Ellipse2D

Ellipse2D Ellipse2D::create(const Axis2D &axis, Standard_Real major_radius,
Standard_Real minor_radius) {
return Ellipse2D{new Geom2d_Ellipse(axis.axis, major_radius, minor_radius)};
}

Ellipse2D Ellipse2D::clone() const { return *this; }

Point2D Ellipse2D::value(Standard_Real u) const {
return Point2D{ellipse->Value(u)};
}

Curve2D Ellipse2D::curve() const {
return Curve2D{const_cast<Ellipse2D &>(*this).ellipse};
}

// Plane

Plane Plane::clone() const { return *this; }

Point Plane::location() const { return Point{plane->Location()}; }

// Surface

Surface Surface::from_cylindrical_surface(const CylindricalSurface &surface) {
return Surface{const_cast<CylindricalSurface &>(surface).surface};
}

Surface Surface::clone() const { return *this; }

bool Surface::is_plane() const {
return surface->DynamicType() == STANDARD_TYPE(Geom_Plane);
}

Plane Surface::as_plane() const {
return Plane{Handle(Geom_Plane)::DownCast(surface)};
}

// Transformation

Transformation Transformation::clone() const { return *this; }

void Transformation::mirror(const Axis &axis) {
transformation.SetMirror(axis.axis);
}

// CylindricalSurface

CylindricalSurface CylindricalSurface::create(const PlaneAxis &axis,
Standard_Real radius) {
return CylindricalSurface{new Geom_CylindricalSurface(axis.axis, radius)};
}

CylindricalSurface CylindricalSurface::clone() const { return *this; }

} // namespace occara::geom
Loading
Loading