Algorithm-BreakOverlappingRectangles
view release on metacpan or search on metacpan
BreakOverlappingRectangles.xs view on Meta::CPAN
DP(printf("cmp(%f, %f) => %d\n", fa, fb, (fa < fb) ? -1 : ((fa > fb) ? 1 : 0)));
return (fa < fb) ? -1 : ((fa > fb) ? 1 : 0);
}
void
sort_inplace(pTHX_ double **v, int size) {
sortsv((SV**)v, size, (SVCOMPARE_t)&double_cmp);
}
static NV
find_best_cut(pTHX_ AV *rects, I32 start, I32 end, int dir, NV *bestv) {
NV **v0, **v1, **vc0, **vc1;
NV v, med, best;
int op, cl;
int i;
SV **svs;
I32 size = end - start;
my_assert(bestv);
DUMP("fbc in", rects, start);
DP(fprintf(stderr, "end: %d\n", end));
Newx(v0, size + 1, NV *);
Newx(v1, size + 1, NV *);
v0[size] = v1[size] = NULL;
vc0 = v0; vc1 = v1;
BreakOverlappingRectangles.xs view on Meta::CPAN
v1[i] = nv + Y1;
}
}
v0[size] = v1[size] = NULL;
sort_inplace(aTHX_ v0, size);
sort_inplace(aTHX_ v1, size);
op = cl = 0;
med = 0.5 * size;
best = .24 * sqr(size);
my_assert(best >= 0);
while (*v0 && *v1) {
NV v, good;
NV l, r;
v = (**v0 <= **v1) ? **v0 : **v1;
while (*v0 && v == **v0) {
op++;
v0++;
BreakOverlappingRectangles.xs view on Meta::CPAN
my_assert(op > 0 && op <= size);
my_assert(cl >= 0 && cl <= size);
l = op - med;
r = size - cl - med;
good = sqr(l) + sqr(r);
my_assert(good >= 0);
if (good < best) {
DP(fprintf(stderr, "find_best_cut l: %.2f, r: %.2f, good: %.2f\n", l, r, good));
best = good;
*bestv = v;
}
}
Safefree(vc0);
Safefree(vc1);
return best;
}
static void
_break(pTHX_ AV *rects, I32 start, AV *parts);
static void
_brute_force_merge(pTHX_ AV *rects, I32 start, AV *parts) {
I32 i, len;
for (i = start; i <= av_len(rects); i++) {
SV *svr = (AvARRAY(rects))[i];
BreakOverlappingRectangles.xs view on Meta::CPAN
svs[end1] = last;
av_push(parts, next);
_brute_force_merge(aTHX_ rects, end1, parts);
}
return;
}
static void
_break(pTHX_ AV *rects, I32 start, AV *parts) {
NV bestx, bestxx, besty, bestyy, div;
int off;
I32 i, j, middle, end;
SV **svs;
DUMP("break", rects, start);
while (1) {
end = av_len(rects) + 1;
if ((end - start) <= BRUTEFORCECUTOFF)
return _brute_force_break(aTHX_ rects, start, parts);
bestx = find_best_cut(aTHX_ rects, start, end, 'x', &bestxx);
besty = ((bestx == 0) ? 1 : find_best_cut(aTHX_ rects, start, end, 'y', &bestyy));
if (bestx < besty) {
off = X0;
div = bestxx;
DP(fprintf(stderr, "cutting at x=%.0f, best=%.2f\n", bestxx, bestx));
}
else {
off = Y0;
div = bestyy;
DP(fprintf(stderr, "cutting at y=%.0f, best=%.2f\n", bestyy, besty));
}
svs = AvARRAY(rects);
i = start;
middle = end;
while (i < middle) {
SV *sv = svs[i];
NV n0 = ((NV*)SvPV_nolen(sv))[off];
if (n0 < div) {
middle--;
#ifndef UV_MAX
# define UV_MAX PERL_ULONG_MAX
#endif
#endif
#ifndef IVSIZE
# ifdef LONGSIZE
# define IVSIZE LONGSIZE
# else
# define IVSIZE 4 /* A bold guess, but the best we can make. */
# endif
#endif
#ifndef UVTYPE
# define UVTYPE unsigned IVTYPE
#endif
#ifndef UVSIZE
# define UVSIZE IVSIZE
#endif
#ifndef sv_setuv
#endif
#ifndef PERL_MAGIC_backref
# define PERL_MAGIC_backref '<'
#endif
#ifndef PERL_MAGIC_ext
# define PERL_MAGIC_ext '~'
#endif
/* That's the best we can do... */
#ifndef SvPV_force_nomg
# define SvPV_force_nomg SvPV_force
#endif
#ifndef SvPV_nomg
# define SvPV_nomg SvPV
#endif
#ifndef sv_catpvn_nomg
# define sv_catpvn_nomg sv_catpvn
( run in 0.890 second using v1.01-cache-2.11-cpan-4e96b696675 )