#include #include #include #include #include #include namespace mbgl { namespace style { void LineLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } bool LineLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) { // for scaling dasharrays PropertyEvaluationParameters dashArrayParams = parameters; dashArrayParams.z = std::floor(dashArrayParams.z); dashLineWidth = paint.evaluate(dashArrayParams); paint.evaluate(parameters); passes = (paint.evaluated.get().constantOr(1.0) > 0 && paint.evaluated.get().constantOr(Color::black()).a > 0 && paint.evaluated.get() > 0) ? RenderPass::Translucent : RenderPass::None; return paint.hasTransition(); } std::unique_ptr LineLayer::Impl::createBucket(const BucketParameters& parameters, const std::vector& layers) const { return std::make_unique(parameters, layers, layout); } float LineLayer::Impl::getLineWidth() const { float lineWidth = paint.evaluated.get(); float gapWidth = paint.evaluated.get().constantOr(0); if (gapWidth) { return gapWidth + 2 * lineWidth; } else { return lineWidth; } } optional offsetLine(const GeometryCollection& rings, const double offset) { if (offset == 0) return {}; GeometryCollection newRings; Point zero(0, 0); for (const auto& ring : rings) { newRings.emplace_back(); auto& newRing = newRings.back(); for (auto i = ring.begin(); i != ring.end(); i++) { auto& p = *i; Point aToB = i == ring.begin() ? zero : util::perp(util::unit(convertPoint(p - *(i - 1)))); Point bToC = i + 1 == ring.end() ? zero : util::perp(util::unit(convertPoint(*(i + 1) - p))); Point extrude = util::unit(aToB + bToC); const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y; extrude *= (1.0 / cosHalfAngle); newRing.push_back(convertPoint(extrude * offset) + p); } } return newRings; } float LineLayer::Impl::getQueryRadius() const { const std::array& translate = paint.evaluated.get(); auto offset = paint.evaluated.get().constantOr(LineOffset::defaultValue()); return getLineWidth() / 2.0 + std::abs(offset) + util::length(translate[0], translate[1]); } bool LineLayer::Impl::queryIntersectsGeometry( const GeometryCoordinates& queryGeometry, const GeometryCollection& geometry, const float bearing, const float pixelsToTileUnits) const { const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits; auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, paint.evaluated.get(), paint.evaluated.get(), bearing, pixelsToTileUnits); auto offset = paint.evaluated.get().constantOr(LineOffset::defaultValue()); auto offsetGeometry = offsetLine(geometry, offset * pixelsToTileUnits); return util::polygonIntersectsBufferedMultiLine( translatedQueryGeometry.value_or(queryGeometry), offsetGeometry.value_or(geometry), halfWidth); } } // namespace style } // namespace mbgl