| 105 | } |
| 106 | |
| 107 | Result<std::vector<std::vector<glm::dvec3>>> parsePolygon( |
| 108 | const rapidjson::Value::ConstArray& arr, |
| 109 | const std::string& name, |
| 110 | uint32_t minItems, |
| 111 | bool mustBeClosed) { |
| 112 | ErrorList error; |
| 113 | std::vector<std::vector<glm::dvec3>> rings; |
| 114 | rings.reserve(arr.Size()); |
| 115 | for (auto& value : arr) { |
| 116 | if (!value.IsArray()) { |
| 117 | return Result<std::vector<std::vector<glm::dvec3>>>(ErrorList::error( |
| 118 | name + " 'coordinates' member must be an array of position arrays.")); |
| 119 | } |
| 120 | |
| 121 | Result<std::vector<glm::dvec3>> pointsResult = |
| 122 | parsePositionArray(value.GetArray()); |
| 123 | if (!pointsResult.value) { |
| 124 | return Result<std::vector<std::vector<glm::dvec3>>>( |
| 125 | std::move(pointsResult.errors)); |
| 126 | } else if (pointsResult.value->size() < minItems) { |
| 127 | return Result<std::vector<std::vector<glm::dvec3>>>( |
| 128 | ErrorList::error(fmt::format( |
| 129 | "{} 'coordinates' member must be an array of " |
| 130 | "arrays of {} or more positions.", |
| 131 | name, |
| 132 | minItems))); |
| 133 | } |
| 134 | |
| 135 | std::vector<glm::dvec3>& points = *pointsResult.value; |
| 136 | |
| 137 | if (mustBeClosed && |
| 138 | (*pointsResult.value)[0] != |
| 139 | (*pointsResult.value)[pointsResult.value->size() - 1]) { |
| 140 | error.emplaceWarning(fmt::format( |
| 141 | "{} 'coordinates' member can only contain closed rings, requiring " |
| 142 | "the first and last coordinates of each ring to have identical " |
| 143 | "values. The first position has been duplicated to make a valid " |
| 144 | "closed ring.", |
| 145 | name, |
| 146 | minItems)); |
| 147 | points.emplace_back(points[0]); |
| 148 | } |
| 149 | |
| 150 | rings.emplace_back(std::move(points)); |
| 151 | } |
| 152 | |
| 153 | return Result<std::vector<std::vector<glm::dvec3>>>( |
| 154 | std::move(rings), |
| 155 | std::move(error)); |
| 156 | } |
| 157 | |
| 158 | Result<std::optional<AxisAlignedBox>> |
| 159 | parseBoundingBox(const rapidjson::Value& value) { |
no test coverage detected