Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mapnik::util::is_clockwise - translate coordinates relative to the or…
…igin (0,0) to avoid numeric precision issues while using double precision. (ref #3402)
- Loading branch information
Showing
2 changed files
with
37 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,18 +23,27 @@ | |
#ifndef MAPNIK_UTIL_IS_CLOCKWISE_HPP | ||
#define MAPNIK_UTIL_IS_CLOCKWISE_HPP | ||
|
||
#include <cassert> | ||
|
||
namespace mapnik { namespace util { | ||
|
||
template <typename T> | ||
bool is_clockwise(T const& ring) | ||
{ | ||
double area = 0.0; | ||
std::size_t num_points = ring.size(); | ||
assert(num_point > 2); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
flippmoke
Member
|
||
double orig_x = ring[0].x; | ||
double orig_y = ring[0].y; | ||
for (std::size_t i = 0; i < num_points; ++i) | ||
{ | ||
auto const& p0 = ring[i]; | ||
auto const& p1 = ring[(i + 1) % num_points]; | ||
area += p0.x * p1.y - p0.y * p1.x; | ||
double x0 = p0.x - orig_x; | ||
double y0 = p0.y - orig_y; | ||
double x1 = p1.x - orig_x; | ||
double y1 = p1.y - orig_y; | ||
area += x0 * y1 - x1 * y0; | ||
} | ||
return (area < 0.0) ? true : false; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include "catch.hpp" | ||
|
||
#include <mapnik/geometry.hpp> | ||
#include <mapnik/util/is_clockwise.hpp> | ||
|
||
TEST_CASE("Ring is_clockwise") { | ||
|
||
// Input is rather thin triangle to test precision issues aren't getting in the way. | ||
SECTION("Clockwise") | ||
{ | ||
mapnik::geometry::linear_ring<double> ring; | ||
ring.emplace_back(-13499697.0366658326, 4698431.85179749783); | ||
ring.emplace_back(-13499697.1113113686, 4698431.85179749783); | ||
ring.emplace_back(-13499697.0366658326, 4698431.92644303292); | ||
ring.emplace_back(-13499697.0366658326, 4698431.85179749783); | ||
REQUIRE(mapnik::util::is_clockwise(ring) == true); | ||
} | ||
SECTION("Anti-Clockwise") | ||
{ | ||
mapnik::geometry::linear_ring<double> ring; | ||
ring.emplace_back(-13499697.0366658326, 4698431.85179749783); | ||
ring.emplace_back(-13499697.0366658326, 4698431.92644303292); | ||
ring.emplace_back(-13499697.1113113686, 4698431.85179749783); | ||
ring.emplace_back(-13499697.0366658326, 4698431.85179749783); | ||
REQUIRE(mapnik::util::is_clockwise(ring) == false); | ||
} | ||
} |
@artemp how about returning
false
ifnum_points < 3
?