Struct kas_core::geom::DVec2

source ·
#[repr(C)]
pub struct DVec2(pub f64, pub f64);
Expand description

2D vector (double precision)

Usually used as either a coordinate or a difference of coordinates, but may have some other uses.

Vectors are partially ordered and support component-wise comparison via methods like lhs.lt(rhs). The PartialOrd trait is not implemented since it implements lhs ≤ rhs as lhs < rhs || lhs == rhs which is wrong for vectors (consider for lhs = (0, 1), rhs = (1, 0)).

Tuple Fields§

§0: f64§1: f64

Implementations§

Zero

One

Negative infinity

Positive infinity

Not a Number (NaN)

Constructs a new instance with each element initialized to value.

Take the minimum component

Take the maximum component

Return the minimum, componentwise

Return the maximum, componentwise

Take the absolute value of each component

Take the floor of each component

Take the ceiling of each component

Round each component to the nearest integer

Take the trunc of each component

Take the fract of each component

For each component, return ±1 with the same sign as self.

True when for all components, lhs < rhs

True when for all components, lhs ≤ rhs

True when for all components, lhs ≥ rhs

True when for all components, lhs > rhs

Multiply two vectors as if they are complex numbers

Examples found in repository?
src/event/manager/mgr_shell.rs (line 190)
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
    pub fn update(&mut self, shell: &mut dyn ShellWindow, widget: &mut dyn Widget) -> TkAction {
        let old_hover_icon = self.hover_icon;

        let mut mgr = EventMgr {
            state: self,
            shell,
            messages: vec![],
            scroll: Scroll::None,
            action: TkAction::empty(),
        };

        while let Some((parent, wid)) = mgr.popup_removed.pop() {
            mgr.send_event(widget, parent, Event::PopupRemoved(wid));
        }

        if let Some((id, event)) = mgr.mouse_grab().and_then(|g| g.flush_move()) {
            mgr.send_event(widget, id, event);
        }

        for i in 0..mgr.touch_grab.len() {
            if let Some((id, event)) = mgr.touch_grab[i].flush_move() {
                mgr.send_event(widget, id, event);
            }
        }

        for gi in 0..mgr.pan_grab.len() {
            let grab = &mut mgr.pan_grab[gi];
            debug_assert!(grab.mode != GrabMode::Grab);
            assert!(grab.n > 0);

            // Terminology: pi are old coordinates, qi are new coords
            let (p1, q1) = (DVec2::conv(grab.coords[0].0), DVec2::conv(grab.coords[0].1));
            grab.coords[0].0 = grab.coords[0].1;

            let alpha;
            let delta;

            if grab.mode == GrabMode::PanOnly || grab.n == 1 {
                alpha = DVec2(1.0, 0.0);
                delta = q1 - p1;
            } else {
                // We don't use more than two touches: information would be
                // redundant (although it could be averaged).
                let (p2, q2) = (DVec2::conv(grab.coords[1].0), DVec2::conv(grab.coords[1].1));
                grab.coords[1].0 = grab.coords[1].1;
                let (pd, qd) = (p2 - p1, q2 - q1);

                alpha = match grab.mode {
                    GrabMode::PanFull => qd.complex_div(pd),
                    GrabMode::PanScale => DVec2((qd.sum_square() / pd.sum_square()).sqrt(), 0.0),
                    GrabMode::PanRotate => {
                        let a = qd.complex_div(pd);
                        a / a.sum_square().sqrt()
                    }
                    _ => unreachable!(),
                };

                // Average delta from both movements:
                delta = (q1 - alpha.complex_mul(p1) + q2 - alpha.complex_mul(p2)) * 0.5;
            }

            let id = grab.id.clone();
            if alpha != DVec2(1.0, 0.0) || delta != DVec2::ZERO {
                let event = Event::Pan { alpha, delta };
                mgr.send_event(widget, id, event);
            }
        }

        // Warning: infinite loops are possible here if widgets always queue a
        // new pending event when evaluating one of these:
        while let Some(item) = mgr.pending.pop_front() {
            log::trace!(target: "kas_core::event::manager", "update: handling Pending::{item:?}");
            let (id, event) = match item {
                Pending::SetNavFocus(id, key_focus) => (id, Event::NavFocus(key_focus)),
                Pending::MouseHover(id) => (id, Event::MouseHover),
                Pending::LostNavFocus(id) => (id, Event::LostNavFocus),
                Pending::LostMouseHover(id) => {
                    mgr.hover_icon = Default::default();
                    (id, Event::LostMouseHover)
                }
                Pending::LostCharFocus(id) => (id, Event::LostCharFocus),
                Pending::LostSelFocus(id) => (id, Event::LostSelFocus),
            };
            mgr.send_event(widget, id, event);
        }

        let action = mgr.action;
        drop(mgr);

        if self.hover_icon != old_hover_icon && self.mouse_grab.is_none() {
            shell.set_cursor_icon(self.hover_icon);
        }

        let action = action | self.action;
        self.action = TkAction::empty();
        action
    }

