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);
    }

Perl.xs  view on Meta::CPAN

    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 1.131 second using v1.01-cache-2.11-cpan-5511b514fd6 )