Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Fix polygon within algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
zmiao committed Feb 7, 2020
1 parent 93aa3db commit 2ccbd68
Show file tree
Hide file tree
Showing 8 changed files with 507 additions and 457 deletions.
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ commands:
command: |
platform/darwin/scripts/generate-style-code.js
platform/darwin/scripts/update-examples.js
git add -A && git diff --staged --exit-code
git add -A && git diff --staged --exit-code | tee nitpick.patch
config:
parameters:
config_params:
Expand Down
2 changes: 1 addition & 1 deletion mapbox-gl-js
Submodule mapbox-gl-js updated 0 files
834 changes: 418 additions & 416 deletions src/mbgl/programs/gl/shader_source.cpp

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions src/mbgl/programs/gl/symbol_icon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ struct ShaderSource;
template <>
struct ShaderSource<SymbolIconProgram> {
static constexpr const char* name = "symbol_icon";
static constexpr const uint8_t hash[8] = {0xa9, 0xd8, 0x73, 0xdf, 0xd9, 0xd8, 0x82, 0xf2};
static constexpr const uint8_t hash[8] = {0x17, 0x8a, 0xb9, 0xa4, 0x9d, 0xd2, 0xe1, 0x90};
static constexpr const auto vertexOffset = 50247;
static constexpr const auto fragmentOffset = 52996;
static constexpr const auto fragmentOffset = 53077;
};

constexpr const char* ShaderSource<SymbolIconProgram>::name;
Expand Down Expand Up @@ -142,6 +142,10 @@ void main() {
vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);
gl_Position = u_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * max(a_minFontScale, fontScale) + a_pxoffset / 16.0), 0.0, 1.0);
// Symbols might end up being behind the camera. Modify z-value to be out of visible bounds
// if this is the case, otherwise ignore depth. -1.1 is safely out of the visible depth range [-1, 1]
gl_Position.z = mix(-1.1 * gl_Position.w, gl_Position.z, float(projected_pos.w > 0.0));
v_tex = a_tex / u_texsize;
vec2 fade_opacity = unpack_opacity(a_fade_opacity);
float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
Expand Down
10 changes: 7 additions & 3 deletions src/mbgl/programs/gl/symbol_sdf_icon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ struct ShaderSource;
template <>
struct ShaderSource<SymbolSDFIconProgram> {
static constexpr const char* name = "symbol_sdf_icon";
static constexpr const uint8_t hash[8] = {0x46, 0xe9, 0x60, 0xde, 0x1e, 0x85, 0x36, 0x54};
static constexpr const auto vertexOffset = 53401;
static constexpr const auto fragmentOffset = 57441;
static constexpr const uint8_t hash[8] = {0x5a, 0xe9, 0x60, 0x5b, 0xb1, 0xc3, 0x2b, 0x3b};
static constexpr const auto vertexOffset = 53482;
static constexpr const auto fragmentOffset = 57603;
};

constexpr const char* ShaderSource<SymbolSDFIconProgram>::name;
Expand Down Expand Up @@ -217,6 +217,10 @@ void main() {
gl_Position = u_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale + a_pxoffset), 0.0, 1.0);
float gamma_scale = gl_Position.w;
// Symbols might end up being behind the camera. Modify z-value to be out of visible bounds
// if this is the case, otherwise ignore depth. -1.1 is safely out of the visible depth range [-1, 1]
gl_Position.z = mix(-1.1 * gl_Position.w, gl_Position.z, float(projected_pos.w > 0.0));
vec2 fade_opacity = unpack_opacity(a_fade_opacity);
float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
Expand Down
10 changes: 7 additions & 3 deletions src/mbgl/programs/gl/symbol_sdf_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ struct ShaderSource;
template <>
struct ShaderSource<SymbolSDFTextProgram> {
static constexpr const char* name = "symbol_sdf_text";
static constexpr const uint8_t hash[8] = {0x46, 0xe9, 0x60, 0xde, 0x1e, 0x85, 0x36, 0x54};
static constexpr const auto vertexOffset = 53401;
static constexpr const auto fragmentOffset = 57441;
static constexpr const uint8_t hash[8] = {0x5a, 0xe9, 0x60, 0x5b, 0xb1, 0xc3, 0x2b, 0x3b};
static constexpr const auto vertexOffset = 53482;
static constexpr const auto fragmentOffset = 57603;
};

constexpr const char* ShaderSource<SymbolSDFTextProgram>::name;
Expand Down Expand Up @@ -217,6 +217,10 @@ void main() {
gl_Position = u_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale + a_pxoffset), 0.0, 1.0);
float gamma_scale = gl_Position.w;
// Symbols might end up being behind the camera. Modify z-value to be out of visible bounds
// if this is the case, otherwise ignore depth. -1.1 is safely out of the visible depth range [-1, 1]
gl_Position.z = mix(-1.1 * gl_Position.w, gl_Position.z, float(projected_pos.w > 0.0));
vec2 fade_opacity = unpack_opacity(a_fade_opacity);
float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
Expand Down
4 changes: 2 additions & 2 deletions src/mbgl/programs/gl/symbol_text_and_icon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ template <>
struct ShaderSource<SymbolTextAndIconProgram> {
static constexpr const char* name = "symbol_text_and_icon";
static constexpr const uint8_t hash[8] = {0x7e, 0xbe, 0x72, 0x43, 0x55, 0x8e, 0xb5, 0xeb};
static constexpr const auto vertexOffset = 59277;
static constexpr const auto fragmentOffset = 63333;
static constexpr const auto vertexOffset = 59439;
static constexpr const auto fragmentOffset = 63495;
};

