use crate::ids::{CurveId, PcurveId, ProceduralCurveId, ProceduralSurfaceId, SurfaceId, UnknownId};
use crate::math::{Point2, Point3, Vector3};
use crate::provenance::SourceObjectAssociation;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct NurbsSurface {
pub u_degree: u32,
pub v_degree: u32,
pub u_knots: Vec<f64>,
pub v_knots: Vec<f64>,
pub u_count: u32,
pub v_count: u32,
pub control_points: Vec<Point3>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub weights: Option<Vec<f64>>,
pub u_periodic: bool,
pub v_periodic: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct NurbsCurve {
pub degree: u32,
pub knots: Vec<f64>,
pub control_points: Vec<Point3>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub weights: Option<Vec<f64>>,
pub periodic: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum SurfaceGeometry {
Plane {
origin: Point3,
normal: Vector3,
u_axis: Vector3,
},
Cylinder {
origin: Point3,
axis: Vector3,
ref_direction: Vector3,
radius: f64,
},
Cone {
origin: Point3,
axis: Vector3,
ref_direction: Vector3,
radius: f64,
half_angle: f64,
},
Sphere {
center: Point3,
axis: Vector3,
ref_direction: Vector3,
radius: f64,
},
Torus {
center: Point3,
axis: Vector3,
ref_direction: Vector3,
major_radius: f64,
minor_radius: f64,
},
Nurbs(NurbsSurface),
Unknown {
#[serde(default, skip_serializing_if = "Option::is_none")]
record: Option<UnknownId>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Surface {
pub id: SurfaceId,
pub geometry: SurfaceGeometry,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_object: Option<SourceObjectAssociation>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum CurveGeometry {
Line {
origin: Point3,
direction: Vector3,
},
Circle {
center: Point3,
axis: Vector3,
ref_direction: Vector3,
radius: f64,
},
Ellipse {
center: Point3,
axis: Vector3,
major_direction: Vector3,
major_radius: f64,
minor_radius: f64,
},
Parabola {
vertex: Point3,
axis: Vector3,
major_direction: Vector3,
focal_distance: f64,
},
Hyperbola {
center: Point3,
axis: Vector3,
major_direction: Vector3,
major_radius: f64,
minor_radius: f64,
},
Degenerate {
point: Point3,
},
Nurbs(NurbsCurve),
Unknown {
#[serde(default, skip_serializing_if = "Option::is_none")]
record: Option<UnknownId>,
},
}
pub fn derive_reference_direction(axis: Vector3) -> Vector3 {
let norm = axis.norm();
if !norm.is_finite() || norm == 0.0 {
return Vector3::new(1.0, 0.0, 0.0);
}
let axis = Vector3::new(axis.x / norm, axis.y / norm, axis.z / norm);
let basis = if axis.x.abs() <= axis.y.abs() && axis.x.abs() <= axis.z.abs() {
Vector3::new(1.0, 0.0, 0.0)
} else if axis.y.abs() <= axis.z.abs() {
Vector3::new(0.0, 1.0, 0.0)
} else {
Vector3::new(0.0, 0.0, 1.0)
};
let dot = axis.x * basis.x + axis.y * basis.y + axis.z * basis.z;
let projected = Vector3::new(
basis.x - dot * axis.x,
basis.y - dot * axis.y,
basis.z - dot * axis.z,
);
let projected_norm = projected.norm();
Vector3::new(
projected.x / projected_norm,
projected.y / projected_norm,
projected.z / projected_norm,
)
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Curve {
pub id: CurveId,
pub geometry: CurveGeometry,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_object: Option<SourceObjectAssociation>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ProceduralSurface {
pub id: ProceduralSurfaceId,
pub surface: SurfaceId,
pub definition: ProceduralSurfaceDefinition,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_fit_tolerance: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ProceduralSurfaceDefinition {
Exact {
parameter_ranges: [[f64; 2]; 2],
extension: i64,
},
Compound {
parameters: Vec<f64>,
components: Vec<SurfaceId>,
},
Taper {
support: SurfaceId,
reference: CurveId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pcurve: Option<PcurveGeometry>,
parameter: f64,
taper: TaperSurfaceKind,
},
Loft {
sections: [LoftSection; 2],
parameter_ranges: [[f64; 2]; 2],
closures: [i64; 2],
singularities: [i64; 2],
mode: i64,
bridge: Vec<LoftBridgeToken>,
},
CompoundLoft {
construction: Box<CompoundLoftConstruction>,
},
G2Blend {
construction: Box<G2BlendConstruction>,
},
VariableBlend {
construction: Box<VariableBlendConstruction>,
},
VertexBlend {
construction: Box<VertexBlendConstruction>,
},
Extrusion {
directrix: CurveId,
direction: Vector3,
},
Revolution {
directrix: CurveId,
axis_origin: Point3,
axis_direction: Vector3,
angular_interval: [f64; 2],
parameter_interval: [f64; 2],
transposed: bool,
},
Sum {
first: CurveId,
second: CurveId,
basepoint: Vector3,
},
Sweep {
profile: CurveId,
spine: CurveId,
},
Offset {
support: SurfaceId,
distance: f64,
u_sense: i64,
v_sense: i64,
extension_flags: Vec<bool>,
},
Ruled {
first: CurveId,
second: CurveId,
},
Blend {
supports: [Option<BlendSupport>; 2],
#[serde(default, skip_serializing_if = "Option::is_none")]
spine: Option<CurveId>,
radius: BlendRadiusLaw,
cross_section: BlendCrossSection,
#[serde(default, skip_serializing_if = "Option::is_none")]
native: Option<Box<RollingBallConstruction>>,
},
Unknown {
#[serde(default, skip_serializing_if = "Option::is_none")]
record: Option<UnknownId>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct BlendSupport {
pub surface: SurfaceId,
#[serde(default)]
pub reversed: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum BlendCrossSection {
Circular,
Conic,
Polynomial,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum TaperSurfaceKind {
Standard,
Orthogonal {
sense: bool,
},
Edge {
draft: Vector3,
},
Shadow {
draft: Vector3,
sine: f64,
cosine: f64,
},
Ruled {
draft: Vector3,
sine: f64,
cosine: f64,
factor: f64,
},
Swept {
draft: Vector3,
sine: f64,
cosine: f64,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftSubdataRow {
pub parameters: [f64; 2],
pub columns: Vec<[f64; 2]>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftSubdata {
pub type_code: i64,
pub row_count: i64,
pub column_count: i64,
pub rows: Vec<LoftSubdataRow>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftProfileData {
pub surface: SurfaceId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pcurve: Option<PcurveGeometry>,
pub first_flag: bool,
pub asm_extension: i64,
pub subdata: LoftSubdata,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub direction: Option<Vector3>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftProfileMember {
pub type_code: i64,
pub curve: CurveId,
pub data: LoftProfileData,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftPath {
pub curve: CurveId,
pub auxiliaries: Vec<CurveId>,
pub flag: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftSectionEntry {
pub parameter: f64,
pub profile: Vec<LoftProfileMember>,
pub path: LoftPath,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LoftSection {
pub entries: Vec<LoftSectionEntry>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", content = "value", rename_all = "snake_case")]
pub enum LoftBridgeToken {
Boolean(bool),
Integer(i64),
Double(f64),
Text(String),
Enum(i64),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct G2BlendSide {
pub label: String,
pub surface: SurfaceId,
pub curve: CurveId,
pub pcurves: [Option<PcurveGeometry>; 2],
pub direction: Vector3,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum G2BlendFirstShape {
Full {
#[serde(default, skip_serializing_if = "Option::is_none")]
surface: Option<SurfaceId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
tolerance: Option<f64>,
},
None {
coefficients: [f64; 9],
tolerance: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
extension: Option<LoftBridgeToken>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pcurve: Option<PcurveGeometry>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct G2BlendConstruction {
pub first: G2BlendSide,
pub singularity: i64,
pub first_shape: G2BlendFirstShape,
pub second: G2BlendSide,
pub second_exact_surface: SurfaceId,
pub center_curve: CurveId,
pub center_parameters: [f64; 2],
pub center_flag: i64,
pub parameter_ranges: [[f64; 2]; 2],
pub trailing_parameters: [f64; 4],
pub discontinuities: [Vec<f64>; 3],
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RollingBallSide {
pub label: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub surface: Option<SurfaceId>,
pub curve: CurveId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pcurve: Option<PcurveGeometry>,
pub location: Point3,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub secondary_pcurve: Option<PcurveGeometry>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub exact_support: Option<SurfaceId>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RollingBallThirdSide {
pub label: String,
pub surface: SurfaceId,
pub curve: CurveId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pcurve: Option<PcurveGeometry>,
pub direction: Vector3,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub secondary_pcurve: Option<PcurveGeometry>,
pub extension: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tertiary_pcurve: Option<PcurveGeometry>,
pub flag: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum RollingBallRadiusSelector {
None,
Value {
value: f64,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RollingBallConstruction {
pub sides: Box<[RollingBallSide; 2]>,
pub slice: CurveId,
pub offsets: [f64; 2],
pub radius_selector: RollingBallRadiusSelector,
pub u_range: [f64; 2],
pub v_range: [f64; 2],
pub parameters: [f64; 3],
pub tail: i64,
pub discontinuities: [Vec<f64>; 3],
#[serde(default, skip_serializing_if = "Option::is_none")]
pub third: Option<Box<RollingBallThirdSide>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VariableBlendSide {
pub label: String,
pub surface: SurfaceId,
pub curve: CurveId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pcurve: Option<PcurveGeometry>,
pub location: Point3,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub secondary_pcurve: Option<PcurveGeometry>,
pub scalar: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tertiary_pcurve: Option<PcurveGeometry>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VariableBlendInterpolationPoint {
pub parameter: f64,
pub radius: f64,
pub tangents: [f64; 2],
pub location: Point3,
pub normal: Vector3,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VariableBlendValue {
pub name: String,
pub modern_flag: bool,
pub discriminator: i64,
pub calibrated: i64,
pub payload: VariableBlendValuePayload,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum VariableBlendValuePayload {
TwoEnds {
parameters: [f64; 2],
radii: [f64; 2],
},
EdgeOffset {
scalars: Vec<f64>,
lengths: Vec<f64>,
},
Functional {
parameter: f64,
radius: f64,
function: PcurveGeometry,
terminal: LoftBridgeToken,
},
Constant {
parameters: [f64; 2],
radius: f64,
variable_chamfer: i64,
chamfer_type: i64,
nested: Box<VariableBlendValue>,
},
Interpolated {
parameter: f64,
radius: f64,
function: PcurveGeometry,
enum_count: i64,
points: Vec<VariableBlendInterpolationPoint>,
#[serde(default, skip_serializing_if = "Option::is_none")]
tail: Option<[f64; 2]>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VariableBlendSingleRadiusTail {
pub selector: LoftBridgeToken,
pub parameters: [f64; 2],
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VariableBlendChamfer {
pub variable_chamfer: i64,
pub chamfer_type: i64,
pub value: VariableBlendValue,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VariableBlendConstruction {
pub sides: Box<[VariableBlendSide; 2]>,
pub primary_curve: CurveId,
pub offsets: [f64; 2],
pub radius_kind: i64,
pub first_value: VariableBlendValue,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub second_value: Option<VariableBlendValue>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chamfer: Option<Box<VariableBlendChamfer>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub single_radius_tail: Option<VariableBlendSingleRadiusTail>,
pub u_range: [f64; 2],
pub v_range: [f64; 2],
pub shape_prefix: i64,
pub shape_parameter: f64,
pub shape_length: f64,
pub shape_tail: i64,
pub shape_extensions: [i64; 3],
pub secondary_curve: CurveId,
pub convexity: i64,
pub render_blend: i64,
pub post_range: [f64; 2],
pub post_curve: CurveId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub post_pcurve: Option<PcurveGeometry>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VertexBlendBoundary {
pub boundary_type: i64,
pub magic: Point3,
pub u_smoothing: i64,
pub v_smoothing: i64,
pub fullness: f64,
pub geometry: VertexBlendBoundaryGeometry,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum VertexBlendBoundaryGeometry {
Circle {
curve: CurveId,
form: i64,
twists: Vec<Point3>,
parameters: [f64; 2],
sense: i64,
},
Degenerate {
location: Point3,
normals: [Vector3; 2],
},
Pcurve {
surface: SurfaceId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pcurve: Option<PcurveGeometry>,
sense: i64,
fit_tolerance: f64,
},
Plane {
normal: Vector3,
parameters: [f64; 2],
curve: CurveId,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct VertexBlendConstruction {
pub boundaries: Vec<VertexBlendBoundary>,
pub grid_size: i64,
pub fit_tolerance: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct CompoundLoftScaleMember {
pub type_code: i64,
pub curve: CurveId,
pub data: LoftProfileData,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct CompoundLoftScale {
pub members: Vec<CompoundLoftScaleMember>,
pub path: CurveId,
pub auxiliaries: Vec<CurveId>,
pub tail: [i64; 2],
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum CompoundLoftDirection {
Vector {
value: Vector3,
},
Curve {
curve: CurveId,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum CompoundLoftTail {
Six {
flags: [bool; 2],
#[serde(default, skip_serializing_if = "Option::is_none")]
scale: Option<Box<CompoundLoftScale>>,
selector: i64,
direction: Vector3,
parameter_range: [f64; 2],
curve: CurveId,
},
Seven {
first_flag: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
first_scale: Option<Box<CompoundLoftScale>>,
second_flag: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
second_scale: Option<Box<CompoundLoftScale>>,
selector: i64,
direction: Vector3,
trailing_flags: [bool; 2],
},
Zero {
flags: [bool; 2],
selector: i64,
direction: CompoundLoftDirection,
trailing_flags: [bool; 2],
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct CompoundLoftConstruction {
pub scales: Box<[Option<CompoundLoftScale>; 4]>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fifth_scale: Option<Box<CompoundLoftScale>>,
pub flags: [bool; 2],
pub tail: CompoundLoftTail,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum BlendRadiusLaw {
Constant {
signed_radius: f64,
},
Linear {
start: f64,
end: f64,
},
Law {
curve: NurbsCurve,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ProceduralCurve {
pub id: ProceduralCurveId,
pub curve: CurveId,
pub definition: ProceduralCurveDefinition,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_fit_tolerance: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct IntcurveSupportSide {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub surface: Option<SurfaceId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pcurve: Option<PcurveGeometry>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct IntcurveSupportContext {
pub sides: [IntcurveSupportSide; 2],
pub parameter_range: [f64; 2],
pub discontinuities: [Vec<f64>; 3],
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ProjectionTail {
EarlyClose {
flag: bool,
},
Ranged {
flag: bool,
parameter_range: [f64; 2],
role: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SurfaceCurveFamily {
Blend,
SurfaceConstrained,
Parametric,
Skin,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum SilhouetteKind {
Standard,
Parametric,
Taper {
draft_factor: f64,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum DeformableCurveData {
VectorField {
vectors: [Vector3; 4],
parameter_pairs: Vec<[f64; 2]>,
},
Surface {
surface: SurfaceId,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ProceduralCurveDefinition {
Exact,
Compound {
parameters: Vec<f64>,
component_parameters: Vec<f64>,
components: Vec<CurveId>,
},
Helix {
angle_range: [f64; 2],
center: Point3,
major: Vector3,
minor: Vector3,
pitch: Vector3,
apex_factor: f64,
axis: Vector3,
},
Intersection {
context: IntcurveSupportContext,
},
ThreeSurfaceIntersection {
context: IntcurveSupportContext,
selector: i64,
third: IntcurveSupportSide,
},
SurfaceCurve {
family: SurfaceCurveFamily,
context: IntcurveSupportContext,
},
Silhouette {
context: IntcurveSupportContext,
silhouette: SilhouetteKind,
cast_surface: SurfaceId,
light_direction: Vector3,
},
SurfaceOffset {
context: IntcurveSupportContext,
base_u_range: [f64; 2],
base_v_range: [f64; 2],
base: CurveId,
base_range: [f64; 2],
distance: f64,
shift: f64,
scale: f64,
},
Spring {
context: IntcurveSupportContext,
surface_parameter_ranges: [Option<[[f64; 2]; 2]>; 2],
#[serde(default, skip_serializing_if = "Option::is_none")]
first_pcurve_parameter_range: Option<[f64; 2]>,
direction: i64,
},
Deformable {
extension: i64,
bend: CurveId,
data: DeformableCurveData,
},
Projection {
context: IntcurveSupportContext,
source: CurveId,
tail: ProjectionTail,
},
Offset {
source: CurveId,
distance: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
support: Option<SurfaceId>,
},
TwoSidedOffset {
context: IntcurveSupportContext,
offsets: [f64; 2],
},
VectorOffset {
source: CurveId,
parameter_range: [f64; 2],
offset: Vector3,
labels: [String; 2],
codes: [i64; 2],
},
Subset {
source: CurveId,
parameter_range: [f64; 2],
},
BlendSpine {
#[serde(default, skip_serializing_if = "Option::is_none")]
blend_surface: Option<SurfaceId>,
},
Unknown {
#[serde(default, skip_serializing_if = "Option::is_none")]
record: Option<UnknownId>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum PcurveGeometry {
Line {
origin: Point2,
direction: Point2,
},
Nurbs {
degree: u32,
knots: Vec<f64>,
control_points: Vec<Point2>,
#[serde(default, skip_serializing_if = "Option::is_none")]
weights: Option<Vec<f64>>,
#[serde(default)]
periodic: bool,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Pcurve {
pub id: PcurveId,
pub geometry: PcurveGeometry,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wrapper_reversed: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parameter_range: Option<[f64; 2]>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fit_tolerance: Option<f64>,
}