Divide by a second vector as if they are complex numbers

Examples found in repository?
src/event/manager/mgr_shell.rs (line 180)
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
    pub fn update(&mut self, shell: &mut dyn ShellWindow, widget: &mut dyn Widget) -> TkAction {
        let old_hover_icon = self.hover_icon;

        let mut mgr = EventMgr {
            state: self,
            shell,
            messages: vec![],
            scroll: Scroll::None,
            action: TkAction::empty(),
        };

        while let Some((parent, wid)) = mgr.popup_removed.pop() {
            mgr.send_event(widget, parent, Event::PopupRemoved(wid));
        }

        if let Some((id, event)) = mgr.mouse_grab().and_then(|g| g.flush_move()) {
            mgr.send_event(widget, id, event);
        }

        for i in 0..mgr.touch_grab.len() {
            if let Some((id, event)) = mgr.touch_grab[i].flush_move() {
                mgr.send_event(widget, id, event);
            }
        }

        for gi in 0..mgr.pan_grab.len() {
            let grab = &mut mgr.pan_grab[gi];
            debug_assert!(grab.mode != GrabMode::Grab);
            assert!(grab.n > 0);

            // Terminology: pi are old coordinates, qi are new coords
            let (p1, q1) = (DVec2::conv(grab.coords[0].0), DVec2::conv(grab.coords[0].1));
            grab.coords[0].0 = grab.coords[0].1;

            let alpha;
            let delta;

            if grab.mode == GrabMode::PanOnly || grab.n == 1 {
                alpha = DVec2(1.0, 0.0);
                delta = q1 - p1;
            } else {
                // We don't use more than two touches: information would be
                // redundant (although it could be averaged).
                let (p2, q2) = (DVec2::conv(grab.coords[1].0), DVec2::conv(grab.coords[1].1));
                grab.coords[1].0 = grab.coords[1].1;
                let (pd, qd) = (p2 - p1, q2 - q1);

                alpha = match grab.mode {
                    GrabMode::PanFull => qd.complex_div(pd),
                    GrabMode::PanScale => DVec2((qd.sum_square() / pd.sum_square()).sqrt(), 0.0),
                    GrabMode::PanRotate => {
                        let a = qd.complex_div(pd);
                        a / a.sum_square().sqrt()
                    }
                    _ => unreachable!(),
                };

                // Average delta from both movements:
                delta = (q1 - alpha.complex_mul(p1) + q2 - alpha.complex_mul(p2)) * 0.5;
            }

            let id = grab.id.clone();
            if alpha != DVec2(1.0, 0.0) || delta != DVec2::ZERO {
                let event = Event::Pan { alpha, delta };
                mgr.send_event(widget, id, event);
            }
        }

        // Warning: infinite loops are possible here if widgets always queue a
        // new pending event when evaluating one of these:
        while let Some(item) = mgr.pending.pop_front() {
            log::trace!(target: "kas_core::event::manager", "update: handling Pending::{item:?}");
            let (id, event) = match item {
                Pending::SetNavFocus(id, key_focus) => (id, Event::NavFocus(key_focus)),
                Pending::MouseHover(id) => (id, Event::MouseHover),
                Pending::LostNavFocus(id) => (id, Event::LostNavFocus),
                Pending::LostMouseHover(id) => {
                    mgr.hover_icon = Default::default();
                    (id, Event::LostMouseHover)
                }
                Pending::LostCharFocus(id) => (id, Event::LostCharFocus),
                Pending::LostSelFocus(id) => (id, Event::LostSelFocus),
            };
            mgr.send_event(widget, id, event);
        }

        let action = mgr.action;
        drop(mgr);

        if self.hover_icon != old_hover_icon && self.mouse_grab.is_none() {
            shell.set_cursor_icon(self.hover_icon);
        }

        let action = action | self.action;
        self.action = TkAction::empty();
        action
    }

