acadrust 0.4.1

A pure Rust library for reading and writing CAD files in DXF format (ASCII and Binary) and DWG format (Binary).
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
//! Stub object types for DXF objects that need basic round-trip support.
//!
//! These are minimal representations of DXF objects that ACadSharp supports
//! but that don't require full rich data models for typical usage.

use crate::types::{Handle, Matrix4, Vector2, Vector3};

/// Trait for minimal stub objects that only need handle + owner fields.
/// Used by the generic `read_stub_object` reader.
pub trait StubObject {
    /// Create a new default instance
    fn new_stub() -> Self;
    /// Set the object handle
    fn set_handle(&mut self, handle: Handle);
    /// Set the owner handle
    fn set_owner(&mut self, owner: Handle);
    /// Get the object handle
    fn handle(&self) -> Handle;
}

/// VisualStyle object — named visual rendering style
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VisualStyle {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Description / name
    pub description: String,
    /// Style type (code 70)
    pub style_type: i16,
    /// Face lighting model (code 71)
    pub face_lighting_model: i16,
    /// Face lighting quality (code 72)
    pub face_lighting_quality: i16,
    /// Face color mode (code 73)
    pub face_color_mode: i16,
    /// Face modifier (code 90)
    pub face_modifier: i32,
    /// Edge model (code 91)
    pub edge_model: i32,
    /// Edge style (code 92)
    pub edge_style: i32,
    /// Internal use only flag (code 291)
    pub internal_use_only: bool,
}

impl VisualStyle {
    /// Create a new VisualStyle with defaults
    pub fn new() -> Self {
        VisualStyle {
            handle: Handle::NULL,
            owner: Handle::NULL,
            description: String::new(),
            style_type: 0,
            face_lighting_model: 0,
            face_lighting_quality: 0,
            face_color_mode: 0,
            face_modifier: 0,
            edge_model: 0,
            edge_style: 0,
            internal_use_only: false,
        }
    }
}

impl Default for VisualStyle {
    fn default() -> Self { Self::new() }
}

/// Material object — named material for 3D rendering
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Material {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Material name
    pub name: String,
    /// Description
    pub description: String,
}

impl Material {
    /// Create a new Material with defaults
    pub fn new() -> Self {
        Material {
            handle: Handle::NULL,
            owner: Handle::NULL,
            name: String::new(),
            description: String::new(),
        }
    }
}

impl Default for Material {
    fn default() -> Self { Self::new() }
}

/// GeoData — geographic location data for a drawing (AcDbGeoData).
///
/// Carries the drawing's georeference, most importantly the coordinate-system
/// definition (a MapGuide coordinate-system XML string on R2010+; a WKT PROJCS
/// string on R2009).
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GeoData {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Object version (code 90): 1 = R2009, 2 = R2010, 3 = R2013
    pub version: i32,
    /// Soft pointer to the host block record
    pub host_block: Handle,
    /// Coordinate type (code 70): 0 = unknown, 1 = local grid, 2 = projected grid, 3 = geographic
    pub coordinate_type: i16,
    /// Design point (WCS) (codes 10/20/30)
    pub design_point: Vector3,
    /// Reference point (geographic/projected) (codes 11/21/31)
    pub reference_point: Vector3,
    /// North direction vector (codes 12/22)
    pub north_direction: Vector2,
    /// Up direction (codes 210/220/230)
    pub up_direction: Vector3,
    /// Horizontal unit scale (code 41)
    pub horizontal_unit_scale: f64,
    /// Vertical unit scale (code 40)
    pub vertical_unit_scale: f64,
    /// Horizontal units (code 91)
    pub horizontal_units: i32,
    /// Vertical units (code 92)
    pub vertical_units: i32,
    /// Scale estimation method (code 95)
    pub scale_estimation_method: i32,
    /// User-specified scale factor (code 141)
    pub user_scale_factor: f64,
    /// Enable sea-level correction (code 294)
    pub sea_level_correction: bool,
    /// Sea-level elevation (code 142)
    pub sea_level_elevation: f64,
    /// Coordinate projection radius (code 143)
    pub coordinate_projection_radius: f64,
    /// Coordinate system definition (code 301): MapGuide XML (R2010+) or WKT (R2009)
    pub coordinate_system_definition: String,
    /// Geo RSS tag (code 302)
    pub geo_rss_tag: String,
    /// Observation-from tag (code 305)
    pub observation_from_tag: String,
    /// Observation-to tag (code 306)
    pub observation_to_tag: String,
    /// Observation-coverage tag (code 307)
    pub observation_coverage_tag: String,
}

impl GeoData {
    /// Create a new GeoData
    pub fn new() -> Self {
        GeoData {
            handle: Handle::NULL,
            owner: Handle::NULL,
            version: 2,
            host_block: Handle::NULL,
            coordinate_type: 0,
            design_point: Vector3::default(),
            reference_point: Vector3::default(),
            north_direction: Vector2::default(),
            up_direction: Vector3::default(),
            horizontal_unit_scale: 1.0,
            vertical_unit_scale: 1.0,
            horizontal_units: 0,
            vertical_units: 0,
            scale_estimation_method: 0,
            user_scale_factor: 1.0,
            sea_level_correction: false,
            sea_level_elevation: 0.0,
            coordinate_projection_radius: 0.0,
            coordinate_system_definition: String::new(),
            geo_rss_tag: String::new(),
            observation_from_tag: String::new(),
            observation_to_tag: String::new(),
            observation_coverage_tag: String::new(),
        }
    }
}

impl Default for GeoData {
    fn default() -> Self { Self::new() }
}

