Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CesiumUtility/include/CesiumUtility/Color.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ struct Color {
* 0xAARRGGBB.
*/
uint32_t toRgba32() const;

bool operator==(const Color& rhs) const;
};
} // namespace CesiumUtility
4 changes: 4 additions & 0 deletions CesiumUtility/src/Color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ uint32_t Color::toRgba32() const {

Color::Color(uint8_t r_, uint8_t g_, uint8_t b_, uint8_t a_)
: r(r_), g(g_), b(b_), a(a_) {}
bool Color::operator==(const Color& rhs) const {
return this->r == rhs.r && this->g == rhs.g && this->b == rhs.b &&
this->a == rhs.a;
}
} // namespace CesiumUtility
10 changes: 10 additions & 0 deletions CesiumVectorData/include/CesiumVectorData/VectorRasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ class VectorRasterizer {
const std::vector<CesiumGeospatial::Cartographic>& points,
const PointStyle& style);

/**
* @brief Draws a set of points to the canvas.
*
* @param points The set of points to draw.
* @param style The @ref PointStyle to use when drawing the points.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param style The @ref PointStyle to use when drawing the points.
* @param styles The @ref PointStyle instances to use when drawing the points.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it seems like styles.size() must equal points.size(), where style[i] is applied to points[i]. Perhaps we should call it out here.

*/
void drawPoints(
const std::vector<CesiumGeospatial::Cartographic>& points,
const std::vector<const CesiumVectorData::VectorStyle*>& styles);

/**
* @brief Rasterizes a `GeoJsonObject` to the canvas.
*
Expand Down
58 changes: 57 additions & 1 deletion CesiumVectorData/include/CesiumVectorData/VectorStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <CesiumUtility/Color.h>

#include <functional>
#include <optional>

namespace CesiumVectorData {
Expand Down Expand Up @@ -46,6 +47,9 @@ struct ColorStyle {
* a given seed, but nearby seeds will not usually return nearby colors.
*/
CesiumUtility::Color getColor(size_t randomColorSeed = 0) const;

/** @brief Checks if two ColorStyle instances are equal. */
bool operator==(const ColorStyle& rhs) const;
};

/** @brief The mode to use when interpreting a given line width. */
Expand Down Expand Up @@ -78,6 +82,9 @@ struct LineStyle : public ColorStyle {
* @brief The mode to use when interpreting `width`.
*/
LineWidthMode widthMode = LineWidthMode::Pixels;

/** @brief Checks if two LineStyle instances are equal. */
bool operator==(const LineStyle& rhs) const;
};

/** @brief The style used to draw a Polygon. */
Expand All @@ -92,6 +99,9 @@ struct PolygonStyle {
* polygon will not be outlined.
*/
std::optional<LineStyle> outline;

/** @brief Checks if two PolygonStyle instances are equal. */
bool operator==(const PolygonStyle& rhs) const;
};

/** @brief The style used to draw a point. */
Expand All @@ -108,6 +118,9 @@ struct PointStyle {
* point will not be outlined.
*/
std::optional<LineStyle> outline;

/** @brief Checks if two PointStyle instances are equal. */
bool operator==(const PointStyle& rhs) const;
};

/**
Expand Down Expand Up @@ -149,5 +162,48 @@ struct VectorStyle {
* @brief Initializes all styles to the given color.
*/
VectorStyle(const CesiumUtility::Color& color);

/** @brief Checks if two VectorStyle instances are equal. */
bool operator==(const VectorStyle& rhs) const;
};
} // namespace CesiumVectorData

/** @brief Hash implementation for \ref CesiumVectorData::ColorStyle. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer @ref according to the style guide, and apply this to the other instances of \ref in this doc too.

Suggested change
/** @brief Hash implementation for \ref CesiumVectorData::ColorStyle. */
/** @brief Hash implementation for @ref CesiumVectorData::ColorStyle. */

