MCPcopy Create free account
hub / github.com/OpenOrienteering/mapper / simplify

Method simplify

src/core/objects/object.cpp:2231–2438  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2229}
2230
2231bool PathObject::simplify(PathObject** undo_duplicate, double threshold)
2232{
2233 // A copy for reference and undo while this is modified.
2234 QScopedPointer<PathObject> original(new PathObject(*this));
2235
2236 // original_indices provides a mapping from this object's indices to the
2237 // equivalent original object indices in order to extract the relevant
2238 // parts of the original object later for cost calculation.
2239 // Note: curve handle indices may become incorrect, we don't need them.
2240 std::vector<MapCoordVector::size_type> original_indices;
2241 original_indices.resize(coords.size());
2242 for (std::size_t i = 0, end = coords.size(); i < end; ++i)
2243 original_indices[i] = i;
2244
2245 // A high value indicating an cost of deletion which is unknown.
2246 auto const undetermined_cost = std::numeric_limits<double>::max();
2247
2248 // This vector provides the costs of deleting individual nodes.
2249 std::vector<double> costs;
2250 costs.resize(coords.size(), undetermined_cost);
2251
2252 // The empty LineSymbol will not generate any renderables,
2253 // thus reducing the cost of update().
2254 // The temp object will be reused (but not reallocated) many times.
2255 LineSymbol empty_symbol;
2256 PathObject temp { &empty_symbol };
2257 temp.coords.reserve(10); // enough for two bezier edges.
2258
2259 for (auto part = path_parts.rbegin(); part != path_parts.rend(); ++part)
2260 {
2261 // Don't simplify parts which would get deleted.
2262 MapCoordVector::size_type minimum_part_size = part->isClosed() ? 4 : 3;
2263 auto minimumPartSizeReached = [&part, minimum_part_size]() -> bool
2264 {
2265 return (part->size() <= 7 && part->countRegularNodes() < minimum_part_size);
2266 };
2267
2268 auto minimum_cost_step = threshold / qMax(std::log2(part->size() / 64.0), 4.0);
2269 auto minimum_cost = 0.0;
2270
2271 // Delete nodes in max n runs (where n = max. part.end_index - part.start_index)
2272 for (auto run = part->last_index; run > part->first_index; --run)
2273 {
2274 if (minimumPartSizeReached())
2275 break;
2276
2277 // Determine the costs of node deletion
2278 {
2279 auto extract_start = part->first_index;
2280 auto index = part->nextCoordIndex(extract_start);
2281 while (index < part->last_index)
2282 {
2283 auto extract_end = part->nextCoordIndex(index);
2284 if (costs[index] == undetermined_cost)
2285 {
2286 temp.assignCoordinates(*this, extract_start, extract_end);
2287 temp.deleteCoordinate(index - extract_start, true, Settings::DeleteBezierPoint_RetainExistingShape);
2288 // Debug check: start and end coords of the extracts should be at the same position

Callers 2

simplifyPathClickedMethod · 0.80

Calls 12

log2Function · 0.85
countRegularNodesMethod · 0.80
nextCoordIndexMethod · 0.80
assignCoordinatesMethod · 0.80
deleteCoordinateMethod · 0.80
isPositionEqualToMethod · 0.80
backMethod · 0.80
calcMaximumDistanceToMethod · 0.80
prevCoordIndexMethod · 0.80
eraseMethod · 0.80
sizeMethod · 0.45
isClosedMethod · 0.45

Tested by

no test coverage detected