/// SpatialFilter — the clip boundary (XCLIP) attached to a block reference.
///
/// Stored under the INSERT's extension dictionary as the `SPATIAL` entry of
/// the `ACAD_FILTER` sub-dictionary. The boundary points are 2D coordinates in
/// the clip boundary's local coordinate system; two transforms relate that
/// system to the block reference and to the world.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SpatialFilter {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Clip boundary definition points (code 10/20), in the boundary's local
    /// 2D coordinate system. Two points = rectangular clip (min/max corners);
    /// three or more = polygonal clip.
    pub boundary_points: Vec<Vector2>,
    /// Normal to the plane of the clip boundary (code 210/220/230).
    pub normal: Vector3,
    /// Origin of the clip boundary local coordinate system (code 11/21/31).
    pub origin: Vector3,
    /// Clip boundary display enabled flag (code 71).
    pub display_enabled: bool,
    /// Front clipping plane distance (code 40), `Some` when the front clip
    /// flag (code 72) is set.
    pub front_clip: Option<f64>,
    /// Back clipping plane distance (code 41), `Some` when the back clip
    /// flag (code 73) is set.
    pub back_clip: Option<f64>,
    /// 4×3 matrix (column-major in DXF) transforming WCS points into the
    /// block-definition coordinate system — the inverse block transform.
    pub inverse_block_transform: Matrix4,
    /// 4×3 matrix transforming clip boundary points into the block reference
    /// coordinate system.
    pub clip_bound_transform: Matrix4,
}

impl SpatialFilter {
    /// Create a new SpatialFilter
    pub fn new() -> Self {
        SpatialFilter {
            handle: Handle::NULL,
            owner: Handle::NULL,
            boundary_points: Vec::new(),
            normal: Vector3::new(0.0, 0.0, 1.0),
            origin: Vector3::new(0.0, 0.0, 0.0),
            display_enabled: true,
            front_clip: None,
            back_clip: None,
            inverse_block_transform: Matrix4::identity(),
            clip_bound_transform: Matrix4::identity(),
        }
    }
}

impl Default for SpatialFilter {
    fn default() -> Self { Self::new() }
}

/// RasterVariables — global raster image settings
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RasterVariables {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Class version (code 90)
    pub class_version: i32,
    /// Image frame display (code 70): 0 = no frame, 1 = display frame
    pub display_image_frame: i16,
    /// Image quality (code 71): 0 = draft, 1 = high
    pub image_quality: i16,
    /// Units (code 72): 0 = none, 1 = mm, 2 = cm, 3 = m, 4 = km, 5 = in, 6 = ft, 7 = yd, 8 = mi
    pub units: i16,
}

impl RasterVariables {
    /// Create new RasterVariables
    pub fn new() -> Self {
        RasterVariables {
            handle: Handle::NULL,
            owner: Handle::NULL,
            class_version: 0,
            display_image_frame: 1,
            image_quality: 1,
            units: 0,
        }
    }
}

impl Default for RasterVariables {
    fn default() -> Self { Self::new() }
}

/// BookColor (DBCOLOR) — named color definition
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BookColor {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Color name (code 1)
    pub color_name: String,
    /// Book name (code 2)
    pub book_name: String,
}

impl BookColor {
    /// Create a new BookColor
    pub fn new() -> Self {
        BookColor {
            handle: Handle::NULL,
            owner: Handle::NULL,
            color_name: String::new(),
            book_name: String::new(),
        }
    }
}

impl Default for BookColor {
    fn default() -> Self { Self::new() }
}

/// AcDbPlaceHolder — placeholder object (no data beyond handle)
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PlaceHolder {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
}

impl PlaceHolder {
    /// Create a new PlaceHolder
    pub fn new() -> Self {
        PlaceHolder {
            handle: Handle::NULL,
            owner: Handle::NULL,
        }
    }
}

impl Default for PlaceHolder {
    fn default() -> Self { Self::new() }
}

/// DictionaryWithDefault — dictionary with a default entry handle
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DictionaryWithDefault {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Dictionary entries (key -> handle)
    pub entries: Vec<(String, Handle)>,
    /// Default entry handle (code 340)
    pub default_handle: Handle,
    /// Duplicate record cloning flag (code 281)
    pub duplicate_cloning: i16,
    /// Hard owner flag (code 280)
    pub hard_owner: bool,
}

impl DictionaryWithDefault {
    /// Create a new DictionaryWithDefault
    pub fn new() -> Self {
        DictionaryWithDefault {
            handle: Handle::NULL,
            owner: Handle::NULL,
            entries: Vec::new(),
            default_handle: Handle::NULL,
            duplicate_cloning: 1,
            hard_owner: false,
        }
    }
}

impl Default for DictionaryWithDefault {
    fn default() -> Self { Self::new() }
}

/// WipeoutVariables — global wipeout display settings
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct WipeoutVariables {
    /// Unique handle
    pub handle: Handle,
    /// Owner handle
    pub owner: Handle,
    /// Display image frame (code 70): 0 = no, 1 = yes
    pub display_frame: i16,
}

impl WipeoutVariables {
    /// Create new WipeoutVariables
    pub fn new() -> Self {
        WipeoutVariables {
            handle: Handle::NULL,
            owner: Handle::NULL,
            display_frame: 0,
        }
    }
}

impl Default for WipeoutVariables {
    fn default() -> Self { Self::new() }
}

// StubObject implementations for types that only need handle + owner parsing

macro_rules! impl_stub_object {
    ($ty:ident) => {
        impl StubObject for $ty {
            fn new_stub() -> Self { Self::new() }
            fn set_handle(&mut self, handle: Handle) { self.handle = handle; }
            fn set_owner(&mut self, owner: Handle) { self.owner = owner; }
            fn handle(&self) -> Handle { self.handle }
        }
    };
}

impl_stub_object!(GeoData);
impl_stub_object!(PlaceHolder);