template <> struct std::hash<CesiumVectorData::ColorStyle> {
/** @brief Returns a `size_t` hash of the provided \ref
* CesiumVectorData::ColorStyle instance. */
std::size_t
operator()(const CesiumVectorData::ColorStyle& style) const noexcept;
};
} // namespace CesiumVectorData

/** @brief Hash implementation for \ref CesiumVectorData::LineStyle. */
template <> struct std::hash<CesiumVectorData::LineStyle> {
/** @brief Returns a `size_t` hash of the provided \ref
* CesiumVectorData::LineStyle instance. */
std::size_t
operator()(const CesiumVectorData::LineStyle& style) const noexcept;
};

/** @brief Hash implementation for \ref CesiumVectorData::PolygonStyle. */
template <> struct std::hash<CesiumVectorData::PolygonStyle> {
/** @brief Returns a `size_t` hash of the provided \ref
* CesiumVectorData::PolygonStyle instance. */
std::size_t
operator()(const CesiumVectorData::PolygonStyle& style) const noexcept;
};

/** @brief Hash implementation for \ref CesiumVectorData::PointStyle. */
template <> struct std::hash<CesiumVectorData::PointStyle> {
/** @brief Returns a `size_t` hash of the provided \ref
* CesiumVectorData::PointStyle instance. */
std::size_t
operator()(const CesiumVectorData::PointStyle& style) const noexcept;
};

/** @brief Hash implementation for \ref CesiumVectorData::VectorStyle. */
template <> struct std::hash<CesiumVectorData::VectorStyle> {
/** @brief Returns a `size_t` hash of the provided \ref
* CesiumVectorData::VectorStyle instance. */
std::size_t
operator()(const CesiumVectorData::VectorStyle& style) const noexcept;
};
37 changes: 37 additions & 0 deletions CesiumVectorData/src/VectorRasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,43 @@ void VectorRasterizer::drawPoints(
style);
}

void VectorRasterizer::drawPoints(
const std::vector<CesiumGeospatial::Cartographic>& points,
const std::vector<const CesiumVectorData::VectorStyle*>& styles) {
if (this->_finalized) {
return;
}

for (size_t i = 0; i < points.size(); i++) {
BLPoint point = radiansToPoint(
points[i].longitude,
points[i].latitude,
this->_bounds,
this->_context);
// clang-tidy does not understand that we *are* in fact checking these
// optionals
if (styles[i]->point.fill) {
Comment on lines +399 to +413

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like there's some assumptions here:

  • styles.size() == points.size()
  • styles[i] != nullptr for all i
  • styles[i].point.hasValue()

We should add if statements to guard for these, or at least add asserts.

// NOLINTBEGIN(bugprone-unchecked-optional-access)
this->_context.fillCircle(
BLCircle(point.x, point.y, styles[i]->point.radius),
BLRgba32(styles[i]
->point.fill->getColor(seedForObject(points[i], 17))
.toRgba32()));
// NOLINTEND(bugprone-unchecked-optional-access)
}

if (styles[i]->point.outline) {
// NOLINTBEGIN(bugprone-unchecked-optional-access)
this->_context.strokeCircle(
BLCircle(point.x, point.y, styles[i]->point.radius),
BLRgba32(styles[i]
->point.outline->getColor(seedForObject(points[i], 31))
.toRgba32()));
// NOLINTEND(bugprone-unchecked-optional-access)
}
}
}

void VectorRasterizer::drawGeoJsonObject(
const GeoJsonObject& geoJsonObject,
const VectorStyle& style) {
Expand Down
79 changes: 78 additions & 1 deletion CesiumVectorData/src/VectorStyle.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <CesiumUtility/Color.h>
#include <CesiumUtility/Hash.h>
#include <CesiumVectorData/VectorStyle.h>

#include <cstddef>
Expand Down Expand Up @@ -38,4 +39,80 @@ VectorStyle::VectorStyle(
const PolygonStyle& polygonStyle,
const PointStyle& pointStyle)
: line(lineStyle), polygon(polygonStyle), point(pointStyle) {}
} // namespace CesiumVectorData

