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
//! Write las files.

use std::path::Path;

use Result;
use file::File;
use header::Header;
use point::Point;

/// A las writer.
///
/// This wrapper conforms to the more standard structure of requiring a filename on create, not on
/// close.
///
/// I recognize that it's pretty messy to have both this and `File`, and TODO I need to clean
/// things up.
#[derive(Debug)]
pub struct Writer<P: AsRef<Path>> {
    auto_offsets: bool,
    file: File,
    header: Header,
    path: P,
}

impl<P: AsRef<Path>> Writer<P> {
    /// Creates a new writer that will write las data to the given path.
    ///
    /// This won't actually write anything until the writer is closed.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las");
    /// ```
    pub fn from_path(path: P) -> Writer<P> {
        Writer {
            auto_offsets: false,
            file: File::new(),
            header: Header::new(),
            path: path,
        }
    }

    /// Sets the scale factors on a writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").scale_factors(0.01, 0.01, 0.01);
    /// ```
    pub fn scale_factors(mut self,
                         x_scale_factor: f64,
                         y_scale_factor: f64,
                         z_scale_factor: f64)
                         -> Writer<P> {
        self.header.x_scale_factor = x_scale_factor;
        self.header.y_scale_factor = y_scale_factor;
        self.header.z_scale_factor = z_scale_factor;
        self
    }

    /// Sets the offset values for a file.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").offsets(1000.0, 2000.0, 100.0);
    /// ```
    pub fn offsets(mut self, x_offset: f64, y_offset: f64, z_offset: f64) -> Writer<P> {
        self.header.x_offset = x_offset;
        self.header.y_offset = y_offset;
        self.header.z_offset = z_offset;
        self
    }

    /// Enables auto-offsetting.
    ///
    /// If auto-offsetting is enabled, this file will set the header offset values to sensible
    /// values before writing anything. This is usually easier than calculating the offsets
    /// yourself.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").auto_offsets(true);
    /// ```
    pub fn auto_offsets(mut self, enable: bool) -> Writer<P> {
        self.auto_offsets = enable;
        self
    }



    /// Writes a point to this writer.
    ///
    /// Note that this point won't actually be written until the writer is closed.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// use las::point::Point;
    /// let mut writer = Writer::from_path("temp.las");
    /// writer.write_point(Point::new());
    /// ```
    pub fn write_point(&mut self, point: Point) {
        self.file.add_point(point)
    }

    /// Closes this writer and actually writes data out to disc.
    ///
    /// Since we need to calculate some stats on the points for the header, we delay writing until
    /// the very last minute. If you don't want to hold all those points in memory, we'll need to
    /// come up with some other way to do that.
    ///
    /// This function consumes the writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::remove_file;
    /// use las::writer::Writer;
    /// use las::point::Point;
    /// let mut writer = Writer::from_path("temp.las");
    /// writer.write_point(Point::new());
    /// writer.close().unwrap();
    /// remove_file("temp.las").unwrap();
    /// ```
    pub fn close(&mut self) -> Result<()> {
        self.file.set_header(self.header);
        self.file.to_path(&self.path, self.auto_offsets)
    }
}