Skip to content

Commit

Permalink
Add WalkDistance function and create Polyline Files
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 686513245
  • Loading branch information
Ink Open Source authored and copybara-github committed Oct 16, 2024
1 parent b2a67ed commit 3dd736c
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
24 changes: 24 additions & 0 deletions ink/geometry/internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,30 @@ cc_library(
],
)

cc_library(
name = "polyline_processing",
srcs = ["polyline_processing.cc"],
hdrs = ["polyline_processing.h"],
deps = [
"//ink/geometry:distance",
"//ink/geometry:point",
"//ink/geometry:segment",
"@com_google_absl//absl/types:span",
],
)

cc_test(
name = "polyline_processing_test",
srcs = ["polyline_processing_test.cc"],
deps = [
":polyline_processing",
"//ink/geometry:point",
"//ink/geometry:segment",
"//ink/geometry:type_matchers",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "circle_test",
srcs = ["circle_test.cc"],
Expand Down
57 changes: 57 additions & 0 deletions ink/geometry/internal/polyline_processing.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ink/geometry/internal/polyline_processing.h"

#include <vector>

#include "absl/types/span.h"
#include "ink/geometry/distance.h"
#include "ink/geometry/point.h"
#include "ink/geometry/segment.h"

namespace ink::geometry_internal {

float WalkDistance(PolylineData& polyline, int index, float fractional_index,
bool walk_backwards) {
int start_idx;
int end_idx;
if (walk_backwards) {
fractional_index = 1.0 - fractional_index;
start_idx = index + 1;
end_idx = polyline.segments.size();
} else {
start_idx = 0;
end_idx = index;
}

float total_distance = polyline.segments[index].length * fractional_index;
for (int i = start_idx; i < end_idx; ++i) {
total_distance += polyline.segments[i].length;
}
return total_distance;
}

PolylineData CreateNewPolylineData(absl::Span<const Point> points) {
PolylineData polyline;
polyline.segments.reserve(points.size() - 1);
for (int i = 0; i < static_cast<int>(points.size()) - 1; ++i) {
polyline.segments.push_back(
SegmentBundle{Segment{points[i], points[i + 1]}, i,
Distance(points[i], points[i + 1])});
}
return polyline;
}

} // namespace ink::geometry_internal
62 changes: 62 additions & 0 deletions ink/geometry/internal/polyline_processing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef INK_GEOMETRY_INTERNAL_POLYLINE_PROCESSING_H_
#define INK_GEOMETRY_INTERNAL_POLYLINE_PROCESSING_H_

#include <stdbool.h>

#include <vector>

#include "absl/types/span.h"
#include "ink/geometry/point.h"
#include "ink/geometry/segment.h"

namespace ink::geometry_internal {

struct SegmentBundle {
Segment segment;
int index;
float length;
};

struct Intersection {
int index_int;
float index_fraction;
float walk_distance;
};

struct PolylineData {
std::vector<SegmentBundle> segments;
Intersection first_intersection;
Intersection last_intersection;
Point new_first_point;
Point new_last_point;
bool connect_first = false;
bool connect_last = false;
bool has_intersection = false;
float min_walk_distance;
float max_connection_distance;
float min_connection_ratio;
float min_trimming_ratio;
};

PolylineData CreateNewPolylineData(absl::Span<const Point> points);

float WalkDistance(PolylineData& polyline, int index, float fractional_index,
bool walk_backwards);

} // namespace ink::geometry_internal

#endif // INK_GEOMETRY_INTERNAL_POLYLINE_PROCESSING_H_
89 changes: 89 additions & 0 deletions ink/geometry/internal/polyline_processing_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "ink/geometry/internal/polyline_processing.h"

#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ink/geometry/point.h"
#include "ink/geometry/segment.h"
#include "ink/geometry/type_matchers.h"

namespace ink::geometry_internal {

namespace {

PolylineData CreateWalkingPolylineData() {
std::vector<Point> walking_points = {
Point{3, 3}, Point{3, 10}, Point{3, 20}, Point{10, 20},
Point{10, 15}, Point{5, 15}, Point{5, 0}, Point{2, 0}};
// Individual Segment lengths: 7, 10, 7, 5, 5, 15, 3
return CreateNewPolylineData(walking_points);
}

TEST(PolylineProcessingTest, WalkDistanceReturnsCorrectValuesAtEndPoints) {
PolylineData walking_polyline = CreateWalkingPolylineData();
EXPECT_EQ(WalkDistance(walking_polyline, 0, 0.0f, false), 0.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 6, 1.0f, true), 0.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 0, 0.0f, true), 52.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 6, 1.0f, false), 52.0f);
}

TEST(PolylineProcessingTest, WalkDistanceReturnsCorrectValuesAtMidPoints) {
PolylineData walking_polyline = CreateWalkingPolylineData();
EXPECT_EQ(WalkDistance(walking_polyline, 0, 0.5f, false), 3.5f);
EXPECT_EQ(WalkDistance(walking_polyline, 0, 0.5f, true), 48.5f);

EXPECT_EQ(WalkDistance(walking_polyline, 1, 0.4f, false), 11.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 1, 0.4f, true), 41.0f);

EXPECT_EQ(WalkDistance(walking_polyline, 5, 0.6f, false), 43.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 5, 0.6f, true), 9.0f);

