use cxx::UniquePtr;
use ferrocad_geom::Shape;
use opencascade_sys as ffi;
use ffi::top_abs::TopAbs_ShapeEnum;
use ffi::top_tools::TopTools_IndexedMapOfShape;
use ffi::topo_ds::TopoDS_Shape;
use crate::error::OcctError;
pub struct OcctShape(pub(crate) UniquePtr<TopoDS_Shape>);
impl OcctShape {
pub fn from_ref(shape: &TopoDS_Shape) -> Self {
OcctShape(ffi::topo_ds::TopoDS_Shape_to_owned(shape))
}
pub fn borrow(&self) -> &UniquePtr<TopoDS_Shape> {
&self.0
}
}
impl Clone for OcctShape {
fn clone(&self) -> Self {
OcctShape(ffi::topo_ds::TopoDS_Shape_to_owned(&self.0))
}
}
impl std::fmt::Debug for OcctShape {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("OcctShape")
}
}
pub(crate) fn downcast(shape: &Shape) -> Result<&OcctShape, OcctError> {
shape
.downcast_ref::<OcctShape>()
.ok_or(OcctError::WrongBackend)
}
pub(crate) fn erase(shape: &TopoDS_Shape) -> Shape {
Shape::new(OcctShape::from_ref(shape))
}
pub(crate) fn new_map() -> UniquePtr<TopTools_IndexedMapOfShape> {
ffi::top_tools::new_indexed_map_of_shape()
}
pub(crate) fn sub_shape_map(shape: &TopoDS_Shape, kind: TopAbs_ShapeEnum) -> UniquePtr<TopTools_IndexedMapOfShape> {
let mut map = new_map();
ffi::top_exp::TopExp::MapShapes(shape, kind, map.pin_mut());
map
}
pub fn write_brep(shape: &Shape) -> Option<Vec<u8>> {
let occt = downcast(shape).ok()?;
let guard = occt.borrow();
let inner = guard.as_ref()?;
let mut bytes = Vec::new();
crate::bridge::fc_brep_write(inner, &mut bytes);
Some(bytes)
}
pub fn read_brep(bytes: &[u8]) -> Option<Shape> {
let shape = crate::bridge::fc_brep_read(bytes);
if shape.is_null() {
return None;
}
Some(Shape::new(OcctShape(shape)))
}