use serde::{Deserialize, Serialize};
pub(crate) mod nan_as_null {
use serde::{Deserialize, Deserializer, Serializer};
pub(crate) fn serialize<S>(value: &f32, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if value.is_nan() {
serializer.serialize_none()
} else {
serializer.serialize_f32(*value)
}
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<f32, D::Error>
where
D: Deserializer<'de>,
{
Ok(Option::<f32>::deserialize(deserializer)?.unwrap_or(f32::NAN))
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolicPolyline {
pub express_id: u32,
pub ifc_type: String,
pub points: Vec<f32>,
pub closed: bool,
#[serde(with = "nan_as_null")]
pub world_y: f32,
pub representation: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolicCircle {
pub express_id: u32,
pub ifc_type: String,
pub center_x: f32,
pub center_y: f32,
pub radius: f32,
#[serde(with = "nan_as_null")]
pub world_y: f32,
pub start_angle: f32,
pub end_angle: f32,
pub representation: String,
}
impl SymbolicCircle {
pub fn full(
express_id: u32,
ifc_type: String,
center_x: f32,
center_y: f32,
radius: f32,
world_y: f32,
representation: String,
) -> Self {
Self {
express_id,
ifc_type,
center_x,
center_y,
radius,
world_y,
start_angle: 0.0,
end_angle: std::f32::consts::TAU,
representation,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolicText {
pub express_id: u32,
pub ifc_type: String,
pub x: f32,
pub y: f32,
pub dir_x: f32,
pub dir_y: f32,
pub height: f32,
pub content: String,
pub alignment: String,
#[serde(with = "nan_as_null")]
pub world_y: f32,
pub color: [f32; 4],
pub target_px: f32,
pub representation: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolicFillArea {
pub express_id: u32,
pub ifc_type: String,
pub points: Vec<f32>,
pub holes_offsets: Vec<u32>,
pub fill_color: [f32; 4],
pub has_hatching: bool,
pub hatch_spacing: f32,
pub hatch_angle: f32,
#[serde(with = "nan_as_null")]
pub hatch_angle_secondary: f32,
pub hatch_line_width: f32,
#[serde(with = "nan_as_null")]
pub world_y: f32,
pub representation: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolicGridAxis {
pub express_id: u32,
pub grid_express_id: u32,
pub tag: String,
pub endpoints: [f32; 4],
#[serde(with = "nan_as_null")]
pub world_y: f32,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SymbolicData {
pub grid_axes: Vec<SymbolicGridAxis>,
pub polylines: Vec<SymbolicPolyline>,
pub circles: Vec<SymbolicCircle>,
pub texts: Vec<SymbolicText>,
pub fills: Vec<SymbolicFillArea>,
}
impl SymbolicData {
pub fn is_empty(&self) -> bool {
self.grid_axes.is_empty()
&& self.polylines.is_empty()
&& self.circles.is_empty()
&& self.texts.is_empty()
&& self.fills.is_empty()
}
}