EXPECT_EQ(WalkDistance(walking_polyline, 6, 0.5f, false), 50.5f);
EXPECT_EQ(WalkDistance(walking_polyline, 6, 0.5f, true), 1.5f);
}

TEST(PolylineProcessingTest,
WalkDistanceReturnsEqualValuesForEquivalentIndices) {
PolylineData walking_polyline = CreateWalkingPolylineData();
EXPECT_EQ(WalkDistance(walking_polyline, 2, 1.0f, false), 24.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 2, 1.0f, true), 28.0f);

EXPECT_EQ(WalkDistance(walking_polyline, 3, 0.0f, false), 24.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 3, 0.0f, true), 28.0f);
}

TEST(PolylineProcessingTest, WalkDistanceReturnsEqualValuesAtMidpoint) {
PolylineData walking_polyline = CreateWalkingPolylineData();
EXPECT_EQ(WalkDistance(walking_polyline, 3, 0.4f, false), 26.0f);
EXPECT_EQ(WalkDistance(walking_polyline, 3, 0.4f, true), 26.0f);
}

TEST(PolylineProcessingTest,
CreateNewPolylineDataCreatesCorrectSegmentBundles) {
PolylineData walking_polyline = CreateWalkingPolylineData();
EXPECT_EQ(walking_polyline.segments.size(), 7);

EXPECT_EQ(walking_polyline.segments[0].index, 0);
EXPECT_EQ(walking_polyline.segments[0].length, 7);
EXPECT_THAT(walking_polyline.segments[0].segment,
SegmentEq(Segment{{3, 3}, {3, 10}}));

EXPECT_EQ(walking_polyline.segments[3].index, 3);
EXPECT_EQ(walking_polyline.segments[3].length, 5);
EXPECT_THAT(walking_polyline.segments[3].segment,
SegmentEq(Segment{{10, 20}, {10, 15}}));

EXPECT_EQ(walking_polyline.segments[5].index, 5);
EXPECT_EQ(walking_polyline.segments[5].length, 15);
EXPECT_THAT(walking_polyline.segments[5].segment,
SegmentEq(Segment{{5, 15}, {5, 0}}));

EXPECT_EQ(walking_polyline.segments[6].index, 6);
EXPECT_EQ(walking_polyline.segments[6].length, 3);
EXPECT_THAT(walking_polyline.segments[6].segment,
SegmentEq(Segment{{5, 0}, {2, 0}}));
}

} // namespace
} // namespace ink::geometry_internal

0 comments on commit 3dd736c

Please sign in to comment.