Take the complex reciprocal

Return the sum of the terms

Return the sum of the square of the terms

Examples found in repository?
src/event/manager/mgr_shell.rs (line 181)
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
    pub fn update(&mut self, shell: &mut dyn ShellWindow, widget: &mut dyn Widget) -> TkAction {
        let old_hover_icon = self.hover_icon;

        let mut mgr = EventMgr {
            state: self,
            shell,
            messages: vec![],
            scroll: Scroll::None,
            action: TkAction::empty(),
        };

        while let Some((parent, wid)) = mgr.popup_removed.pop() {
            mgr.send_event(widget, parent, Event::PopupRemoved(wid));
        }

        if let Some((id, event)) = mgr.mouse_grab().and_then(|g| g.flush_move()) {
            mgr.send_event(widget, id, event);
        }

        for i in 0..mgr.touch_grab.len() {
            if let Some((id, event)) = mgr.touch_grab[i].flush_move() {
                mgr.send_event(widget, id, event);
            }
        }

        for gi in 0..mgr.pan_grab.len() {
            let grab = &mut mgr.pan_grab[gi];
            debug_assert!(grab.mode != GrabMode::Grab);
            assert!(grab.n > 0);

            // Terminology: pi are old coordinates, qi are new coords
            let (p1, q1) = (DVec2::conv(grab.coords[0].0), DVec2::conv(grab.coords[0].1));
            grab.coords[0].0 = grab.coords[0].1;

            let alpha;
            let delta;

            if grab.mode == GrabMode::PanOnly || grab.n == 1 {
                alpha = DVec2(1.0, 0.0);
                delta = q1 - p1;
            } else {
                // We don't use more than two touches: information would be
                // redundant (although it could be averaged).
                let (p2, q2) = (DVec2::conv(grab.coords[1].0), DVec2::conv(grab.coords[1].1));
                grab.coords[1].0 = grab.coords[1].1;
                let (pd, qd) = (p2 - p1, q2 - q1);

                alpha = match grab.mode {
                    GrabMode::PanFull => qd.complex_div(pd),
                    GrabMode::PanScale => DVec2((qd.sum_square() / pd.sum_square()).sqrt(), 0.0),
                    GrabMode::PanRotate => {
                        let a = qd.complex_div(pd);
                        a / a.sum_square().sqrt()
                    }
                    _ => unreachable!(),
                };

                // Average delta from both movements:
                delta = (q1 - alpha.complex_mul(p1) + q2 - alpha.complex_mul(p2)) * 0.5;
            }

            let id = grab.id.clone();
            if alpha != DVec2(1.0, 0.0) || delta != DVec2::ZERO {
                let event = Event::Pan { alpha, delta };
                mgr.send_event(widget, id, event);
            }
        }

        // Warning: infinite loops are possible here if widgets always queue a
        // new pending event when evaluating one of these:
        while let Some(item) = mgr.pending.pop_front() {
            log::trace!(target: "kas_core::event::manager", "update: handling Pending::{item:?}");
            let (id, event) = match item {
                Pending::SetNavFocus(id, key_focus) => (id, Event::NavFocus(key_focus)),
                Pending::MouseHover(id) => (id, Event::MouseHover),
                Pending::LostNavFocus(id) => (id, Event::LostNavFocus),
                Pending::LostMouseHover(id) => {
                    mgr.hover_icon = Default::default();
                    (id, Event::LostMouseHover)
                }
                Pending::LostCharFocus(id) => (id, Event::LostCharFocus),
                Pending::LostSelFocus(id) => (id, Event::LostSelFocus),
            };
            mgr.send_event(widget, id, event);
        }

        let action = mgr.action;
        drop(mgr);

        if self.hover_icon != old_hover_icon && self.mouse_grab.is_none() {
            shell.set_cursor_icon(self.hover_icon);
        }

        let action = action | self.action;
        self.action = TkAction::empty();
        action
    }

