/** 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 unclump (std::vector<SPItem*> &items) { c_cache.clear(); wh_cache.clear(); for (std::vector<SPItem*>::const_iterator i = items.begin(); i != items.end();++i) { // for each original/clone x: SPItem *item = *i; std::list<SPItem*> nei; std::list<SPItem*> rest; for (int i=0; i < static_cast<int>(items.size()); i++) { rest.push_front(items[items.size() - i - 1]); } rest.remove(item); while (!rest.empty()) { SPItem *closest = unclump_closest (item, rest); if (closest) { nei.push_front(closest); rest.remove(closest); std::vector<SPItem*> new_rest = unclump_remove_behind (item, closest, rest); rest.clear(); for (int i=0; i < static_cast<int>(new_rest.size()); i++) { rest.push_front(new_rest[new_rest.size() - i - 1]); } } else { break; } } if ( (nei.size()) >= 2) { double ave = unclump_average (item, nei); SPItem *closest = unclump_closest (item, nei); SPItem *farest = unclump_farest (item, nei); double dist_closest = unclump_dist (closest, item); double dist_farest = unclump_dist (farest, item); //g_print ("NEI %d for item %s closest %s at %g farest %s at %g ave %g\n", g_slist_length(nei), item->getId(), closest->getId(), dist_closest, farest->getId(), 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 unclump_push (closest, item, 0.3 * (ave - dist_closest)); unclump_pull (farest, item, 0.35 * (dist_farest - ave)); } } } }
/** 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 unclump (GSList *items) { c_cache.clear(); wh_cache.clear(); for (GSList *i = items; i != NULL; i = i->next) { // for each original/clone x: SPItem *item = SP_ITEM (i->data); GSList *nei = NULL; GSList *rest = g_slist_copy (items); rest = g_slist_remove (rest, item); while (rest != NULL) { SPItem *closest = unclump_closest (item, rest); if (closest) { nei = g_slist_prepend (nei, closest); rest = g_slist_remove (rest, closest); GSList *new_rest = unclump_remove_behind (item, closest, rest); g_slist_free (rest); rest = new_rest; } else { g_slist_free (rest); break; } } if (g_slist_length (nei) >= 2) { double ave = unclump_average (item, nei); SPItem *closest = unclump_closest (item, nei); SPItem *farest = unclump_farest (item, nei); double dist_closest = unclump_dist (closest, item); double dist_farest = unclump_dist (farest, item); //g_print ("NEI %d for item %s closest %s at %g farest %s at %g ave %g\n", g_slist_length(nei), item->getId(), closest->getId(), dist_closest, farest->getId(), 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 unclump_push (closest, item, 0.3 * (ave - dist_closest)); unclump_pull (farest, item, 0.35 * (dist_farest - ave)); } } } }