bool ColorStyle::operator==(const ColorStyle& rhs) const {
return this->color == rhs.color && this->colorMode == rhs.colorMode;
}

bool LineStyle::operator==(const LineStyle& rhs) const {
return this->width == rhs.width && this->widthMode == rhs.widthMode &&
this->color == rhs.color && this->colorMode == rhs.colorMode;
}

bool PolygonStyle::operator==(const PolygonStyle& rhs) const {
return this->fill == rhs.fill && this->outline == rhs.outline;
}

bool PointStyle::operator==(const PointStyle& rhs) const {
return this->radius == rhs.radius && this->fill == rhs.fill &&
this->outline == rhs.outline;
}
bool VectorStyle::operator==(const VectorStyle& rhs) const {
return this->line == rhs.line && this->polygon == rhs.polygon &&
this->point == rhs.point;
}
} // namespace CesiumVectorData

std::size_t std::hash<CesiumVectorData::ColorStyle>::operator()(
const CesiumVectorData::ColorStyle& style) const noexcept {
std::size_t result = std::hash<uint32_t>{}(style.color.toRgba32());
result = CesiumUtility::Hash::combine(
result,
std::hash<uint8_t>{}(static_cast<uint8_t>(style.colorMode)));
return result;
}

std::size_t std::hash<CesiumVectorData::LineStyle>::operator()(
const CesiumVectorData::LineStyle& style) const noexcept {
std::size_t result = std::hash<CesiumVectorData::ColorStyle>{}(style);
result =
CesiumUtility::Hash::combine(result, std::hash<double>{}(style.width));
result = CesiumUtility::Hash::combine(
result,
std::hash<uint8_t>{}(static_cast<uint8_t>(style.widthMode)));
return result;
}

std::size_t std::hash<CesiumVectorData::PolygonStyle>::operator()(
const CesiumVectorData::PolygonStyle& style) const noexcept {
std::size_t result =
std::hash<std::optional<CesiumVectorData::ColorStyle>>{}(style.fill);
result = CesiumUtility::Hash::combine(
result,
std::hash<std::optional<CesiumVectorData::LineStyle>>{}(style.outline));
return result;
}

std::size_t std::hash<CesiumVectorData::PointStyle>::operator()(
const CesiumVectorData::PointStyle& style) const noexcept {
std::size_t result =
std::hash<std::optional<CesiumVectorData::ColorStyle>>{}(style.fill);
result = CesiumUtility::Hash::combine(
result,
std::hash<std::optional<CesiumVectorData::LineStyle>>{}(style.outline));
result =
CesiumUtility::Hash::combine(result, std::hash<double>{}(style.radius));
return result;
}

