Graph-Layout-Aesthetic
view release on metacpan or search on metacpan
Aesthetic.xs view on Meta::CPAN
nr_vertices(aglo_graph topology)
CODE:
RETVAL = topology->vertices;
OUTPUT:
RETVAL
void
neighbors(aglo_graph topology, aglo_vertex vertex)
PREINIT:
aglo_edge_record here, next;
PPCODE:
if (vertex >= topology->vertices)
croak("Vertex number %"UVuf" is invalid, there are only %"UVuf" in the topology",
(UV) vertex, (UV) topology->vertices);
here = topology->edge_table[vertex];
while (here) {
next = here->next;
XPUSHs(sv_2mortal(newSVuv(here->tail)));
here = next;
}
void
forward_neighbors(aglo_graph topology, aglo_vertex vertex)
PREINIT:
aglo_edge_record here, next;
PPCODE:
if (vertex >= topology->vertices)
croak("Vertex number %"UVuf" is invalid, there are only %"UVuf" in the topology",
(UV) vertex, (UV) topology->vertices);
here = topology->edge_table[vertex];
while (here) {
next = here->next;
if (here->forward) XPUSHs(sv_2mortal(newSVuv(here->tail)));
here = next;
}
void
edges(aglo_graph topology)
PREINIT:
aglo_vertex i;
PPCODE:
for (i=0; i<topology->vertices; i++) {
aglo_edge_record here, next;
for (here = topology->edge_table[i]; here; here = next) {
next = here->next;
if (here->forward) {
AV *av = newAV();
av_extend(av, 2-1);
av_push(av, newSVuv(i));
av_push(av, newSVuv(here->tail));
XPUSHs(sv_2mortal(newRV_noinc((SV *) av)));
}
}
}
void
add_edge(aglo_graph topology, aglo_vertex u, aglo_vertex v, aglo_boolean forward=1)
PREINIT:
aglo_edge_record f_edge, b_edge;
PPCODE:
if (topology->done) croak("Cannot add nodes to a finished topology");
if (u >= topology->vertices)
croak("Vertex number %"UVuf" is invalid, there are only %"UVuf" in the topology",
(UV) u, (UV) topology->vertices);
if (v >= topology->vertices)
croak("Vertex number %"UVuf" is invalid, there are only %"UVuf" in the topology",
(UV) v, (UV) topology->vertices);
if (u == v) croak("Vertex %"UVuf" connects to itself", (UV) u);
New(_LINE__, f_edge, 1, struct aglo_edge_record);
Aesthetic.xs view on Meta::CPAN
topology->edge_table[u] = f_edge;
New(__LINE__, b_edge, 1, struct aglo_edge_record);
b_edge->tail = u;
b_edge->forward = !forward;
b_edge->next = topology->edge_table[v];
topology->edge_table[v] = b_edge;
void
finish(aglo_graph topology)
PPCODE:
if (topology->done) croak("Topology is already finished");
topology->done = true;
aglo_boolean
finished(aglo_graph topology)
CODE:
RETVAL = topology->done;
OUTPUT:
RETVAL
void
levels(aglo_graph topology)
PREINIT:
aglo_vertex i;
PPCODE:
at_setup_node_level(topology);
EXTEND(SP, topology->vertices);
for (i=0; i<topology->vertices; i++)
PUSHs(sv_2mortal(newSVnv(topology->at_level[i])));
void
user_data(aglo_graph topology, SV *new_user_data=0)
PPCODE:
if (GIMME_V != G_VOID)
XPUSHs(topology->user_data ? topology->user_data : &PL_sv_undef);
if (new_user_data) {
if (topology->user_data) sv_2mortal(topology->user_data);
topology->user_data = newSVsv(new_user_data);
}
void
_private_data(aglo_graph topology, SV *new_private_data=0)
PPCODE:
if (GIMME_V != G_VOID)
XPUSHs(topology->private_data ? topology->private_data : &PL_sv_undef);
if (new_private_data) {
if (topology->private_data) sv_2mortal(topology->private_data);
topology->private_data = newSVsv(new_private_data);
}
void
DESTROY(aglo_graph topology)
PREINIT:
aglo_vertex i;
PPCODE:
if (topology->user_data) sv_2mortal(topology->user_data);
if (topology->private_data) sv_2mortal(topology->private_data);
if (topology->at_level) Safefree(topology->at_level);
if (topology->level_sorted_vertex) Safefree(topology->level_sorted_vertex);
if (topology->level2nodes) Safefree(topology->level2nodes);
for (i=0; i<topology->vertices; i++) {
aglo_edge_record next, here = topology->edge_table[i];
while (here) {
next = here->next;
Safefree(here);
here = next;
}
}
Safefree(topology);
MODULE = Graph::Layout::Aesthetic PACKAGE = Graph::Layout::Aesthetic::Force
void
user_data(aglo_force force, SV *new_user_data=0)
PPCODE:
if (GIMME_V != G_VOID)
XPUSHs(force->user_data ? force->user_data : &PL_sv_undef);
if (new_user_data) {
if (force->user_data) sv_2mortal(force->user_data);
force->user_data = newSVsv(new_user_data);
}
void
_private_data(aglo_force force, SV *new_private_data=0)
PPCODE:
if (GIMME_V != G_VOID)
XPUSHs(force->private_data ? force->private_data : &PL_sv_undef);
if (new_private_data) {
if (force->private_data) sv_2mortal(force->private_data);
force->private_data = newSVsv(new_private_data);
}
void
DESTROY(aglo_force force)
PPCODE:
if (force->private_data) sv_2mortal(force->private_data);
if (force->user_data) sv_2mortal(force->user_data);
Safefree(force);
MODULE = Graph::Layout::Aesthetic PACKAGE = Graph::Layout::Aesthetic
SV *
new_state(char *class, SV *topology, aglo_signed nr_dimensions=2)
PREINIT:
aglo_graph gr;
Aesthetic.xs view on Meta::CPAN
state->paused = 0;
RETVAL = NEWSV(1, 0);
sv_setref_pv(RETVAL, class, (void*) state);
OUTPUT:
RETVAL
void
paused(aglo_state state, aglo_boolean new_paused=0)
PPCODE:
if (GIMME_V != G_VOID) XPUSHs(state->paused ? &PL_sv_yes : &PL_sv_no);
if (items > 1) state->paused = new_paused;
aglo_unsigned
nr_dimensions(aglo_state state)
CODE:
RETVAL = state->dimensions;
OUTPUT:
RETVAL
Aesthetic.xs view on Meta::CPAN
state->end_temperature = end_temperature;
}
OUTPUT:
RETVAL
void
coordinates(aglo_state state, aglo_vertex vertex, ...)
PREINIT:
aglo_unsigned i, d;
aglo_point v;
PPCODE:
if (vertex >= state->graph->vertices)
croak("Vertex number %"UVuf" is invalid, there are only %"UVuf" in the topology",
(UV) vertex, (UV) state->graph->vertices);
d = state->dimensions;
v = state->point[vertex];
/* First push the result */
switch(GIMME_V) {
AV *av;
case G_ARRAY:
Aesthetic.xs view on Meta::CPAN
}
}
void
all_coordinates(aglo_state state, ...)
PREINIT:
aglo_unsigned j, d;
aglo_vertex i, v;
AV *coords;
aglo_point p;
PPCODE:
d = state->dimensions;
v = state->graph->vertices;
/* First push the result */
switch(GIMME_V) {
AV *av;
case G_ARRAY:
EXTEND(SP, v);
for (i=0; i<v; i++) {
AV *pav = newAV();
Aesthetic.xs view on Meta::CPAN
void
increasing_edges(aglo_state state)
PREINIT:
aglo_vertex i;
aglo_unsigned j, d;
aglo_graph graph;
aglo_point p;
aglo_edge_record here;
AV *rav, *av, *av_from, *av_to;
PPCODE:
d = state->dimensions;
graph = state->graph;
switch(GIMME_V) {
case G_ARRAY:
for (i=0; i<graph->vertices; i++) {
for (here = graph->edge_table[i]; here; here = here->next) {
if (i < here->tail) {
av = newAV();
av_extend(av, 2-1);
XPUSHs(sv_2mortal(newRV_noinc((SV *) av)));
Aesthetic.xs view on Meta::CPAN
break;
default:
break;
}
void
zero(aglo_state state)
PREINIT:
aglo_unsigned i, d;
aglo_vertex p, v;
PPCODE:
d = state->dimensions;
v = state->graph->vertices;
for (p=0; p<v; p++) {
aglo_real *here = state->point[p];
for (i=0; i<d; i++) here[i] = 0;
}
state->sequence++;
void
randomize(aglo_state state, aglo_real size = 1)
PPCODE:
aglo_randomize(aTHX_ state, size);
void
frame(aglo_state state)
PREINIT:
aglo_real *frame;
aglo_unsigned i, d;
AV *av;
PPCODE:
if (state->graph->vertices > 0) {
d = state->dimensions;
New(__LINE__, frame, 2*d, aglo_real);
aglo_frame_coordinates(state, frame, &frame[d]);
EXTEND(SP, 2);
av = newAV();
av_extend(av, d-1);
Aesthetic.xs view on Meta::CPAN
Safefree(frame);
}
void
iso_frame(aglo_state state)
PREINIT:
aglo_real *frame;
aglo_unsigned i, d;
AV *av;
PPCODE:
if (state->graph->vertices > 0) {
d = state->dimensions;
New(__LINE__, frame, 2*d, aglo_real);
aglo_iso_frame_coordinates(state, frame, &frame[d]);
EXTEND(SP, 2);
av = newAV();
av_extend(av, d-1);
Aesthetic.xs view on Meta::CPAN
av = newAV();
av_extend(av, d-1);
for (i=0; i<d; i++) av_push(av, newSVnv(frame[i+d]));
PUSHs(sv_2mortal(newRV_noinc((SV *) av)));
Safefree(frame);
}
void
normalize(aglo_state state)
PPCODE:
aglo_normalize_state(state);
void
jitter(aglo_state state, aglo_real distance=1e-5)
PPCODE:
jitter(aTHX_ state, distance);
void
_add_force(SV *state, SV *force, aglo_real weight=1)
PREINIT:
aglo_state st;
aglo_force fo;
use_force use;
void *private;
PPCODE:
/* This replaces force by what it references */
fo = C_OBJECT(force, "Graph::Layout::Aesthetic::Force", "force");
/* This replaces state by what it references */
st = C_OBJECT(state, "Graph::Layout::Aesthetic", "state");
sv_2mortal(SvREFCNT_inc(force));
# Make sure we do this test before allocating anything (permanently)
private = fo->aesth_setup(aTHX_ force, state, st);
New(__LINE__, use, 1, struct use_force);
Aesthetic.xs view on Meta::CPAN
use->force_sv = newRV(force);
use->private = private;
use->next = st->forces;
st->forces = use;
void
forces(aglo_state state)
PREINIT:
use_force force;
PPCODE:
switch(GIMME_V) {
AV *rav;
case G_ARRAY:
for (force = state->forces; force; force = force->next) {
AV *av = newAV();
XPUSHs(sv_2mortal(newRV_noinc((SV *) av)));
av_extend(av, 2-1);
SvREFCNT_inc(force->force_sv);
av_push(av, force->force_sv);
av_push(av, newSVnv(force->weight));
Aesthetic.xs view on Meta::CPAN
av_push(av, newSVnv(force->weight));
}
break;
default:
break;
}
void
init_gloss(aglo_state state, aglo_real temperature, aglo_real end_temperature, aglo_signed iterations, aglo_real randomize_size=1)
PPCODE:
if (temperature <= 0)
croak("Temperature %"NVff" should be > 0", (NV) temperature);
if (end_temperature <= 0)
croak("End_temperature %"NVff" should be > 0", (NV) end_temperature);
if (temperature < end_temperature)
warn("Temperature %"NVff" should probably be >= end_temperature %"NVff,
(NV) temperature, (NV) end_temperature);
if (iterations < 0)
croak("Iterations %"IVdf" should be >= 0", (IV) iterations);
state->temperature = temperature;
state->end_temperature = end_temperature;
state->iterations = iterations;
if (randomize_size > 0) aglo_randomize(aTHX_ state, randomize_size);
void
_gloss(aglo_state state, aglo_real pause_time=1e50)
PREINIT:
time_t now;
aglo_real lambda;
PPCODE:
if (state->iterations <= 0) croak("No more iterations left");
lambda = pow(state->temperature / state->end_temperature, 1.0 / state->iterations);
state->paused = 0;
while (state->iterations > 0 && !state->paused) {
aglo_step(aTHX_ state, state->temperature,
state->temperature < 1e-5 ? state->temperature : 1e-5);
state->temperature /= lambda;
state->iterations--;
if (items > 1) {
time(&now);
if (pause_time <= now) break;
}
}
/* We lose the value anyways on exception in gradient,
but restore is just a nicity, not part of the API */
void
step(aglo_state state, aglo_real temperature = state->temperature, aglo_real jitter_size = 1e-5)
PPCODE:
if (items < 3 && temperature < jitter_size) jitter_size = temperature;
aglo_step(aTHX_ state, temperature, jitter_size);
void gradient(aglo_state state)
PREINIT:
aglo_unsigned i, d;
aglo_vertex p, v;
aglo_gradient gradient;
PPCODE:
calculate_aesth_forces(aTHX_ state);
gradient = state->gradient;
d = state->dimensions;
v = state->graph->vertices;
switch(GIMME_V) {
AV *rav, *av;
case G_ARRAY:
EXTEND(SP, v);
for (p=0; p<v; p++) {
Aesthetic.xs view on Meta::CPAN
RETVAL = state->graph_sv;
OUTPUT:
RETVAL
void
DESTROY(SV *state)
PREINIT:
use_force here;
aglo_state st;
aglo_boolean warned;
PPCODE:
/* This replaces state by what it references */
st = C_OBJECT(state, "Graph::Layout::Aesthetic", "state");
warned = 0;
ENTER;
EXTEND(SP, 1);
while (st->forces) {
I32 count;
here = st->forces;
SAVETMPS;
Aesthetic.xs view on Meta::CPAN
sv_2mortal(st->graph_sv);
Safefree(st->point[0]);
Safefree(st);
void
clear_forces(aglo_state state)
PREINIT:
use_force here;
aglo_aesth_cleanup_fx *cleanup;
void *private;
PPCODE:
while (state->forces) {
here = state->forces;
/* Keep datastructure valid in case the cleanup call dies */
state->forces = here->next;
cleanup = here->force->aesth_cleanup;
private = here->private;
sv_2mortal(here->force_sv);
Safefree(here);
cleanup(aTHX_ state, private);
}
force->aesth_setup = ae_setup_perl;
force->aesth_cleanup = ae_cleanup_perl;
force->private_data = force->user_data = NULL;
RETVAL = NEWSV(1, 0);
sv_setref_pv(RETVAL, class, (void*) force);
OUTPUT:
RETVAL
void
setup(SV *force, SV *state)
PPCODE:
PERL_UNUSED_VAR(force);
PERL_UNUSED_VAR(state);
EXTEND(SP, 1);
PUSHs(&PL_sv_undef);
void
cleanup(SV *force, SV *state, SV *closure)
PPCODE:
PERL_UNUSED_VAR(force);
PERL_UNUSED_VAR(state);
PERL_UNUSED_VAR(closure);
( run in 0.657 second using v1.01-cache-2.11-cpan-5511b514fd6 )