/* Automatically reallocate storage for a buffer that has an unknown * final size. To create a new accumulator, pass in old==NULL. To * reuse an existing accumulator, pass it in as old. The new desired * size in bytes is len. If zerofill is non-zero, all bytes between * the old and new length will be zero filled. * * Call this every time before placing a new element in the * accumulator. If you may place new elements non-sequentially, you * should set zerofill on every call for a given accumulator. * * If it's non-NULL, the argument 'old' points four bytes into an * allocated block. The four preceding bytes give the length of the * most recent allocation for that block. That's why we back up from * old to get the value for accumulator, which is a block of size * length+sizeof(unsigned int). */ void * accumulator(void *old, unsigned int len, int zerofill) { unsigned int *accumulator; // points to length word, or NULL if a new accumulator unsigned int new_len; // includes the length word unsigned int accum_length; // includes the length word unsigned int old_accum_length; // includes the length word // The value stored in the length word includes the length word itself. // allocate something even if len==0 new_len = (len ? len : 1) + sizeof(int); if (old == NULL) { accumulator = NULL; old_accum_length = sizeof(int); } else { accumulator = ((unsigned int *)old) - 1; old_accum_length = *accumulator; } if (new_len > old_accum_length) { accum_length = quantize_length(new_len); accumulator = (unsigned int *)reallocate(accumulator, accum_length); *accumulator = accum_length; if (zerofill) { memset(((char *)accumulator)+old_accum_length, 0, accum_length - old_accum_length); } return (void *)(accumulator+1); } return old; }
static Tuple<Nested<CircleArc>,Nested<CircleArc>,Nested<CircleArc>> single_circle_handling_test(int seed, int count) { const auto test_center_range = Box<Vec2>(Vec2(0,0)).thickened(100); const real max_test_r = 100.; const auto test_bounds = test_center_range.thickened(max_test_r); const auto quant = make_arc_quantizer(test_bounds); // Get appropriate quantizer for test_bounds IntervalScope scope; auto rnd = new_<Random>(seed); ArcAccumulator<Pb::Implicit> acc; for(int i = 0; i < count; ++i) { const auto center = quant(rnd->uniform(test_center_range)); const Quantized r = max(1, quant.quantize_length(rnd->uniform<real>(0, max_test_r))); acc.add_full_circle(ExactCircle<Pb::Implicit>(center, r), ArcDirection::CCW); // Each circle becomes a single ccw halfedge } const auto unquantized_input = acc.vertices.unquantize_circle_arcs(quant, acc.contours); auto graph = new_<PlanarArcGraph<Pb::Implicit>>(acc.vertices, acc.contours); const auto unquantized_unions = graph->unquantize_circle_arcs(quant, extract_region(graph->topology, faces_greater_than(*graph, 0))); const auto unquantized_overlaps = graph->unquantize_circle_arcs(quant, extract_region(graph->topology, faces_greater_than(*graph, 1))); return tuple(unquantized_input, unquantized_unions, unquantized_overlaps); }