unclump.cpp revision b6534ae963bb0f40d95b848aa2d12109969c71aa
#define __UNCLUMP_C__
/*
* Unclumping objects
*
* Authors:
* bulia byak
*
* Copyright (C) 2005 Authors
* Released under GNU GPL
*/
#include <algorithm>
#include <map>
#include "libnr/nr-matrix-ops.h"
#include "sp-item.h"
// Taking bbox of an item is an expensive operation, and we need to do it many times, so here we
// cache the centers, widths, and heights of items
//FIXME: make a class with these cashes as members instead of globals
/**
Center of bbox of item
*/
{
return i->second;
}
if (r) {
return c;
} else {
// FIXME
}
}
{
} else {
if (r) {
wh = r->dimensions();
} else {
}
}
return wh;
}
/**
Distance between "edges" of item1 and item2. An item is considered to be an ellipse inscribed into its w/h,
so its radius (distance from center to edge) depends on the w/h and the angle towards the other item.
May be negative if the edge of item1 is between the center and the edge of item2.
*/
double
{
// angle from each item's center to the other's, unsqueezed by its w/h, normalized to 0..pi/2
// get the radius of each item for the given angle
// dist between centers minus angle-adjusted radii
// If both objects are not circle-like, find dists between four corners
{
double y_closest;
} else {
}
double x_closest;
} else {
}
}
{
double y_closest;
} else {
}
double x_closest;
} else {
}
}
for (int i = 0; i < 2; i ++) {
for (int j = 0; j < 2; j ++) {
}
}
// return the minimum of all dists
} else {
return dist_r;
}
}
/**
Average unclump_dist from item to others
*/
{
int n = 0;
double sum = 0;
continue;
n++;
}
if (n != 0)
return sum/n;
else
return 0;
}
/**
Closest to item among others
*/
{
continue;
}
}
return closest;
}
/**
Most distant from item among others
*/
{
continue;
}
}
return farest;
}
/**
Removes from the \a rest list those items that are "behind" \a closest as seen from \a item,
i.e. those on the other side of the line through \a closest perpendicular to the direction from \a
item to \a closest. Returns a newly created list which must be freed.
*/
GSList *
{
// perpendicular through closest to the direction to item:
// get the standard Ax + By + C = 0 form for p1-p2:
// substitute the item into it:
continue;
// different signs, which means item and other are on the different sides of p1-p2 line; skip
} else {
}
}
return out;
}
/**
Moves \a what away from \a from by \a dist
*/
void
{
}
//g_print ("push %s at %g,%g from %g,%g by %g,%g, dist %g\n", SP_OBJECT_ID(what), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist);
}
/**
Moves \a what towards \a to by \a dist
*/
void
{
}
//g_print ("pull %s at %g,%g to %g,%g by %g,%g, dist %g\n", SP_OBJECT_ID(what), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist);
}
/**
Unclumps the items in \a items, reducing local unevenness in their distribution. Produces an effect
similar to "engraver dots". The only distribution which is unchanged by unclumping is a hexagonal
grid. May be called repeatedly for stronger effect.
*/
void
{
if (closest) {
g_slist_free (rest);
} else {
g_slist_free (rest);
break;
}
}
//g_print ("NEI %d for item %s closest %s at %g farest %s at %g ave %g\n", g_slist_length(nei), SP_OBJECT_ID(item), SP_OBJECT_ID(closest), dist_closest, SP_OBJECT_ID(farest), dist_farest, ave);
if (fabs (ave) < 1e6 && fabs (dist_closest) < 1e6 && fabs (dist_farest) < 1e6) { // otherwise the items are bogus
// increase these coefficients to make unclumping more aggressive and less stable
// the pull coefficient is a bit bigger to counteract the long-term expansion trend
}
}
}
}