#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() > 0 && paint.evaluated.get().a > 0 && paint.evaluated.get() > 0) ? RenderPass::Translucent : RenderPass::None; return paint.hasTransition(); } std::unique_ptr LineLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const { auto bucket = std::make_unique(parameters.tileID.overscaleFactor()); bucket->layout = layout.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ)); auto& name = bucketName(); parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) { auto geometries = feature.getGeometries(); bucket->addGeometry(geometries); parameters.featureIndex.insert(geometries, index, layerName, name); }); return std::move(bucket); } float LineLayer::Impl::getLineWidth() const { if (paint.evaluated.get() > 0) { return paint.evaluated.get() + 2 * paint.evaluated.get(); } else { return paint.evaluated.get(); } } 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(); return getLineWidth() / 2.0 + std::abs(paint.evaluated.get()) + 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 offsetGeometry = offsetLine(geometry, paint.evaluated.get() * pixelsToTileUnits); return util::polygonIntersectsBufferedMultiLine( translatedQueryGeometry.value_or(queryGeometry), offsetGeometry.value_or(geometry), halfWidth); } } // namespace style } // namespace mbgl