Skip to main content

maliput/api/objects/
mod.rs

1// BSD 3-Clause License
2//
3// Copyright (c) 2026, Woven by Toyota.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice, this
10//   list of conditions and the following disclaimer.
11//
12// * Redistributions in binary form must reproduce the above copyright notice,
13//   this list of conditions and the following disclaimer in the documentation
14//   and/or other materials provided with the distribution.
15//
16// * Neither the name of the copyright holder nor the names of its
17//   contributors may be used to endorse or promote products derived from
18//   this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31use std::collections::HashMap;
32use strum_macros::{Display, EnumString};
33
34#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, Display)]
35/// Defines the possible road object types.
36pub enum RoadObjectType {
37    None,
38    Unknown,
39    Barrier,
40    GuardWall,
41    GuardRail,
42    Building,
43    Gantry,
44    Obstacle,
45    Pole,
46    TrafficIsland,
47    Tree,
48    Vegetation,
49    Pylon,
50    Delineator,
51    BikeStatic,
52    BusStatic,
53    CarStatic,
54    MotorbikeStatic,
55    Patch,
56    PedestrianStatic,
57    Railing,
58    RoadSurface,
59    SoundBarrier,
60    StreetLamp,
61    TrailerStatic,
62    TrainStatic,
63    TramStatic,
64    VanStatic,
65    Wind,
66}
67
68fn road_object_type_from_cpp(obj_type: maliput_sys::api::objects::ffi::RoadObjectType) -> RoadObjectType {
69    match obj_type {
70        maliput_sys::api::objects::ffi::RoadObjectType::kUnknown => RoadObjectType::Unknown,
71        maliput_sys::api::objects::ffi::RoadObjectType::kBarrier => RoadObjectType::Barrier,
72        maliput_sys::api::objects::ffi::RoadObjectType::kGuardWall => RoadObjectType::GuardWall,
73        maliput_sys::api::objects::ffi::RoadObjectType::kGuardRail => RoadObjectType::GuardRail,
74        maliput_sys::api::objects::ffi::RoadObjectType::kBuilding => RoadObjectType::Building,
75        maliput_sys::api::objects::ffi::RoadObjectType::kGantry => RoadObjectType::Gantry,
76        maliput_sys::api::objects::ffi::RoadObjectType::kObstacle => RoadObjectType::Obstacle,
77        maliput_sys::api::objects::ffi::RoadObjectType::kPole => RoadObjectType::Pole,
78        maliput_sys::api::objects::ffi::RoadObjectType::kTrafficIsland => RoadObjectType::TrafficIsland,
79        maliput_sys::api::objects::ffi::RoadObjectType::kTree => RoadObjectType::Tree,
80        maliput_sys::api::objects::ffi::RoadObjectType::kVegetation => RoadObjectType::Vegetation,
81        maliput_sys::api::objects::ffi::RoadObjectType::kPylon => RoadObjectType::Pylon,
82        maliput_sys::api::objects::ffi::RoadObjectType::kDelineator => RoadObjectType::Delineator,
83        maliput_sys::api::objects::ffi::RoadObjectType::kBikeStatic => RoadObjectType::BikeStatic,
84        maliput_sys::api::objects::ffi::RoadObjectType::kBusStatic => RoadObjectType::BusStatic,
85        maliput_sys::api::objects::ffi::RoadObjectType::kCarStatic => RoadObjectType::CarStatic,
86        maliput_sys::api::objects::ffi::RoadObjectType::kMotorbikeStatic => RoadObjectType::MotorbikeStatic,
87        maliput_sys::api::objects::ffi::RoadObjectType::kPatch => RoadObjectType::Patch,
88        maliput_sys::api::objects::ffi::RoadObjectType::kPedestrianStatic => RoadObjectType::PedestrianStatic,
89        maliput_sys::api::objects::ffi::RoadObjectType::kRailing => RoadObjectType::Railing,
90        maliput_sys::api::objects::ffi::RoadObjectType::kRoadSurface => RoadObjectType::RoadSurface,
91        maliput_sys::api::objects::ffi::RoadObjectType::kSoundBarrier => RoadObjectType::SoundBarrier,
92        maliput_sys::api::objects::ffi::RoadObjectType::kStreetLamp => RoadObjectType::StreetLamp,
93        maliput_sys::api::objects::ffi::RoadObjectType::kTrailerStatic => RoadObjectType::TrailerStatic,
94        maliput_sys::api::objects::ffi::RoadObjectType::kTrainStatic => RoadObjectType::TrainStatic,
95        maliput_sys::api::objects::ffi::RoadObjectType::kTramStatic => RoadObjectType::TramStatic,
96        maliput_sys::api::objects::ffi::RoadObjectType::kVanStatic => RoadObjectType::VanStatic,
97        maliput_sys::api::objects::ffi::RoadObjectType::kWind => RoadObjectType::Wind,
98        _ => RoadObjectType::None,
99    }
100}
101
102fn road_object_type_to_cpp(obj_type: &RoadObjectType) -> maliput_sys::api::objects::ffi::RoadObjectType {
103    match obj_type {
104        RoadObjectType::None => maliput_sys::api::objects::ffi::RoadObjectType::kUnknown,
105        RoadObjectType::Unknown => maliput_sys::api::objects::ffi::RoadObjectType::kUnknown,
106        RoadObjectType::Barrier => maliput_sys::api::objects::ffi::RoadObjectType::kBarrier,
107        RoadObjectType::GuardWall => maliput_sys::api::objects::ffi::RoadObjectType::kGuardWall,
108        RoadObjectType::GuardRail => maliput_sys::api::objects::ffi::RoadObjectType::kGuardRail,
109        RoadObjectType::Building => maliput_sys::api::objects::ffi::RoadObjectType::kBuilding,
110        RoadObjectType::Gantry => maliput_sys::api::objects::ffi::RoadObjectType::kGantry,
111        RoadObjectType::Obstacle => maliput_sys::api::objects::ffi::RoadObjectType::kObstacle,
112        RoadObjectType::Pole => maliput_sys::api::objects::ffi::RoadObjectType::kPole,
113        RoadObjectType::TrafficIsland => maliput_sys::api::objects::ffi::RoadObjectType::kTrafficIsland,
114        RoadObjectType::Tree => maliput_sys::api::objects::ffi::RoadObjectType::kTree,
115        RoadObjectType::Vegetation => maliput_sys::api::objects::ffi::RoadObjectType::kVegetation,
116        RoadObjectType::Pylon => maliput_sys::api::objects::ffi::RoadObjectType::kPylon,
117        RoadObjectType::Delineator => maliput_sys::api::objects::ffi::RoadObjectType::kDelineator,
118        RoadObjectType::BikeStatic => maliput_sys::api::objects::ffi::RoadObjectType::kBikeStatic,
119        RoadObjectType::BusStatic => maliput_sys::api::objects::ffi::RoadObjectType::kBusStatic,
120        RoadObjectType::CarStatic => maliput_sys::api::objects::ffi::RoadObjectType::kCarStatic,
121        RoadObjectType::MotorbikeStatic => maliput_sys::api::objects::ffi::RoadObjectType::kMotorbikeStatic,
122        RoadObjectType::Patch => maliput_sys::api::objects::ffi::RoadObjectType::kPatch,
123        RoadObjectType::PedestrianStatic => maliput_sys::api::objects::ffi::RoadObjectType::kPedestrianStatic,
124        RoadObjectType::Railing => maliput_sys::api::objects::ffi::RoadObjectType::kRailing,
125        RoadObjectType::RoadSurface => maliput_sys::api::objects::ffi::RoadObjectType::kRoadSurface,
126        RoadObjectType::SoundBarrier => maliput_sys::api::objects::ffi::RoadObjectType::kSoundBarrier,
127        RoadObjectType::StreetLamp => maliput_sys::api::objects::ffi::RoadObjectType::kStreetLamp,
128        RoadObjectType::TrailerStatic => maliput_sys::api::objects::ffi::RoadObjectType::kTrailerStatic,
129        RoadObjectType::TrainStatic => maliput_sys::api::objects::ffi::RoadObjectType::kTrainStatic,
130        RoadObjectType::TramStatic => maliput_sys::api::objects::ffi::RoadObjectType::kTramStatic,
131        RoadObjectType::VanStatic => maliput_sys::api::objects::ffi::RoadObjectType::kVanStatic,
132        RoadObjectType::Wind => maliput_sys::api::objects::ffi::RoadObjectType::kWind,
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use super::{road_object_type_from_cpp, road_object_type_to_cpp, RoadObjectType};
139
140    #[test]
141    fn unknown_from_cpp_stays_unknown() {
142        let cpp = maliput_sys::api::objects::ffi::RoadObjectType::kUnknown;
143        assert_eq!(road_object_type_from_cpp(cpp), RoadObjectType::Unknown);
144    }
145
146    #[test]
147    fn none_to_cpp_maps_to_unknown() {
148        assert!(
149            road_object_type_to_cpp(&RoadObjectType::None) == maliput_sys::api::objects::ffi::RoadObjectType::kUnknown
150        );
151    }
152}
153
154/// Represents the position of a [RoadObject] in the road network.
155///
156/// Always contains an inertial position. May also contain a lane position
157/// expressed as `(lane_id, s, r, h)`.
158pub struct RoadObjectPosition {
159    pub inertial_position: crate::api::InertialPosition,
160    pub lane_position: Option<(String, f64, f64, f64)>,
161}
162
163/// Represents a single corner point of an [Outline].
164///
165/// `height` is `Some` when the corner has an explicit height attribute, `None` otherwise.
166pub struct OutlineCorner {
167    pub x: f64,
168    pub y: f64,
169    pub z: f64,
170    pub height: Option<f64>,
171}
172
173/// Represents a single dimension sample of a continuous [RoadObject].
174///
175/// Continuous-object samples are lane-agnostic: each sample stores width and height at an
176/// explicit inertial point.
177pub struct ContinuousObject {
178    pub width: f64,
179    pub height: f64,
180    pub point_sample: crate::api::InertialPosition,
181}
182
183/// Represents an outline (a polygon) of a [RoadObject].
184pub struct Outline<'a> {
185    pub(crate) outline: &'a maliput_sys::api::objects::ffi::Outline,
186}
187
188impl<'a> Outline<'a> {
189    /// Returns the unique identifier of this outline.
190    pub fn id(&self) -> String {
191        maliput_sys::api::objects::ffi::Outline_id(self.outline)
192    }
193
194    /// Returns whether this outline is closed (first and last corner coincide).
195    pub fn is_closed(&self) -> bool {
196        maliput_sys::api::objects::ffi::Outline_is_closed(self.outline)
197    }
198
199    /// Returns the number of corners in this outline.
200    pub fn num_corners(&self) -> i32 {
201        maliput_sys::api::objects::ffi::Outline_num_corners(self.outline)
202    }
203
204    /// Returns the corners of this outline.
205    pub fn corners(&self) -> Vec<OutlineCorner> {
206        maliput_sys::api::objects::ffi::Outline_corners(self.outline)
207            .into_iter()
208            .map(|c| OutlineCorner {
209                x: c.x,
210                y: c.y,
211                z: c.z,
212                height: if c.has_height { Some(c.height) } else { None },
213            })
214            .collect()
215    }
216}
217
218/// Models a physical road object in the road network.
219///
220/// A `RoadObject` has a type, position, orientation, bounding box, and optional
221/// outlines and properties.
222pub struct RoadObject<'a> {
223    pub(crate) road_object: &'a maliput_sys::api::objects::ffi::RoadObject,
224}
225
226impl<'a> RoadObject<'a> {
227    /// Returns the unique identifier of this road object.
228    pub fn id(&self) -> String {
229        maliput_sys::api::objects::ffi::RoadObject_id(self.road_object)
230    }
231
232    /// Returns the optional human-readable name of this road object.
233    pub fn name(&self) -> Option<String> {
234        let wrapper = maliput_sys::api::objects::ffi::RoadObject_name(self.road_object);
235        if wrapper.is_null() {
236            return None;
237        }
238        Some(wrapper.value.clone())
239    }
240
241    /// Returns the [RoadObjectType] of this road object.
242    pub fn object_type(&self) -> RoadObjectType {
243        let t = maliput_sys::api::objects::ffi::RoadObject_object_type(self.road_object);
244        road_object_type_from_cpp(t)
245    }
246
247    /// Returns the optional subtype string of this road object.
248    pub fn subtype(&self) -> Option<String> {
249        let wrapper = maliput_sys::api::objects::ffi::RoadObject_subtype(self.road_object);
250        if wrapper.is_null() {
251            return None;
252        }
253        Some(wrapper.value.clone())
254    }
255
256    /// Returns the [RoadObjectPosition] of this road object.
257    pub fn position(&self) -> RoadObjectPosition {
258        let inertial_position = maliput_sys::api::objects::ffi::RoadObject_position_inertial(self.road_object);
259        let has_lane = maliput_sys::api::objects::ffi::RoadObject_position_has_lane_position(self.road_object);
260        let lane_position = if has_lane {
261            Some((
262                maliput_sys::api::objects::ffi::RoadObject_position_lane_id(self.road_object),
263                maliput_sys::api::objects::ffi::RoadObject_position_lane_s(self.road_object),
264                maliput_sys::api::objects::ffi::RoadObject_position_lane_r(self.road_object),
265                maliput_sys::api::objects::ffi::RoadObject_position_lane_h(self.road_object),
266            ))
267        } else {
268            None
269        };
270        RoadObjectPosition {
271            inertial_position: crate::api::InertialPosition { ip: inertial_position },
272            lane_position,
273        }
274    }
275
276    /// Returns the orientation of this road object in the inertial frame.
277    pub fn orientation(&self) -> crate::api::Rotation {
278        let rotation = maliput_sys::api::objects::ffi::RoadObject_orientation(self.road_object);
279        crate::api::Rotation { r: rotation }
280    }
281
282    /// Returns the bounding box of this road object.
283    pub fn bounding_box(&self) -> crate::math::BoundingBox {
284        let b = maliput_sys::api::objects::ffi::RoadObject_bounding_box(self.road_object);
285        crate::math::BoundingBox { b }
286    }
287
288    /// Returns whether this road object is dynamic (i.e., may change position or state).
289    pub fn is_dynamic(&self) -> bool {
290        maliput_sys::api::objects::ffi::RoadObject::is_dynamic(self.road_object)
291    }
292
293    /// Returns whether this road object's position can change.
294    pub fn is_movable(&self) -> bool {
295        maliput_sys::api::objects::ffi::RoadObject::is_movable(self.road_object)
296    }
297
298    /// Returns the IDs of lanes related to this road object.
299    pub fn related_lanes(&self) -> Vec<String> {
300        maliput_sys::api::objects::ffi::RoadObject_related_lanes(self.road_object)
301    }
302
303    /// Returns the number of outlines of this road object.
304    pub fn num_outlines(&self) -> i32 {
305        maliput_sys::api::objects::ffi::RoadObject::num_outlines(self.road_object)
306    }
307
308    /// Returns the outlines of this road object.
309    pub fn outlines(&self) -> Vec<Outline<'_>> {
310        maliput_sys::api::objects::ffi::RoadObject_outlines(self.road_object)
311            .into_iter()
312            .map(|ptr| Outline {
313                outline: unsafe { ptr.outline.as_ref().expect("Outline pointer is null") },
314            })
315            .collect()
316    }
317
318    /// Returns the key-value properties of this road object.
319    pub fn properties(&self) -> HashMap<String, String> {
320        maliput_sys::api::objects::ffi::RoadObject_properties(self.road_object)
321            .into_iter()
322            .map(|p| (p.key, p.value))
323            .collect()
324    }
325
326    /// Returns the continuous properties of this road object.
327    ///
328    /// An empty vector indicates that the object does not have continuous properties.
329    pub fn continuous_properties(&self) -> Vec<ContinuousObject> {
330        maliput_sys::api::objects::ffi::RoadObject_continuous_properties(self.road_object)
331            .into_iter()
332            .map(|c| ContinuousObject {
333                width: c.width,
334                height: c.height,
335                point_sample: crate::api::InertialPosition::new(c.x, c.y, c.z),
336            })
337            .collect()
338    }
339}
340
341/// Interface for accessing [RoadObject]s in the road network.
342pub struct RoadObjectBook<'a> {
343    pub(super) road_object_book: &'a maliput_sys::api::objects::ffi::RoadObjectBook,
344}
345
346impl<'a> RoadObjectBook<'a> {
347    /// Returns all [RoadObject]s in the book.
348    pub fn road_objects(&self) -> Vec<RoadObject<'_>> {
349        maliput_sys::api::objects::ffi::RoadObjectBook_RoadObjects(self.road_object_book)
350            .into_iter()
351            .map(|ptr| RoadObject {
352                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
353            })
354            .collect()
355    }
356
357    /// Returns the [RoadObject] with the given `id`, or `None` if not found.
358    pub fn get_road_object(&self, id: &String) -> Option<RoadObject<'_>> {
359        let ptr = maliput_sys::api::objects::ffi::RoadObjectBook_GetRoadObject(self.road_object_book, id);
360        if ptr.is_null() {
361            return None;
362        }
363        Some(RoadObject {
364            road_object: unsafe { ptr.as_ref().expect("Unable to get underlying RoadObject pointer") },
365        })
366    }
367
368    /// Returns all [RoadObject]s of the given [RoadObjectType].
369    pub fn find_by_type(&self, obj_type: &RoadObjectType) -> Vec<RoadObject<'_>> {
370        let obj_type_ffi = road_object_type_to_cpp(obj_type);
371        maliput_sys::api::objects::ffi::RoadObjectBook_FindByType(self.road_object_book, obj_type_ffi)
372            .into_iter()
373            .map(|ptr| RoadObject {
374                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
375            })
376            .collect()
377    }
378
379    /// Returns all [RoadObject]s whose `related_lanes()` includes the given lane ID.
380    pub fn find_by_lane(&self, lane_id: &String) -> Vec<RoadObject<'_>> {
381        maliput_sys::api::objects::ffi::RoadObjectBook_FindByLane(self.road_object_book, lane_id)
382            .into_iter()
383            .map(|ptr| RoadObject {
384                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
385            })
386            .collect()
387    }
388
389    /// Returns all [RoadObject]s within `radius` meters of position `(x, y, z)`.
390    /// If the road object has continuous properties, it will check for all sampled points of the continuous object.
391    pub fn find_in_radius(&self, x: f64, y: f64, z: f64, radius: f64) -> Vec<RoadObject<'_>> {
392        maliput_sys::api::objects::ffi::RoadObjectBook_FindInRadius(self.road_object_book, x, y, z, radius)
393            .into_iter()
394            .map(|ptr| RoadObject {
395                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
396            })
397            .collect()
398    }
399}
400
401/// Domain alias for road marking semantic types.
402pub type RoadMarkingType = crate::api::rules::TrafficControlDeviceType;
403
404#[derive(Debug, Copy, Clone, PartialEq, Eq)]
405/// Unit of a [RoadMarkingValue].
406pub enum RoadMarkingValueUnit {
407    MetersPerSecond,
408    KilometersPerHour,
409    MilesPerHour,
410}
411
412fn road_marking_value_unit_from_cpp(u: maliput_sys::api::objects::ffi::RoadMarkingValueUnit) -> RoadMarkingValueUnit {
413    match u {
414        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kMetersPerSecond => RoadMarkingValueUnit::MetersPerSecond,
415        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kKilometersPerHour => {
416            RoadMarkingValueUnit::KilometersPerHour
417        }
418        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kMilesPerHour => RoadMarkingValueUnit::MilesPerHour,
419        _ => RoadMarkingValueUnit::MetersPerSecond,
420    }
421}
422
423/// Numeric value (with unit) associated with a [RoadMarking] (e.g. a speed limit).
424#[derive(Debug, Copy, Clone, PartialEq)]
425pub struct RoadMarkingValue {
426    pub value: f64,
427    pub unit: RoadMarkingValueUnit,
428}
429
430/// Models a physical road marking (e.g. stop line, crosswalk, arrow) in the road network.
431pub struct RoadMarking<'a> {
432    pub(crate) road_marking: &'a maliput_sys::api::objects::ffi::RoadMarking,
433}
434
435impl<'a> RoadMarking<'a> {
436    /// Returns the unique identifier of this road marking.
437    pub fn id(&self) -> String {
438        maliput_sys::api::objects::ffi::RoadMarking_id(self.road_marking)
439    }
440
441    /// Returns the optional human-readable name of this road marking.
442    pub fn name(&self) -> Option<String> {
443        let wrapper = maliput_sys::api::objects::ffi::RoadMarking_name(self.road_marking);
444        if wrapper.is_null() {
445            return None;
446        }
447        Some(wrapper.value.clone())
448    }
449
450    /// Returns the [RoadMarkingType] of this road marking.
451    pub fn marking_type(&self) -> RoadMarkingType {
452        let t = maliput_sys::api::objects::ffi::RoadMarking_marking_type(self.road_marking);
453        crate::api::rules::traffic_control_device_type_from_cpp(&t)
454    }
455
456    /// Returns the [RoadObjectPosition] of this road marking.
457    pub fn position(&self) -> RoadObjectPosition {
458        let inertial_position = maliput_sys::api::objects::ffi::RoadMarking_position_inertial(self.road_marking);
459        let has_lane = maliput_sys::api::objects::ffi::RoadMarking_position_has_lane_position(self.road_marking);
460        let lane_position = if has_lane {
461            Some((
462                maliput_sys::api::objects::ffi::RoadMarking_position_lane_id(self.road_marking),
463                maliput_sys::api::objects::ffi::RoadMarking_position_lane_s(self.road_marking),
464                maliput_sys::api::objects::ffi::RoadMarking_position_lane_r(self.road_marking),
465                maliput_sys::api::objects::ffi::RoadMarking_position_lane_h(self.road_marking),
466            ))
467        } else {
468            None
469        };
470        RoadObjectPosition {
471            inertial_position: crate::api::InertialPosition { ip: inertial_position },
472            lane_position,
473        }
474    }
475
476    /// Returns the orientation of this road marking in the inertial frame.
477    pub fn orientation(&self) -> crate::api::Rotation {
478        let rotation = maliput_sys::api::objects::ffi::RoadMarking_orientation(self.road_marking);
479        crate::api::Rotation { r: rotation }
480    }
481
482    /// Returns the bounding box of this road marking.
483    pub fn bounding_box(&self) -> crate::math::BoundingBox {
484        let b = maliput_sys::api::objects::ffi::RoadMarking_bounding_box(self.road_marking);
485        crate::math::BoundingBox { b }
486    }
487
488    /// Returns the IDs of lanes related to this road marking.
489    pub fn related_lanes(&self) -> Vec<String> {
490        maliput_sys::api::objects::ffi::RoadMarking_related_lanes(self.road_marking)
491    }
492
493    /// Returns the number of outlines of this road marking.
494    pub fn num_outlines(&self) -> i32 {
495        maliput_sys::api::objects::ffi::RoadMarking::num_outlines(self.road_marking)
496    }
497
498    /// Returns the outlines of this road marking.
499    pub fn outlines(&self) -> Vec<Outline<'_>> {
500        maliput_sys::api::objects::ffi::RoadMarking_outlines(self.road_marking)
501            .into_iter()
502            .map(|ptr| Outline {
503                outline: unsafe { ptr.outline.as_ref().expect("Outline pointer is null") },
504            })
505            .collect()
506    }
507
508    /// Returns the numeric value (with unit) associated with this road marking, if any.
509    pub fn value(&self) -> Option<RoadMarkingValue> {
510        let data = maliput_sys::api::objects::ffi::RoadMarking_value(self.road_marking);
511        if !data.has_value {
512            return None;
513        }
514        Some(RoadMarkingValue {
515            value: data.value,
516            unit: road_marking_value_unit_from_cpp(data.unit),
517        })
518    }
519}
520
521/// Interface for accessing [RoadMarking]s in the road network.
522pub struct RoadMarkingBook<'a> {
523    pub(super) road_marking_book: &'a maliput_sys::api::objects::ffi::RoadMarkingBook,
524}
525
526impl<'a> RoadMarkingBook<'a> {
527    /// Returns all [RoadMarking]s in the book.
528    pub fn road_markings(&self) -> Vec<RoadMarking<'_>> {
529        maliput_sys::api::objects::ffi::RoadMarkingBook_RoadMarkings(self.road_marking_book)
530            .into_iter()
531            .map(|ptr| RoadMarking {
532                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
533            })
534            .collect()
535    }
536
537    /// Returns the [RoadMarking] with the given `id`, or `None` if not found.
538    pub fn get_road_marking(&self, id: &String) -> Option<RoadMarking<'_>> {
539        let ptr = maliput_sys::api::objects::ffi::RoadMarkingBook_GetRoadMarking(self.road_marking_book, id);
540        if ptr.is_null() {
541            return None;
542        }
543        Some(RoadMarking {
544            road_marking: unsafe { ptr.as_ref().expect("Unable to get underlying RoadMarking pointer") },
545        })
546    }
547
548    /// Returns all [RoadMarking]s whose `related_lanes()` includes the given lane ID.
549    pub fn find_by_lane(&self, lane_id: &String) -> Vec<RoadMarking<'_>> {
550        maliput_sys::api::objects::ffi::RoadMarkingBook_FindByLane(self.road_marking_book, lane_id)
551            .into_iter()
552            .map(|ptr| RoadMarking {
553                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
554            })
555            .collect()
556    }
557
558    /// Returns all [RoadMarking]s of the given [RoadMarkingType].
559    pub fn find_by_type(&self, marking_type: &RoadMarkingType) -> Vec<RoadMarking<'_>> {
560        let t_ffi = crate::api::rules::traffic_control_device_type_to_cpp(marking_type);
561        maliput_sys::api::objects::ffi::RoadMarkingBook_FindByType(self.road_marking_book, t_ffi)
562            .into_iter()
563            .map(|ptr| RoadMarking {
564                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
565            })
566            .collect()
567    }
568}