constexpr const char* ShaderSource<SymbolTextAndIconProgram>::name;
Expand Down
94 changes: 65 additions & 29 deletions src/mbgl/style/expression/within.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,65 @@
namespace mbgl {
namespace {

double isLeft(mbgl::Point<double> P0, mbgl::Point<double> P1, mbgl::Point<double> P2) {
return ((P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y));
class PolygonFeature : public GeometryTileFeature {
public:
const Feature& feature;
mutable optional<GeometryCollection> geometry;

PolygonFeature(const Feature& feature_) : feature(feature_) {}
PolygonFeature(const Feature& feature_, const CanonicalTileID& canonical) : feature(feature_) {
geometry = convertGeometry(feature.geometry, canonical);
geometry = fixupPolygons(*geometry);
}

FeatureType getType() const override { return FeatureType::Polygon; }
const PropertyMap& getProperties() const override { return feature.properties; }
FeatureIdentifier getID() const override { return feature.id; }
optional<mbgl::Value> getValue(const std::string& /*key*/) const override { return optional<mbgl::Value>(); }
const GeometryCollection& getGeometries() const override {
if (geometry) return *geometry;
geometry = GeometryCollection();
return *geometry;
}
};

bool rayIntersect(const mbgl::Point<double>& p, const mbgl::Point<double>& p1, const mbgl::Point<double>& p2) {
return ((p1.y > p.y) != (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x);
}

// winding number algorithm for checking if point inside a ploygon or not.
// http://geomalgorithms.com/a03-_inclusion.html#wn_PnPoly()
bool pointWithinPolygons(mbgl::Point<double> point, const mapbox::geometry::polygon<double>& polys) {
// wn = the winding number (=0 only when point is outside)
int wn = 0;
for (auto poly : polys) {
auto size = poly.size();
// ray casting algorithm for detecting if point is in polygon
bool pointWithinPolygon(const mbgl::Point<double>& point, const mapbox::geometry::polygon<double>& polygon) {
bool within = false;
for (auto ring : polygon) {
auto size = ring.size();
// loop through every edge of the polygon
for (decltype(size) i = 0; i < size - 1; ++i) {
if (poly[i].y <= point.y) {
if (poly[i + 1].y > point.y) { // upward horizontal crossing from point to edge E(poly[i], poly[i+1])
if (isLeft(poly[i], poly[i + 1], point) > 0) {
++wn;
}
}
} else {
if (poly[i + 1].y <= point.y) { // downward crossing
if (isLeft(poly[i], poly[i + 1], point) < 0) {
--wn;
}
}
if (rayIntersect(point, ring[i], ring[i + 1])) {
within = !within;
}
}
if (wn != 0) {
return true;
}
}
return wn != 0;
return within;
}

bool pointWithinPolygons(const mbgl::Point<double>& point, const mapbox::geometry::multi_polygon<double>& polygons) {
for (auto polygon : polygons) {
auto within = pointWithinPolygon(point, polygon);
if (within) return true;
}
return false;
}

bool pointsWithinPolygons(const mbgl::GeometryTileFeature& feature,
const mbgl::CanonicalTileID& canonical,
const mbgl::GeoJSON& geoJson) {
return geoJson.match(
[&feature, &canonical](const mapbox::geometry::geometry<double>& geometrySet) -> bool {
return geometrySet.match(
[&feature, &canonical](const mapbox::geometry::polygon<double>& polygons) -> bool {
mbgl::Feature f(geometrySet);
PolygonFeature polyFeature(f, canonical);
auto refinedGeoSet = convertGeometry(polyFeature, canonical);
return refinedGeoSet.match(
[&feature, &canonical](const mapbox::geometry::multi_polygon<double>& polygons) -> bool {
return convertGeometry(feature, canonical)
.match(
[&polygons](const mapbox::geometry::point<double>& point) -> bool {
Expand All @@ -71,6 +89,24 @@ bool pointsWithinPolygons(const mbgl::GeometryTileFeature& feature,
},
[](const auto&) -> bool { return false; });
},
[&feature, &canonical](const mapbox::geometry::polygon<double>& polygon) -> bool {
return convertGeometry(feature, canonical)
.match(
[&polygon](const mapbox::geometry::point<double>& point) -> bool {
return pointWithinPolygon(point, polygon);
},
[&polygon](const mapbox::geometry::multi_point<double>& points) -> bool {
auto result = false;
for (const auto& p : points) {
result = pointWithinPolygon(p, polygon);
if (!result) {
return result;
}
}
return result;
},
[](const auto&) -> bool { return false; });
},
[](const auto&) -> bool { return false; });
},
[](const auto&) -> bool { return false; });
Expand Down Expand Up @@ -116,7 +152,7 @@ EvaluationResult Within::evaluate(const EvaluationContext& params) const {
if (geometryType == FeatureType::Point) {
return pointsWithinPolygons(*params.feature, *params.canonical, geoJSONSource);
} else {
mbgl::Log::Warning(mbgl::Event::General, "Within expression currently only support 'Point' geometry type");
mbgl::Log::Warning(mbgl::Event::General, "within expression currently only support 'Point' geometry type");
}
return false;
}
Expand All @@ -125,7 +161,7 @@ ParseResult Within::parse(const Convertible& value, ParsingContext& ctx) {
if (isArray(value)) {
// object value, quoted with ["Within", value]
if (arrayLength(value) != 2) {
ctx.error("'Within' expression requires exactly one argument, but found " +
ctx.error("'within' expression requires exactly one argument, but found " +
util::toString(arrayLength(value) - 1) + " instead.");
return ParseResult();
}
Expand Down

0 comments on commit 2ccbd68

Please sign in to comment.