std::size_t std::hash<CesiumVectorData::VectorStyle>::operator()(
const CesiumVectorData::VectorStyle& style) const noexcept {
std::size_t result = std::hash<CesiumVectorData::LineStyle>{}(style.line);
result = CesiumUtility::Hash::combine(
result,
std::hash<CesiumVectorData::PolygonStyle>{}(style.polygon));
result = CesiumUtility::Hash::combine(
result,
std::hash<CesiumVectorData::PointStyle>{}(style.point));
return result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#include "Library.h"

#include <CesiumAsync/AsyncSystem.h>
#include <CesiumAsync/Future.h>
#include <CesiumGeospatial/Cartographic.h>
#include <CesiumGltf/Model.h>
#include <CesiumVectorData/VectorStyle.h>

namespace CesiumVectorOverlays {

/**
* @brief An interface for providing styling information for vector features.
*/
class CESIUMVECTOROVERLAYS_API VectorStylingProvider {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a unit test for this, to confirm that a simple style can be successfully applied?

public:
/**
* @brief Styles a set of point features.
*
* @param asyncSystem The async system.
* @param model The glTF model containing the features and metadata
* information.
* @param featureIds The feature IDs of the points to style.
* @param points The geometry of the points to style. This will be the same
* size as `featureIds`, and each point corresponds to the feature ID at the
* same index.
* @returns A future that resolves to a vector of optional VectorStyle
* objects, one for each point feature. The vector should be the same size as
* `featureIds and `points`. If `std::nullopt` is provided for a feature, the
* feature will use the default style. If the returned vector is empty or does
* not match the size of `featureIds` and `points`, the default style will be
* used for all features.
*/
virtual CesiumAsync::Future<
std::vector<std::optional<CesiumVectorData::VectorStyle>>>
onStylePoints(
const CesiumAsync::AsyncSystem& asyncSystem,
const CesiumGltf::Model& model,
const std::vector<int64_t>& featureIds,
const std::vector<CesiumGeospatial::Cartographic>& points) = 0;

/**
* @brief Styles a set of polyline features.
*
* @param asyncSystem The async system.
* @param model The glTF model containing the features and metadata
* information.
* @param featureIds The feature IDs of the polylines to style.
* @param polylines The geometry of the polylines to style. This will be the
* same size as `featureIds`, and each polyline corresponds to the feature ID
* at the same index.
* @returns A future that resolves to a vector of optional VectorStyle
* objects, one for each polyline feature. The vector should be the same size
* as `featureIds` and `polylines`. If `std::nullopt` is provided for a
* feature, the feature will use the default style. If the returned vector is
* empty or does not match the size of `featureIds` and `polylines`, the
* default style will be used for all features.
*/
virtual CesiumAsync::Future<
std::vector<std::optional<CesiumVectorData::VectorStyle>>>
onStylePolylines(
const CesiumAsync::AsyncSystem& asyncSystem,
const CesiumGltf::Model& model,
const std::vector<int64_t>& featureIds,
const std::vector<std::vector<CesiumGeospatial::Cartographic>>&
polylines) = 0;

/**
* @brief Styles a set of polygon features.
*
* @param asyncSystem The async system.
* @param model The glTF model containing the features and metadata
* information.
* @param featureIds The feature IDs of the polygons to style.
* @param polygons The geometry of the polygons to style. This will be the
* same size as `featureIds`, and each polygon corresponds to the feature ID
* at the same index.
* @returns A future that resolves to a vector of optional VectorStyle
* objects, one for each polygon feature. The vector should be the same size
* as `featureIds` and `polygons`. If `std::nullopt` is provided for a
* feature, the feature will use the default style. If the returned vector is
* empty or does not match the size of `featureIds` and `polygons`, the
* default style will be used for all features.
*/
virtual CesiumAsync::Future<
std::vector<std::optional<CesiumVectorData::VectorStyle>>>
onStylePolygons(
const CesiumAsync::AsyncSystem& asyncSystem,
const CesiumGltf::Model& model,
const std::vector<int64_t>& featureIds,
const std::vector<std::vector<CesiumGeospatial::Cartographic>>&
polygons) = 0;
};

} // namespace CesiumVectorOverlays
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <CesiumAsync/IAssetAccessor.h>
#include <CesiumRasterOverlays/RasterOverlay.h>
#include <CesiumVectorData/VectorStyle.h>
#include <CesiumVectorOverlays/VectorStylingProvider.h>

namespace CesiumVectorOverlays {

Expand All @@ -19,6 +20,13 @@ struct VectorTilesRasterOverlayOptions {
* @brief HTTP headers to attach to requests made for this tileset.
*/
std::vector<CesiumAsync::IAssetAccessor::THeader> requestHeaders;

/**
* @brief An optional provider for styling information for features in the
* vector tileset. If not provided, the default style will be used for all
* features.
*/
std::shared_ptr<VectorStylingProvider> pStylingProvider;
};

/**
Expand Down
Loading
Loading