///|
pub fn Transform3::identity() -> Transform3 {
{
m00: 1.0,
m01: 0.0,
m02: 0.0,
m10: 0.0,
m11: 1.0,
m12: 0.0,
m20: 0.0,
m21: 0.0,
m22: 1.0,
tx: 0.0,
ty: 0.0,
tz: 0.0,
}
}
///|
pub fn Transform3::translation(
x~ : Double,
y~ : Double,
z~ : Double,
) -> Transform3 {
{
m00: 1.0,
m01: 0.0,
m02: 0.0,
m10: 0.0,
m11: 1.0,
m12: 0.0,
m20: 0.0,
m21: 0.0,
m22: 1.0,
tx: x,
ty: y,
tz: z,
}
}
///|
pub fn Transform3::apply(self : Transform3, point : Point3) -> Point3 {
{
x: self.m00 * point.x + self.m01 * point.y + self.m02 * point.z + self.tx,
y: self.m10 * point.x + self.m11 * point.y + self.m12 * point.z + self.ty,
z: self.m20 * point.x + self.m21 * point.y + self.m22 * point.z + self.tz,
}
}
///|
pub fn Transform3::multiply(
self : Transform3,
other : Transform3,
) -> Transform3 {
{
m00: self.m00 * other.m00 + self.m01 * other.m10 + self.m02 * other.m20,
m01: self.m00 * other.m01 + self.m01 * other.m11 + self.m02 * other.m21,
m02: self.m00 * other.m02 + self.m01 * other.m12 + self.m02 * other.m22,
m10: self.m10 * other.m00 + self.m11 * other.m10 + self.m12 * other.m20,
m11: self.m10 * other.m01 + self.m11 * other.m11 + self.m12 * other.m21,
m12: self.m10 * other.m02 + self.m11 * other.m12 + self.m12 * other.m22,
m20: self.m20 * other.m00 + self.m21 * other.m10 + self.m22 * other.m20,
m21: self.m20 * other.m01 + self.m21 * other.m11 + self.m22 * other.m21,
m22: self.m20 * other.m02 + self.m21 * other.m12 + self.m22 * other.m22,
tx: self.m00 * other.tx +
self.m01 * other.ty +
self.m02 * other.tz +
self.tx,
ty: self.m10 * other.tx +
self.m11 * other.ty +
self.m12 * other.tz +
self.ty,
tz: self.m20 * other.tx +
self.m21 * other.ty +
self.m22 * other.tz +
self.tz,
}
}
///|
fn placement_point(index : ModelIndex, entity : Entity) -> Transform3 {
match entity_value(entity, 0) {
Some(value) =>
match references(value).get(0) {
Some(point_id) =>
match point_from_entity(index, point_id) {
Some(point) =>
Transform3::translation(x=point.x, y=point.y, z=point.z)
None => Transform3::identity()
}
None => Transform3::identity()
}
None => Transform3::identity()
}
}
///|
fn placement_transform_inner(
index : ModelIndex,
id : Int,
stack : Array[Int],
) -> Transform3? {
if stack.contains(id) {
return None
}
let next_stack = stack.copy()
next_stack.push(id)
match index.entity(id) {
Some(entity) =>
match entity.name.to_upper() {
"IFCLOCALPLACEMENT" => {
let relative = match optional_reference_argument(entity, 1) {
Some(relative_id) =>
placement_transform_inner(index, relative_id, next_stack).unwrap_or(
Transform3::identity(),
)
None => Transform3::identity()
}
match optional_reference_argument(entity, 0) {
Some(parent_id) =>
match placement_transform_inner(index, parent_id, next_stack) {
Some(parent) => Some(parent.multiply(relative))
None => Some(relative)
}
None => Some(relative)
}
}
"IFCAXIS2PLACEMENT3D" | "IFCAXIS2PLACEMENT2D" =>
Some(placement_point(index, entity))
_ => None
}
None => None
}
}
///|
pub fn placement_transform(index : ModelIndex, id : Int) -> Transform3? {
placement_transform_inner(index, id, [])
}
///|
pub fn product_transform(index : ModelIndex, product : Product) -> Transform3 {
match product.placement {
Some(id) => placement_transform(index, id).unwrap_or(Transform3::identity())
None => Transform3::identity()
}
}
///|
pub fn transform_point(
index : ModelIndex,
product : Product,
point : Point3,
) -> Point3 {
product_transform(index, product).apply(point)
}
///|
pub fn transform_points(
index : ModelIndex,
product : Product,
points : Array[Point3],
) -> Array[Point3] {
let transform = product_transform(index, product)
points.map(point => transform.apply(point))
}