mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Mkirk/perf 2 (#370)
* perf: return Line iterator rather than Vec avoids allocating vector memory, cleans up some call sites too.
This commit is contained in:
parent
d8910ad04f
commit
6025d89598
@ -177,12 +177,10 @@ impl PolyLine {
|
||||
self.pts
|
||||
}
|
||||
|
||||
// Makes a copy :\
|
||||
pub fn lines(&self) -> Vec<Line> {
|
||||
pub fn lines(&self) -> impl Iterator<Item = Line> + '_ {
|
||||
self.pts
|
||||
.windows(2)
|
||||
.map(|pair| Line::must_new(pair[0], pair[1]))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn length(&self) -> Distance {
|
||||
@ -212,7 +210,7 @@ impl PolyLine {
|
||||
let mut result: Vec<Pt2D> = Vec::new();
|
||||
let mut dist_so_far = Distance::ZERO;
|
||||
|
||||
for line in self.lines().iter() {
|
||||
for line in self.lines() {
|
||||
let length = line.length();
|
||||
|
||||
// Does this line contain the first point of the slice?
|
||||
@ -307,7 +305,7 @@ impl PolyLine {
|
||||
|
||||
let mut dist_left = dist_along;
|
||||
let mut length_remeasured = Distance::ZERO;
|
||||
for (idx, l) in self.lines().iter().enumerate() {
|
||||
for (idx, l) in self.lines().enumerate() {
|
||||
let length = l.length();
|
||||
length_remeasured += length;
|
||||
let epsilon = if idx == self.pts.len() - 2 {
|
||||
@ -624,23 +622,30 @@ impl PolyLine {
|
||||
assert_ne!(self, other);
|
||||
|
||||
// There could be several collisions. Pick the "first" from self's perspective.
|
||||
let mut closest_intersection: Option<(Pt2D, Angle)> = None;
|
||||
let mut closest_intersection_distance: Option<Distance> = None;
|
||||
|
||||
for l1 in self.lines() {
|
||||
let mut hits: Vec<(Pt2D, Angle)> = Vec::new();
|
||||
for l2 in other.lines() {
|
||||
if let Some(pt) = l1.intersection(&l2) {
|
||||
hits.push((pt, l1.angle()));
|
||||
if let Some(new_distance) = self.get_slice_ending_at(pt).map(|pl| pl.length()) {
|
||||
match closest_intersection_distance {
|
||||
None => {
|
||||
closest_intersection = Some((pt, l1.angle()));
|
||||
closest_intersection_distance = Some(new_distance);
|
||||
}
|
||||
Some(existing_distance) if existing_distance > new_distance => {
|
||||
closest_intersection = Some((pt, l1.angle()));
|
||||
closest_intersection_distance = Some(new_distance);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(hit) = hits.into_iter().min_by_key(|(pt, _)| {
|
||||
self.get_slice_ending_at(*pt)
|
||||
.map(|pl| pl.length())
|
||||
.unwrap_or(Distance::ZERO)
|
||||
}) {
|
||||
return Some(hit);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
||||
closest_intersection
|
||||
}
|
||||
|
||||
// TODO Also distance along
|
||||
@ -660,7 +665,7 @@ impl PolyLine {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(idx) = self.lines().iter().position(|l| l.contains_pt(pt)) {
|
||||
if let Some(idx) = self.lines().position(|l| l.contains_pt(pt)) {
|
||||
let mut pts = self.pts.clone();
|
||||
pts.truncate(idx + 1);
|
||||
// Make sure the last line isn't too tiny
|
||||
@ -683,7 +688,7 @@ impl PolyLine {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(idx) = self.lines().iter().position(|l| l.contains_pt(pt)) {
|
||||
if let Some(idx) = self.lines().position(|l| l.contains_pt(pt)) {
|
||||
let mut pts = self.pts.clone();
|
||||
pts = pts.split_off(idx + 1);
|
||||
if pt != pts[0] {
|
||||
@ -773,7 +778,7 @@ fn fix_angles(orig: &PolyLine, result: PolyLine) -> Result<PolyLine, String> {
|
||||
let mut pts = result.pts.clone();
|
||||
|
||||
// Check that the angles roughly match up between the original and shifted line
|
||||
for (idx, (orig_l, shifted_l)) in orig.lines().iter().zip(result.lines().iter()).enumerate() {
|
||||
for (idx, (orig_l, shifted_l)) in orig.lines().zip(result.lines()).enumerate() {
|
||||
let orig_angle = orig_l.angle();
|
||||
let shifted_angle = shifted_l.angle();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user