Extract one component, based on a direction

This merely extracts the horizontal or vertical component. It never negates it, even if the axis is reversed.

Trait Implementations§

The resulting type after applying the + operator.
Performs the + operation. Read more
The resulting type after applying the + operator.
Performs the + operation. Read more
Performs the += operation. Read more
Performs the += operation. Read more
Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Convert from T to Self Read more
Try converting from T to Self Read more
Try converting from T to Self Read more
Convert from T to Self Read more
Convert from T to Self Read more
Try converting from T to Self Read more
Try converting from T to Self Read more
Convert from T to Self Read more
Try converting from T to Self Read more
Convert from T to Self Read more
Try converting from T to Self, allowing approximation of value Read more
Converting from T to Self, allowing approximation of value Read more
Try converting from T to Self, allowing approximation of value Read more
Converting from T to Self, allowing approximation of value Read more
Try converting from T to Self, allowing approximation of value Read more
Converting from T to Self, allowing approximation of value Read more
Try converting from T to Self, allowing approximation of value Read more
Converting from T to Self, allowing approximation of value Read more
Try converting to integer with truncation Read more
Try converting to the nearest integer Read more
Try converting the floor to an integer Read more
Try convert the ceiling to an integer Read more
Convert to integer with truncatation Read more
Convert to the nearest integer Read more
Convert the floor to an integer Read more
Convert the ceiling to an integer Read more
Try converting to integer with truncation Read more
Try converting to the nearest integer Read more
Try converting the floor to an integer Read more
Try convert the ceiling to an integer Read more
Convert to integer with truncatation Read more
Convert to the nearest integer Read more
Convert the floor to an integer Read more
Convert the ceiling to an integer Read more
Try converting to integer with truncation Read more
Try converting to the nearest integer Read more
Try converting the floor to an integer Read more
Try convert the ceiling to an integer Read more
Convert to integer with truncatation Read more
Convert to the nearest integer Read more
Convert the floor to an integer Read more
Convert the ceiling to an integer Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Deserialize this value from the given Serde deserializer. Read more
The resulting type after applying the / operator.
Performs the / operation. Read more
The resulting type after applying the / operator.
Performs the / operation. Read more
The resulting type after applying the / operator.
Performs the / operation. Read more
Converts to this type from the input type.
Converts to this type from the input type.
The resulting type after applying the * operator.
Performs the * operation. Read more
The resulting type after applying the * operator.
Performs the * operation. Read more
The resulting type after applying the - operator.
Performs the unary - operation. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Serialize this value into the given Serde serializer. Read more
The resulting type after applying the - operator.
Performs the - operation. Read more
The resulting type after applying the - operator.
Performs the - operation. Read more
Performs the -= operation. Read more
Performs the -= operation. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Cast from Self to T Read more
Try converting from Self to T Read more
Try approximate conversion from Self to T Read more
Cast approximately from Self to T Read more
Cast to integer, truncating Read more
Cast to the nearest integer Read more
Cast the floor to an integer Read more
Cast the ceiling to an integer Read more
Try converting to integer with truncation Read more
Try converting to the nearest integer Read more
Try converting the floor to an integer Read more
Try convert the ceiling to an integer Read more
Try converting from T to Self, allowing approximation of value Read more
Converting from T to Self, allowing approximation of value Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.