-
Notifications
You must be signed in to change notification settings - Fork 1
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
Back | 3dModel - Collect information about 3d model c/cpp & rust libraries #5
Comments
Projects overview, not sorted.
|
Project: Truck. Sometimes even rather simple models (I used a cube, a cube with one hole (boolean made), a primitive boat shape) give errors. Known issues/solutions:
{
"boundaries": [
old content
]
} Some other errors might be output CAD specific (I generated models used Rhino 8). The crate maintainer says that such import is not fully supported yet and was added for demos ( ricosjp/truck#29 (comment) ). |
Project: Truck. OK. Two objects can be OR'ed or AND'ed. One of them should be inverted, for instance, via truck_topology::solid::Solid::not(&mut self) |
Project: Truck. I've got a bunch of real boat models exported with different options, included the whole object and chunked into separate parts. After fixes (see known issues/solutions in #5 (comment)) only a few models exported successfully, but with numbers of artefacts. |
Project: Truck. Truck is a good and ambitious project, but in many use cases its functionality doesn't fit our requirements well. For instance,
For now, there are too many questions and nuances being open regarding this tool (I've mentioned only a few). We decided to stop here, and have a look at a next tool from the table. |
Project: opencascade-rs. Generally, the project is an adapter from C++ (native language of OCCT) to Rust. It requires manual cover of C++ modules to be called in Rust. Some functionality is already covered by the author, but many cases are not covered yet. The following instruction describes how to extend the wrapper properly. I've written a few sketches to play with simple and complex objects (the goal of all of them was to find a cross-section by a plane as I did for Truck). It's quite intuitive to develop, and the kernel (OCCT) is well documented (general overview, more technical details of code behind the kernel). |
Project: opencascade-rs. I tested and benchmarked intersection (aka Boolean Common operation) on two models. Read and write from/to STEP works out of box w/o any visual artifacts. Models were created in Rhino 8.0 and (CATIA?). The operation takes about 1sec to complete. Analogue steps in Python console in FreeCAD gives 0.2-0.5 sec. Perhaps, default lack of optimizations affects on that (deeper investigation of this put in backlog). main.rs use std::{os::unix::ffi::OsStrExt, path::PathBuf, str::FromStr};
use anyhow::bail;
use clap::{Parser, Subcommand, ValueEnum};
use glam::dvec3;
use opencascade::{
primitives::{Compound, Edge, IntoShape, Shape},
workplane::Workplane,
};
fn main() {
let args = Args::parse();
let input_model = Shape::read_step(args.input).expect("Failed while reading STEP");
let output_model = {
let result = match args.command {
Cmd::Intersect {
orientation,
heigh,
width,
depth,
} => {
#[cfg(feature = "verbose")]
let mut instant = std::time::Instant::now();
let plane = {
let (plane, dir) = match orientation {
Orientation::Xy => (Workplane::xy(), dvec3(0.0, 0.0, depth)),
Orientation::Xz => (Workplane::xz(), dvec3(0.0, depth, 0.0)),
Orientation::Yz => (Workplane::yz(), dvec3(0.0, 0.0, depth)),
};
plane
.translated(dir)
.rect(width, heigh)
.to_face()
.into_shape()
};
#[cfg(feature = "verbose")]
{
dbg!(instant.elapsed());
instant = std::time::Instant::now();
}
let result = input_model.intersect(&plane).into_shape();
#[cfg(feature = "verbose")]
{
dbg!(instant.elapsed());
}
result
}
};
if args.join_all {
Compound::from_shapes([input_model, result]).into_shape()
} else if args.only_edges {
Compound::from_shapes(result.edges().map(Edge::into_shape)).into_shape()
} else {
result
}
};
output_model
.write_step(args.output)
.expect("Failed while writting STEP");
}
#[derive(Parser, Clone)]
/// Examples of use:
///
/// For model hull_centred.step:
///
/// - YZ touches the front holl (print taken time):
/// :cargo run -rF verbose -- hull_centered.step intersect yz 200000.0 200000.0 112000.0
///
/// - XZ from start to end of the hull:
/// :cargo run -r -- hull_centered.step intersect xz 250000.0 250000.0 0.0
///
/// For model ship_for_a.stp:
///
/// - XZ from left to right:
/// :cargo run -- ship_for_a.step intersect xz 100000.0 100000.0 700.0
pub struct Args {
/// Input file path
#[clap(value_parser = input_parser)]
pub input: PathBuf,
/// Output file path
#[clap(short, long, default_value = "output.step")]
pub output: PathBuf,
/// Join all parts
#[clap(long, default_value_t = false, group = "view")]
pub join_all: bool,
/// Save only edges
#[clap(long, default_value_t = false, group = "view")]
pub only_edges: bool,
/// Commands
#[command(subcommand)]
pub command: Cmd,
}
#[derive(ValueEnum, Clone)]
pub enum Orientation {
Xy,
Xz,
Yz,
}
#[derive(Subcommand, Clone)]
pub enum Cmd {
/// Build plane intersection
Intersect {
orientation: Orientation,
width: f64,
heigh: f64,
depth: f64,
},
}
fn input_parser(arg: &str) -> anyhow::Result<PathBuf> {
let input = PathBuf::from_str(arg)?;
if !matches!(
input.extension().map(OsStrExt::as_bytes),
Some(b"stp" | b"step")
) {
bail!("Supported output format is .step (.stp).");
}
Ok(input)
} Cargo.toml [package]
name = "try-occt-rs"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.86"
opencascade = "0.2"
[dependencies.glam]
version = "0.24.2"
features = ["bytemuck"]
[dependencies.clap]
version = "4"
features = ["derive"]
[features]
verbose = [] |
opencascade-rs crate has wide functionality and fits well out requirements. It's chosen as the main crate to work with 3D objects. Further investigation is planned in scope of the next task. |
Related to a-givertzman/mdmt-server#5 (rsrch).
The text was updated successfully, but these errors were encountered: