Exemple #1
0
vx_buffer_t * vx_world_get_buffer(vx_world_t * world, const char * name)
{
    vx_buffer_t * buffer = NULL;

    pthread_mutex_lock(&world->buffer_mutex);

    zhash_get(world->buffer_map, &name, &buffer);
    if (buffer == NULL) {
        buffer = calloc(1, sizeof(vx_buffer_t));

        buffer->name = strdup(name);
        buffer->world = world;
        buffer->draw_order = 0;

        buffer->back_objs = zarray_create(sizeof(vx_object_t*));
        buffer->pending_objs = zarray_create(sizeof(vx_object_t*));
        buffer->front_objs = zarray_create(sizeof(vx_object_t*));

        buffer->front_resc = zhash_create(sizeof(uint64_t), sizeof(vx_resc_t*), zhash_uint64_hash, zhash_uint64_equals);
        buffer->front_codes = vx_code_output_stream_create(128);

        pthread_mutex_init(&buffer->mutex, NULL);

        vx_buffer_t * oldBuffer= NULL;
        zhash_put(buffer->world->buffer_map, &buffer->name, &buffer, NULL, &oldBuffer);
        assert(oldBuffer == NULL);
    }

    pthread_mutex_unlock(&world->buffer_mutex);

    return buffer;
}
Exemple #2
0
static state_t * state_create(vx_display_t * super)
{
    state_t * state = calloc(1, sizeof(state_t));
    state->super = super;
    state->glrend = vx_gl_renderer_create();


    // because the resource manager is called in send_codes(), and will itself call send_codes() again
    pthread_mutexattr_t mutexAttr;
    pthread_mutexattr_init(&mutexAttr);
    pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE);

    pthread_mutex_init(&state->mutex, &mutexAttr);
    state->listeners = zarray_create(sizeof(vx_display_listener_t*));
    pthread_mutex_init(&state->listener_mutex, NULL);
    state->rendering = 1;
    state->target_frame_rate = 30.0f; // XXX
    state->buffer_manager = vx_gtk_buffer_manager_create(state->super);

    state->movie_pending = zarray_create(sizeof(movie_frame_t*));
    pthread_mutex_init(&state->movie_mutex, NULL);
    pthread_cond_init(&state->movie_cond, NULL);
    pthread_create(&state->movie_thread, NULL, movie_run, state);

    state->layer_info_map = zhash_create(sizeof(uint32_t), sizeof(layer_info_t*), zhash_uint32_hash, zhash_uint32_equals);

    return state;
}
getopt_t *
getopt_create (void)
{
    getopt_t *gopt = calloc (1, sizeof(*gopt));

    gopt->lopts     = zhash_create (sizeof(char*), sizeof(getopt_option_t*), zhash_str_hash, zhash_str_equals);
    gopt->sopts     = zhash_create (sizeof(char*), sizeof(getopt_option_t*), zhash_str_hash, zhash_str_equals);
    gopt->options   = zarray_create (sizeof(getopt_option_t*));
    gopt->extraargs = zarray_create (sizeof(char*));

    return gopt;
}
Exemple #4
0
void default_cam_mgr_rotate(default_cam_mgr_t * state, double *q, uint32_t animate_ms)
{
    zarray_t * fp = zarray_create(sizeof(matd_t*));

    matd_t * eye = matd_create_data(3,1,state->eye1);       zarray_add(fp, &eye);
    matd_t *lookat = matd_create_data(3,1,state->lookat1);  zarray_add(fp, &lookat);
    matd_t *up = matd_create_data(3,1,state->up1);          zarray_add(fp, &up);


    matd_t * toEye = matd_subtract(eye, lookat); zarray_add(fp, &toEye);
    matd_t * nextToEye = matd_create(3,1); zarray_add(fp, &nextToEye);
    vx_util_quat_rotate(q, toEye->data, nextToEye->data);

    matd_t * nextEye = matd_add(lookat, nextToEye); zarray_add(fp, &nextEye);
    matd_t * nextUp = matd_copy(up); zarray_add(fp, &nextUp);

    vx_util_quat_rotate(q, up->data, nextUp->data);

    // copy back results
    memcpy(state->eye1, nextEye->data, sizeof(double)*3);
    memcpy(state->up1, nextUp->data, sizeof(double)*3);
    state->mtime1 = vx_util_mtime() + animate_ms;

    // Disable any prior fit command
    default_destroy_fit(state);

    // cleanup
    zarray_vmap(fp, matd_destroy);
    zarray_destroy(fp);

    default_cam_mgr_follow_disable(state);

}
zarray_t *
str_match_regex (const char *str, const char *regex)
{
    assert (str != NULL);
    assert (regex != NULL);

    regex_t regex_comp;
    if (regcomp (&regex_comp, regex, REG_EXTENDED) != 0)
        return NULL;

    zarray_t *matches = zarray_create (sizeof(char*));

    const void *ptr = str;
    regmatch_t match;
    while (REG_NOMATCH!=regexec (&regex_comp, ptr, 1, &match, 0))  {
        if (match.rm_so == -1)
            break;

        if (match.rm_so == match.rm_eo) // ambiguous regex
            break;

        int   length = match.rm_eo - match.rm_so;
        char *substr = malloc(length+1);
        bzero (substr, length+1);

        memcpy (substr, ptr+match.rm_so, length);

        ptr = ptr + match.rm_eo;

        zarray_add (matches, &substr);
    }

    regfree (&regex_comp);
    return matches;
}
Exemple #6
0
void vx_util_project(double * xyz, double * M44, double * P44, int * viewport, double * win_out3)
{
    zarray_t * fp = zarray_create(sizeof(matd_t*));

    matd_t * M = matd_create_data(4,4, M44); zarray_add(fp, &M);
    matd_t * P = matd_create_data(4,4, P44); zarray_add(fp, &P);
    matd_t * xyzp = matd_create(4,1); zarray_add(fp, &xyzp);
    memcpy(xyzp->data, xyz, 3*sizeof(double));
    xyzp->data[3] = 1.0;

    matd_t * p = matd_op("MMM", P, M, xyzp); zarray_add(fp, &p);

        p->data[0] = p->data[0] / p->data[3];
        p->data[1] = p->data[1] / p->data[3];
        p->data[2] = p->data[2] / p->data[3];


    double res[] =  { viewport[0] + viewport[2]*(p->data[0]+1)/2.0,
                      viewport[1] + viewport[3]*(p->data[1]+1)/2.0,
                      (viewport[2] + 1)/2.0 };
    memcpy(win_out3, res, 3*sizeof(double));

    // cleanup
    zarray_vmap(fp, matd_destroy);
    zarray_destroy(fp);
}
Exemple #7
0
void vx_util_unproject(double * winxyz, double * model_matrix, double * projection_matrix, int * viewport, double * vec3_out)
{
    zarray_t * fp = zarray_create(sizeof(matd_t*));

    matd_t * mm = matd_create_data(4, 4, model_matrix);
    zarray_add(fp, &mm);
    matd_t * pm = matd_create_data(4, 4, projection_matrix);
    zarray_add(fp, &pm);

    matd_t *invpm = matd_op("(MM)^-1", pm, mm);
    zarray_add(fp, &invpm);

    double v[4] = { 2*(winxyz[0]-viewport[0]) / viewport[2] - 1,
                    2*(winxyz[1]-viewport[1]) / viewport[3] - 1,
                    2*winxyz[2] - 1,
                    1 };
    matd_t * vm = matd_create_data(4, 1, v);
    zarray_add(fp, &vm);

    matd_t * objxyzh = matd_op("MM", invpm, vm);
    zarray_add(fp, &objxyzh);

    vec3_out[0] = objxyzh->data[0] / objxyzh->data[3];
    vec3_out[1] = objxyzh->data[1] / objxyzh->data[3];
    vec3_out[2] = objxyzh->data[2] / objxyzh->data[3];

    // cleanup
    zarray_vmap(fp, matd_destroy);
    zarray_destroy(fp);
}
workerpool_t *workerpool_create(int nthreads)
{
    assert(nthreads > 0);

    workerpool_t *wp = calloc(1, sizeof(workerpool_t));
    wp->nthreads = nthreads;
    wp->tasks = zarray_create(sizeof(struct task));

    if (nthreads > 1) {
        wp->threads = calloc(wp->nthreads, sizeof(pthread_t));

        pthread_mutex_init(&wp->mutex, NULL);
        pthread_cond_init(&wp->startcond, NULL);
        pthread_cond_init(&wp->endcond, NULL);

        for (int i = 0; i < nthreads; i++) {
            int res = pthread_create(&wp->threads[i], NULL, worker_thread, wp);
            if (res != 0) {
                perror("pthread_create");
                exit(-1);
            }
        }
    }

    return wp;
}
zarray_t *
str_split_regex (const char *str, const char *regex)
{
    assert (str != NULL);
    assert (regex != NULL);

    regex_t regex_comp;
    if (0!=regcomp (&regex_comp, regex, REG_EXTENDED))
        return NULL;

    zarray_t *matches = zarray_create (sizeof(char*));

    int origlen = strlen (str);
    const void *end = str + origlen;
    const void *ptr = str;

    regmatch_t match;
    while (regexec(&regex_comp, ptr, 1, &match, 0) != REG_NOMATCH)
    {
        //printf("so %3d eo %3d\n", match.rm_so, match.rm_eo);

        if (match.rm_so == -1)
            break;

        if (match.rm_so == match.rm_eo) // ambiguous regex
            break;

        void *so = ((void*) ptr) + match.rm_so;

        int length = so - ptr;

        if (length > 0) {
            char *substr = malloc (length+1);
            bzero (substr, length+1);
            memcpy (substr, ptr, length);

            //printf("match '%s'\n", substr);
            //fflush(stdout);

            zarray_add (matches, &substr);
        }

        ptr = ptr + match.rm_eo;
    }

    if (ptr - (void*) str != origlen) {
        int length = end - ptr;
        char *substr = malloc (length+1);
        bzero (substr, length+1);

        memcpy (substr, ptr, length);

        zarray_add (matches, &substr);
    }


    regfree (&regex_comp);
    return matches;
}
Exemple #10
0
static render_info_t * render_info_create()
{
    render_info_t * rinfo = calloc(1, sizeof(render_info_t));
    rinfo->layers = zarray_create(sizeof(layer_info_t*));
    rinfo->camera_positions = zhash_create(sizeof(uint32_t), sizeof(vx_camera_pos_t *), zhash_uint32_hash, zhash_uint32_equals);
    rinfo->layer_positions = zhash_create(sizeof(uint32_t), sizeof(uint32_t *), zhash_uint32_hash, zhash_uint32_equals);
    return rinfo;
}
Exemple #11
0
zarray_t *g2d_polygon_create_data(double v[][2], int sz)
{
    zarray_t *points = zarray_create(sizeof(double[2]));

    for (int i = 0; i < sz; i++)
        zarray_add(points, v[i]);

    return points;
}
Exemple #12
0
vx_world_t * vx_world_create()
{
    vx_world_t *world = malloc(sizeof(vx_world_t));
    world->worldID = xxxAtomicID++;
    world->buffer_map = zhash_create(sizeof(char*), sizeof(vx_buffer_t*), zhash_str_hash, zhash_str_equals);
    world->listeners = zarray_create(sizeof(vx_world_listener_t*));
    pthread_mutex_init(&world->buffer_mutex, NULL);
    pthread_mutex_init(&world->listener_mutex, NULL);

    pthread_mutex_init(&world->queue_mutex, NULL);
    pthread_cond_init(&world->queue_cond, NULL);

    world->listener_queue = zarray_create(sizeof(vx_world_listener_t*));
    world->buffer_queue = zarray_create(sizeof(char*));

    world->process_running = 1;
    pthread_create(&world->process_thread, NULL, run_process, world);
    return world;
}
Exemple #13
0
zarray_t *g2d_polygon_create_zeros(int sz)
{
    zarray_t *points = zarray_create(sizeof(double[2]));

    double z[2] = { 0, 0 };

    for (int i = 0; i < sz; i++)
        zarray_add(points, z);

    return points;
}
Exemple #14
0
void vx_util_lookat(double * _eye, double * _lookat, double * _up, double * _out44)
{
    zarray_t * fp = zarray_create(sizeof(matd_t*));

    matd_t * eye = matd_create_data(3,1, _eye);
    zarray_add(fp, &eye);

    matd_t * lookat = matd_create_data(3,1, _lookat);
    zarray_add(fp, &lookat);

    matd_t * up = matd_create_data(3,1, _up);
    zarray_add(fp, &up);

    up = matd_vec_normalize(up);

    zarray_add(fp, &up); // note different pointer than before!

    matd_t * tmp1 = matd_subtract(lookat, eye); zarray_add(fp, &tmp1);

    matd_t * f = matd_vec_normalize(tmp1);      zarray_add(fp, &f);
    matd_t * s = matd_crossproduct(f, up);      zarray_add(fp, &s);
    matd_t * u = matd_crossproduct(s, f);       zarray_add(fp, &u);

    matd_t * M = matd_create(4,4); // set the rows of M with s, u, -f
    zarray_add(fp, &M);
    memcpy(M->data,s->data,3*sizeof(double));
    memcpy(M->data + 4,u->data,3*sizeof(double));
    memcpy(M->data + 8,f->data,3*sizeof(double));
    for (int i = 0; i < 3; i++)
        M->data[2*4 +i] *= -1;
    M->data[3*4 + 3] = 1.0;


    matd_t * T = matd_create(4,4);
    T->data[0*4 + 3] = -eye->data[0];
    T->data[1*4 + 3] = -eye->data[1];
    T->data[2*4 + 3] = -eye->data[2];
    T->data[0*4 + 0] = 1;
    T->data[1*4 + 1] = 1;
    T->data[2*4 + 2] = 1;
    T->data[3*4 + 3] = 1;
    zarray_add(fp, &T);

    matd_t * MT = matd_op("MM",M,T);
    zarray_add(fp, &MT);


    memcpy(_out44, MT->data, 16*sizeof(double));

    // cleanup
    zarray_vmap(fp, matd_destroy);
    zarray_destroy(fp);
}
Exemple #15
0
void vx_util_angle_axis_to_quat(double theta, double * axis3, double * qout)
{
    zarray_t * fp = zarray_create(sizeof(matd_t*));

    matd_t * axis = matd_create_data(3,1, axis3); zarray_add(fp, &axis);
    matd_t * axis_norm = matd_vec_normalize(axis); zarray_add(fp, &axis_norm);

    qout[0] = cos(theta/2);
    double s = sin(theta/2);

    qout[1] = axis_norm->data[0] * s;
    qout[2] = axis_norm->data[1] * s;
    qout[3] = axis_norm->data[2] * s;

    // cleanup
    zarray_vmap(fp, matd_destroy);
    zarray_destroy(fp);
}
Exemple #16
0
// form arguments for homography_compute and return the homography matrix
matd_t* dist_homography(int* pix, int size)
{
    zarray_t* correspondences = zarray_create(sizeof(float[4]));
    // printf("\ncorrespondences\n");
    
    float* real_world_coords;
    if(size == NUM_TARGETS) real_world_coords = target_coords;
    else if(size == NUM_CHART_BLOBS) real_world_coords = chart_coords;
    else assert(0);

    for(int i = 0; i < size; i++)
    {
        float tmp[4] = {real_world_coords[i*2], real_world_coords[i*2+1], 
                        pix[i*2], pix[i*2+1]};
        zarray_add(correspondences, &tmp);
        // printf("%f %f %f %f \n", tmp[0], tmp[1], tmp[2], tmp[3]);    
    }
    matd_t * H = homography_compute(correspondences);
    return(H);
}
zarray_t *
str_split (const char *str, const char *delim)
{
    assert (str != NULL);
    assert (delim != NULL);

    zarray_t *parts = zarray_create (sizeof(char*));
    string_buffer_t *sb = string_buffer_create ();

    size_t delim_len = strlen (delim);
    size_t len = strlen (str);
    size_t pos = 0;

    while (pos < len) {
        if (str_starts_with (&str[pos], delim) && delim_len > 0) {
            pos += delim_len;
            // never add empty strings (repeated tokens)
            if (string_buffer_size (sb) > 0) {
                char *part = string_buffer_to_string (sb);
                zarray_add (parts, &part);
            }
            string_buffer_reset (sb);
        }
        else {
            string_buffer_append (sb, str[pos]);
            pos++;
        }
    }

    if (string_buffer_size(sb) > 0) {
        char *part = string_buffer_to_string (sb);
        zarray_add (parts, &part);
    }

    string_buffer_destroy (sb);
    return parts;
}
Exemple #18
0
int main(int argc, char *argv[])
{
    april_tag_family_t *tf = tag36h11_create();

    april_tag_detector_t *td = april_tag_detector_create(tf);
    td->small_tag_refinement = 0;

    int maxiters = 1;

    zarray_t *inputs = zarray_create(sizeof(char*));
    int waitsec = 0;

    for (int i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-d"))
            td->debug = 1;
        else if (!strcmp(argv[i], "-t"))
            td->nthreads = atoi(argv[++i]);
        else if (!strcmp(argv[i], "-f"))
            td->seg_decimate = (i+1 < argc && isdigit(argv[i+1][0])) ? atoi(argv[++i]) : 2;
        else if (!strcmp(argv[i], "-i"))
            maxiters = atoi(argv[++i]);
        else if (!strcmp(argv[i], "-r"))
            td->small_tag_refinement = 1;
        else if (!strcmp(argv[i], "-w"))
            waitsec = atoi(argv[++i]);
        else if (!strcmp(argv[i], "-b"))
            td->seg_sigma = atof(argv[++i]);
/*        else if (!strcmp(argv[i], "--family")) {
            char *fam = argv[++i];
            if (!strcmp(fam, "36h11"))
                td->tag_family = tag36h11_create();
            else if (!strcmp(fam, "36h10"))
                td->tag_family = tag36h10_create();
                } */
        else
            zarray_add(inputs, &argv[i]);
    }

    for (int iter = 0; iter < maxiters; iter++) {

        if (maxiters > 1)
            printf("iter %d / %d\n", iter + 1, maxiters);

        for (int input = 0; input < zarray_size(inputs); input++) {

            char *path;
            zarray_get(inputs, input, &path);
            printf("loading %s\n", path);
            image_u8_t *im = image_u8_create_from_pnm(path);
            if (im == NULL) {
                printf("couldn't find %s\n", path);
                continue;
            }

            zarray_t *detections = april_tag_detector_detect(td, im);

            for (int i = 0; i < zarray_size(detections); i++) {
                april_tag_detection_t *det;
                zarray_get(detections, i, &det);

                printf("detection %3d: id %4d, hamming %d, goodness %f\n", i, det->id, det->hamming, det->goodness);
                april_tag_detection_destroy(det);
            }

            zarray_destroy(detections);

            timeprofile_display(td->tp);
            printf("nedges: %d, nsegments: %d, nquads: %d\n", td->nedges, td->nsegments, td->nquads);

            image_u8_destroy(im);

            if (zarray_size(inputs) > 1 || iter > 0)
                sleep(waitsec);
        }
    }

    april_tag_detector_destroy(td);

    tag36h11_destroy(tf);
    return 0;
}
Exemple #19
0
loc_t* fit_lines(image_u32_t* im, node_t* n, vx_buffer_t* buf, metrics_t met, loc_t* out)
{
    // usleep(2000000);
    srand(time(NULL));
    // isolate valid entries 
    zarray_t* loc_arr = zarray_create(sizeof(loc_t*));
   
    for(int i = 0; i < im->height; i++) {
        if(n->sides[i].leftmost.x == im->width) continue;        // not apart of blob


        loc_t* loc = malloc(sizeof(loc_t));
        loc->x = n->sides[i].leftmost.x;
        loc->y = n->sides[i].leftmost.y;
        loc->valid = 0;
        zarray_add(loc_arr, &loc);
    }
    for(int i = 0; i < im->height; i++) {
        if(n->sides[i].rightmost.x == -1) continue;

        loc_t* loc = malloc(sizeof(loc_t));
        loc->x = n->sides[i].rightmost.x;
        loc->y = n->sides[i].rightmost.y;
        loc->valid = 0;
        zarray_add(loc_arr, &loc);
    }

    // printf("\n\nall\n");
    // for(int i = 0; i < zarray_size(loc_arr); i++)
    // {
    //     loc_t* p1;
    //     zarray_get(loc_arr, i, &p1);
    //     printf("(%d, %d)\n", p1->x, p1->y);
    // }
    // printf("\n\n");
    int iterations = 0;
    int best_score = 0;
    int lines_found = 0;
    loc_t line_match[8];
    int max_iterations = 500;
    while(lines_found < 2  && zarray_size(loc_arr) > met.num_outliers)      // still a lot of points left 
    {  
        if(iterations > max_iterations) break;
        // reset image and array
        // vx_object_t *vim = vxo_image_from_u32(im, 0, 0);
        // vx_buffer_add_back(buf, vxo_pix_coords(VX_ORIGIN_BOTTOM_LEFT, vim));
        add_arr_of_locs_to_buffer(loc_arr, buf, 1.0, vx_black, met);

        int num_outliers = met.num_outliers/met.consensus_accuracy;

        while(best_score < ((zarray_size(loc_arr) - num_outliers)/(4 - lines_found)))
        {
            reset_locs(loc_arr);
            // pick random sample (2 points)
            loc_t* p1;
            loc_t* p2;
            zarray_get(loc_arr, (rand()%zarray_size(loc_arr)), &p1);
            p2 = p1;
            while(p1 == p2)
                zarray_get(loc_arr, (rand()%zarray_size(loc_arr)), &p2);    // don't get same point

            // find consensus score of line from other points 
            // if inside consensus range add 1
            int tmp_score = 0;
            for(int j = 0; j < zarray_size(loc_arr); j++) {
                loc_t* tmp;
                zarray_get(loc_arr, j, &tmp);
                if(fabs(dist_from_point_to_line(p1, p2, tmp)) < (double)met.consensus_accuracy) 
                {

                    tmp->valid = 1;
                    // printf("dist: (%d, %d, %d)  %lf\n", tmp->x, tmp->y, tmp->valid,
                    //         fabs(dist_from_point_to_line(p1, p2, tmp)));
                    tmp_score++;
                }
            }
            // keep best line so far 
            if(tmp_score > best_score) {
                if(lines_found != 0) {      // if 2nd line intersects, throw it out and find another 
                    loc_t intersect = get_line_intersection(line_match[0], line_match[1], *p1, *p2);
                        if(in_range(im, intersect.x, intersect.y)) continue;
                }
                best_score = tmp_score;
                // printf("      score:%d,  %d,  %d  %lf\n", best_score, ((zarray_size(loc_arr)-1)/(4-lines_found)), 
                //                                     zarray_size(loc_arr), 10/met.std_dev_from_square);
                line_match[lines_found*2] = *p1;
                line_match[lines_found*2+1] = *p2;
            }
            iterations++;
            if(iterations > max_iterations) break;
        }
        // loc_t ext_lines[2];
        // extend_lines_to_edge_of_image(im, line_match[lines_found*2], line_match[lines_found*2+1], ext_lines);
        // add_line_to_buffer(im, buf, 2.0, ext_lines[0], ext_lines[1], vx_yellow);
        // delete all points associated with the found line
        zarray_t* endpoints_arr = zarray_create(sizeof(loc_t*));
        for(int i = 0; i < zarray_size(loc_arr); i++) {
            loc_t* tmp;
            zarray_get(loc_arr, i, &tmp);
            // printf("removed: (%d, %d, %d) \n", tmp->x, tmp->y, tmp->valid);
            if(tmp->valid) 
            {
                // add_circle_to_buffer(buf,  1.0, *tmp, vx_red);
                zarray_add(endpoints_arr, &tmp);
                zarray_remove_index(loc_arr, i, 0);
                i--;
            }
        }
        // find endpoints of line 
        loc_t ext_lines[2];
        extend_lines_to_edge_of_image(im, line_match[lines_found*2], line_match[lines_found*2+1], ext_lines);
        line_t endpoints = find_line_endpoints(endpoints_arr, &ext_lines[0], &ext_lines[1]);
        add_circle_to_buffer(buf,  2.0, endpoints.start, vx_red);
        add_circle_to_buffer(buf,  2.0, endpoints.end, vx_red);
        line_match[lines_found*2] = endpoints.start;
        line_match[lines_found*2+1] = endpoints.end;

        lines_found++;
        best_score = 0;
        // vx_buffer_swap(buf);
        // usleep(500000);
    }

    loc_t* ret = calloc(lines_found*2, sizeof(loc_t));
    for(int i = 0; i < lines_found; i++) {
        ret[i*2] = line_match[i*2];
        ret[i*2+1] = line_match[i*2+1]; 
        loc_t ext_lines[2];
        extend_lines_to_edge_of_image(im, line_match[i*2], line_match[i*2+1], ext_lines);
        add_line_to_buffer(im, buf, 2.0, ext_lines[0], ext_lines[1], vx_blue);
    }

    zarray_vmap(loc_arr, free);
    zarray_destroy(loc_arr);
    return(ret);

    // int corners_found = 0;
    // loc_t corners[4];
    // find_corners_from_lines(im,line_match, 4, &corners_found, corners);
    // for(int i = 0; i < corners_found; i++) {
    //     printf("(%d, %d)\n", corners[i].x, corners[i].y);
    //     add_circle_to_buffer(buf, 3.0, corners[i], vx_blue);
    // }

    // printf("(%d, %d) (%d, %d)   %lf\n", line_match[0].x, line_match[0].y, 
    //                                     line_match[1].x, line_match[1].y, 
    //                                     (double)best_score/N);

}
Exemple #20
0
// returns the 35 points associated to the test chart in [x1,y1,x2,y2] 
// format if there are more than 35 points will return NULL
matd_t* build_homography(image_u32_t* im, vx_buffer_t* buf, metrics_t met)
{
    frame_t frame = {{0,0}, {im->width-1, im->height-1},
                        {0,0}, {1,1}};
    int good_size = 0;
    zarray_t* blobs = zarray_create(sizeof(node_t));
    hsv_find_balls_blob_detector(im, frame, met, blobs, buf);

    // remove unqualified blobs
    if(met.qualify) {
        for(int i = 0; i < zarray_size(blobs); i++) {
            node_t n;
            zarray_get(blobs, i, &n);

            if(!blob_qualifies(im, &n, met, buf))
                zarray_remove_index(blobs, i, 0);
        }
    }
    if(zarray_size(blobs) == NUM_TARGETS ||zarray_size(blobs) == NUM_CHART_BLOBS) good_size = 1;

    zarray_sort(blobs, compare);
    int pix_array[zarray_size(blobs)*2];

    // iterate through
    int idx = 0;
    double size = 2.0;
    for(int i = 0; i < zarray_size(blobs); i++) {
        node_t n;
        zarray_get(blobs, i, &n);
        loc_t center = {    .x = n.ave_loc.x/n.num_children,
                            .y = n.ave_loc.y/n.num_children};
        loc_t parent = {    .x = n.id % im->stride,
                            .y = n.id / im->stride};


        if(buf != NULL) {
            add_circle_to_buffer(buf, size, center, vx_maroon);
            // add_circle_to_buffer(buf, size, parent, vx_olive);

            // add_sides_to_buffer(im, buf, 1.0, &n, vx_orange, met);
            loc_t* lp = fit_lines(im, &n, buf, met, NULL);
            if(lp != NULL) {
                // printf("(%d, %d) (%d, %d) (%d, %d) (%d, %d) \n",
                //         lp[0].x, lp[0].y, lp[1].x, lp[1].y, lp[2].x, lp[2].y, lp[3].x, lp[3].y);
                loc_t intersect = get_line_intersection(lp[0], lp[1], lp[2], lp[3]);
                if(in_range(im, intersect.x, intersect.y)) {
                    loc_t ext_lines[2];
                    extend_lines_to_edge_of_image(im, intersect, center, ext_lines);
                    add_line_to_buffer(im, buf, 2.0, ext_lines[0], ext_lines[1], vx_blue);                
                }
                for(int i = 0; i < 4; i++) {
                    pix_array[i*2] = lp[i].x;
                    pix_array[i*2+1] = lp[i].y;
                    add_circle_to_buffer(buf, 3.0, lp[i], vx_orange);
                }
            }



            free(n.sides);

            // loc_t corners[4] = {{n.box.right, n.box.top},
            //                     {n.box.right, n.box.bottom},
            //                     {n.box.left, n.box.bottom},
            //                     {n.box.left, n.box.top}};
            // print extremes of box
            // if(1) {
            //     add_circle_to_buffer(buf, size, corners[0], vx_green);
            //     add_circle_to_buffer(buf, size, corners[1], vx_yellow);
            //     add_circle_to_buffer(buf, size, corners[2], vx_red);
            //     add_circle_to_buffer(buf, size, corners[3], vx_blue);
            //     for(int j = 0; j < 4; j++) {
            //         // add_circle_to_buffer(buf, size, corners[j], vx_maroon);
            //     }
            // }
        }
    }

    matd_t* H;
    H = dist_homography(pix_array, NUM_TARGETS);

    // if(0) {//zarray_size(blobs) == NUM_CHART_BLOBS){
    //     H = dist_homography(pix_array, NUM_CHART_BLOBS);
    // }
    // else if(zarray_size(blobs) == NUM_TARGETS){
    //     H = dist_homography(pix_array, NUM_TARGETS);
    //     if(met.add_lines) connect_lines(blobs, buf);
    // }
    // else {
    //     if(met.dothis)
    //         printf("num figures: %d\n", zarray_size(blobs));
    //     return(NULL);
    // }

    // make projected points
    // project_measurements_through_homography(H, buf, blobs, zarray_size(blobs));
    zarray_destroy(blobs);

    return(H);
}


/*
{ R00, R01, R02, TX,
   R10, R11, R12, TY,
   R20, R21, R22, TZ,
    0, 0, 0, 1 });
*/
double get_rotation(const char* axis, matd_t* H)
{
    double cosine, sine, theta;

    if(strncmp(axis,"x", 1)) {
        cosine = MATD_EL(H, 1, 1);
        sine = MATD_EL(H, 2, 1);
    }
    else if(strncmp(axis,"y", 1)) {
        cosine = MATD_EL(H, 0, 0);
        sine = MATD_EL(H, 0, 2);
    }
    else if(strncmp(axis,"z", 1)) {
        cosine = MATD_EL(H, 0, 0);
        sine = MATD_EL(H, 1, 0);
    }
    else assert(0);

    theta = atan2(sine, cosine);
    return(theta);
}

// if buf is NULL, will not fill with points of the homography
void take_measurements(image_u32_t* im, vx_buffer_t* buf, metrics_t met)
{
    // form homography
    matd_t* H = build_homography(im, buf, met);
    if(H == NULL) return;

    // get model view from homography
    matd_t* Model = homography_to_pose(H, 654, 655, 334, 224);
    // printf("\n");
    // matd_print(H, matrix_format);
    // printf("\n\n");
    // printf("model:\n");
    // matd_print(Model, "%15f");
    // printf("\n\n");
    // matd_print(matd_op("M^-1",Model), matrix_format);
    // printf("\n");
    // extrapolate metrics from model view
    double TX = MATD_EL(Model, 0, 3);
    double TY = MATD_EL(Model, 1, 3);
    double TZ = MATD_EL(Model, 2, 3);

    // double rot_x = get_rotation("x", H);
    // double rot_y = get_rotation("y", H);
    // double rot_z = get_rotation("z", H);

    double cosine = MATD_EL(Model, 0, 0);

    double rot_z = acos(cosine) * 180/1.5 - 180;


    cosine = MATD_EL(Model, 2, 2);
    double rot_x = asin(cosine) * 90/1.3 + 90;

    cosine = MATD_EL(Model, 1, 1);
    double rot_y = asin(cosine);



    char str[200];
    sprintf(str, "<<#00ffff,serif-30>> DIST:%lf  Offset:(%lf, %lf)\n rot: (%lf, %lf, %lf)\n", 
                TZ, TX, TY, rot_x, rot_y, rot_z);
    vx_object_t *text = vxo_text_create(VXO_TEXT_ANCHOR_BOTTOM_LEFT, str); 
    vx_buffer_add_back(buf, vxo_pix_coords(VX_ORIGIN_BOTTOM_LEFT, text));

    // printf("dist: %lf   cos:%lf  angle: %lf\n", TZ, cosine, theta);
}
Exemple #21
0
// this loop tries to run at X fps, and issue render commands
static void * render_loop(void * foo)
{
    state_t * state = foo;
    if (verbose)printf("Starting render thread!\n");

    uint64_t render_count = 0;
    uint64_t last_mtime = vx_mtime();
    double avgDT = 1.0f/state->target_frame_rate;
    uint64_t avg_loop_us = 3000; // initial render time guess
    while (state->rendering) {
        int64_t sleeptime = (1000000 / state->target_frame_rate) - (int64_t) avg_loop_us;
        if (sleeptime > 0)
            usleep(sleeptime); // XXX fix to include render time

        // Diagnostic tracking
        uint64_t mtime_start = vx_mtime(); // XXX
        avgDT = avgDT*.9 + .1 * (mtime_start - last_mtime)/1000;
        last_mtime = mtime_start;
        render_count++;

        if (verbose) {
            if (render_count % 100 == 0)
                printf("Average render DT = %.3f FPS = %.3f avgloopus %"PRIu64" sleeptime = %"PRIi64"\n",
                       avgDT, 1.0/avgDT, avg_loop_us, sleeptime);
        }

        // prep the render data
        render_buffer_t rbuf;
        rbuf.state = state;
        rbuf.width = gtku_image_pane_get_width(state->imagePane);
        rbuf.height = gtku_image_pane_get_height(state->imagePane);
        if (rbuf.width == 0 && rbuf.height == 0)
            continue; // if the viewport is 0,0

        // smartly reuse, or reallocate the output pixel buffer when resizing occurs
        GdkPixbuf * pixbuf = state->pixbufs[state->cur_pb_idx];
        if (pixbuf == NULL || gdk_pixbuf_get_width(pixbuf) != rbuf.width || gdk_pixbuf_get_height(pixbuf) != rbuf.height) {
            if (pixbuf != NULL) {
                g_object_unref(pixbuf);
                free(state->pixdatas[state->cur_pb_idx]);
            }

            state->pixdatas[state->cur_pb_idx] = malloc(rbuf.width*rbuf.height*3); // can't stack allocate, can be too big (retina)
            pixbuf = gdk_pixbuf_new_from_data(state->pixdatas[state->cur_pb_idx], GDK_COLORSPACE_RGB, FALSE, 8,
                                              rbuf.width, rbuf.height, rbuf.width*3, NULL, NULL); // no destructor fn for pix data, handle manually
            state->pixbufs[state->cur_pb_idx] = pixbuf;
        }

        // second half of init:
        rbuf.out_buf = gdk_pixbuf_get_pixels(pixbuf);
        rbuf.format = GL_RGB;
        rbuf.rendered = 0;

        // 1 compute all the viewports
        render_info_t * rinfo = render_info_create();
        rinfo->viewport[0] = rinfo->viewport[1] = 0;
        rinfo->viewport[2] = rbuf.width;
        rinfo->viewport[3] = rbuf.height;

        {
            zhash_iterator_t itr;
            uint32_t layer_id = 0;
            layer_info_t * linfo = NULL;
            zhash_iterator_init(state->layer_info_map, &itr);
            while(zhash_iterator_next(&itr, &layer_id, &linfo)){
                zarray_add(rinfo->layers, &linfo);
            }
            zarray_sort(rinfo->layers, zvx_layer_info_compare);
        }

        zarray_t * fp = zarray_create(sizeof(matd_t*));

        matd_t *mm = matd_create(4,4); zarray_add(fp, &mm);
        matd_t *pm = matd_create(4,4); zarray_add(fp, &pm);

        pthread_mutex_lock(&state->mutex);
        for (int i = 0; i < zarray_size(rinfo->layers); i++) {
            layer_info_t *linfo = NULL;
            zarray_get(rinfo->layers, i, &linfo);

            int * viewport = vx_viewport_mgr_get_pos(linfo->vp_mgr, rinfo->viewport, mtime_start);
            vx_camera_pos_t *pos = default_cam_mgr_get_cam_pos(linfo->cam_mgr, viewport, mtime_start);

            // store viewport, pos
            zhash_put(rinfo->layer_positions, &linfo->layer_id, &viewport, NULL, NULL);
            zhash_put(rinfo->camera_positions, &linfo->layer_id, &pos, NULL, NULL);

            // feed the actual camera/projection matrix to the gl side
            vx_camera_pos_model_matrix(pos,mm->data);
            vx_camera_pos_projection_matrix(pos, pm->data);

            matd_t * pmmm = matd_multiply(pm,mm); zarray_add(fp, &pmmm);

            float pm16[16];
            vx_util_copy_floats(pmmm->data, pm16, 16);

            float eye3[16];
            vx_util_copy_floats(pos->eye, eye3, 3);

            vx_gl_renderer_set_layer_render_details(state->glrend, linfo->layer_id, viewport, pm16, eye3);
        }

        // 2 Render the data
        task_thread_schedule_blocking(gl_thread, render_task, &rbuf);

        render_info_t * old = state->last_render_info;
        state->last_render_info = rinfo;

        pthread_mutex_unlock(&state->mutex);


        // 3 if a render occurred, then swap gtk buffers
        if (rbuf.rendered) {

            // point to the correct buffer for the next render:
            state->cur_pb_idx = (state->cur_pb_idx +1 ) % 2;

            // flip y coordinate in place:
            vx_util_flipy(rbuf.width*3, rbuf.height, rbuf.out_buf);

            // swap the image's backing buffer
            g_object_ref(pixbuf); // XXX Since gtku always unrefs with each of these calls, increment accordingly
            gtku_image_pane_set_buffer(state->imagePane, pixbuf);
        }

        // 3.1 If a movie is in progress, also need to serialize the frame
        pthread_mutex_lock(&state->movie_mutex);
        if (state->movie_file != NULL) {

            int last_idx = (state->cur_pb_idx + 1) % 2;
            GdkPixbuf * pb = state->pixbufs[last_idx];

            movie_frame_t * movie_img = calloc(1, sizeof(movie_frame_t));
            movie_img->mtime = mtime_start;
            movie_img->width = gdk_pixbuf_get_width(pb);
            movie_img->height = gdk_pixbuf_get_height(pb);
            movie_img->stride = 3*movie_img->width;
            movie_img->buf = malloc(movie_img->stride*movie_img->height);
            memcpy(movie_img->buf, state->pixdatas[last_idx], movie_img->stride*movie_img->height);


            // Alloc in this thread, dealloc in movie thread
            zarray_add(state->movie_pending, & movie_img);

            pthread_cond_signal(&state->movie_cond);

        }
        pthread_mutex_unlock(&state->movie_mutex);


        // cleanup
        if (old)
            render_info_destroy(old);
        zarray_vmap(fp, matd_destroy);
        zarray_destroy(fp);


        uint64_t mtime_end = vx_mtime();
        avg_loop_us = (uint64_t)(.5*avg_loop_us + .5 * 1000 * (mtime_end - mtime_start));
    }
    if (verbose) printf("Render thread exiting\n");

    pthread_exit(NULL);

}
Exemple #22
0
vx_camera_pos_t * default_cam_mgr_get_cam_pos(default_cam_mgr_t * state, int * viewport, uint64_t mtime)
{
    vx_camera_pos_t * p = calloc(1, sizeof(vx_camera_pos_t));
    memcpy(p->viewport, viewport, 4*sizeof(int));

    p->perspective_fovy_degrees = state->perspective_fovy_degrees;
    p->zclip_near = state->zclip_near;
    p->zclip_far = state->zclip_far;

    // process a fit command if necessary:
    if (state->fit != NULL) {
        fit_t * f = state->fit;

        // consume the fit command
        state->fit = NULL; // XXX minor race condition, could lose a fit cmd

        // XXX We can probably do better than this using the viewport...
        state->lookat1[0] = (f->xy0[0] + f->xy1[0]) / 2;
        state->lookat1[1] = (f->xy0[1] + f->xy1[1]) / 2;
        state->lookat1[2] = 0;

        // dimensions of fit
        double Fw = f->xy1[0] - f->xy0[0];
        double Fh = f->xy1[1] - f->xy0[1];

        // aspect ratios
        double Far = Fw / Fh;
        double Var = p->viewport[2] * 1.0 / p->viewport[3];

        double tAngle = tan(p->perspective_fovy_degrees/2*M_PI/180.0);
        double height = fabs(0.5 * (Var > Far ? Fh : Fw / Var) / tAngle);

        state->eye1[0] = state->lookat1[0];
        state->eye1[1] = state->lookat1[1];
        state->eye1[2] = height;

        state->up1[0] = 0;
        state->up1[1] = 1;
        state->up1[2] = 0;

        state->mtime1 = f->mtime;

        free(f);
    }

    if (mtime > state->mtime1) {
        memcpy(p->eye, state->eye1, 3*sizeof(double));
        memcpy(p->up, state->up1, 3*sizeof(double));
        memcpy(p->lookat, state->lookat1, 3*sizeof(double));
        p->perspectiveness = state->perspectiveness1;
    } else  if (mtime <= state->mtime0) {
        memcpy(p->eye, state->eye0, 3*sizeof(double));
        memcpy(p->up, state->up0, 3*sizeof(double));
        memcpy(p->lookat, state->lookat0, 3*sizeof(double));
        p->perspectiveness = state->perspectiveness0;
    } else {
        double alpha1 = ((double) mtime - state->mtime0) / (state->mtime1 - state->mtime0);
        double alpha0 = 1.0 - alpha1;

        scaled_combination(state->eye0,    alpha0, state->eye1,    alpha1, p->eye,    3);
        scaled_combination(state->up0,     alpha0, state->up1,     alpha1, p->up,     3);
        scaled_combination(state->lookat0, alpha0, state->lookat1, alpha1, p->lookat, 3);
        p->perspectiveness = state->perspectiveness0*alpha0 + state->perspectiveness1*alpha1;

        // Tweak so eye-to-lookat is the right distance
        {
            zarray_t * fp = zarray_create(sizeof(matd_t*));

            matd_t * eye = matd_create_data(3,1, p->eye); zarray_add(fp, &eye);
            matd_t * lookat = matd_create_data(3,1, p->lookat); zarray_add(fp, &lookat);
            matd_t * up = matd_create_data(3,1, p->up); zarray_add(fp, &up);

            matd_t * eye0 = matd_create_data(3,1, state->eye0); zarray_add(fp, &eye0);
            matd_t * lookat0 = matd_create_data(3,1, state->lookat0); zarray_add(fp, &lookat0);
            matd_t * up0 = matd_create_data(3,1, state->up0); zarray_add(fp, &up0);

            matd_t * eye1 = matd_create_data(3,1, state->eye1); zarray_add(fp, &eye1);
            matd_t * lookat1 = matd_create_data(3,1, state->lookat1); zarray_add(fp, &lookat1);
            matd_t * up1 = matd_create_data(3,1, state->up1); zarray_add(fp, &up1);


            double dist0 = matd_vec_dist(eye0, lookat0);
            double dist1 = matd_vec_dist(eye1, lookat1);

            matd_t * dist = matd_create_scalar(dist0*alpha0 + dist1*alpha1); zarray_add(fp, &dist);

            matd_t * eye2p = matd_subtract(eye,lookat); zarray_add(fp, &eye2p);
            eye2p = matd_vec_normalize(eye2p); zarray_add(fp, &eye2p);

            eye = matd_op("M + (M*M)", lookat, eye2p, dist);

            // Only modified eye
            memcpy(p->eye, eye->data, 3*sizeof(double));

            zarray_vmap(fp, matd_destroy);

            zarray_destroy(fp);
        }
    }

    // Need to do more fixup depending on interface mode!
    {
        if (state->interface_mode <= 2.0) {
            // stack eye on lookat:
            p->eye[0] = p->lookat[0];
            p->eye[1] = p->lookat[1];
            p->lookat[2] = 0;

            // skip fabs() for ENU/NED compat
            //p->eye[2] = fabs(p->eye[2]);


            {
                matd_t * up = matd_create_data(3,1, p->up);
                up->data[2] = 0; // up should never point in Z
                matd_t * up_norm = matd_vec_normalize(up);

                memcpy(p->up, up_norm->data, sizeof(double)*3);
                matd_destroy(up);
                matd_destroy(up_norm);
            }

        } else if (state->interface_mode == 2.5) {
            zarray_t * fp = zarray_create(sizeof(matd_t*));

            matd_t * eye = matd_create_data(3,1, p->eye); zarray_add(fp, &eye);
            matd_t * lookat = matd_create_data(3,1, p->lookat); zarray_add(fp, &lookat);
            matd_t * up = matd_create_data(3,1, p->up); zarray_add(fp, &up);

            lookat->data[2] = 0.0;

            // Level horizon
            matd_t * dir = matd_subtract(lookat, eye); zarray_add(fp, &dir);
            matd_t * dir_norm = matd_vec_normalize(dir); zarray_add(fp, &dir_norm);
            matd_t * left = matd_crossproduct(up, dir_norm); zarray_add(fp, &left);
            left->data[2] = 0.0;

            left = matd_vec_normalize(left); zarray_add(fp, &left);


            // Don't allow upside down
            //up->data[2] = fmax(0.0, up->data[2]); // XXX NED?

            // Find an 'up' direction perpendicular to left
            matd_t * dot_scalar = matd_create_scalar(matd_vec_dot_product(up, left)); zarray_add(fp, &dot_scalar);
            up = matd_op("M - (M*M)", up,  left, dot_scalar); zarray_add(fp, &up);
            up = matd_vec_normalize(up); zarray_add(fp, &up);

            // Now find eye position by computing new lookat dir
            matd_t * eye_dir = matd_crossproduct(up, left); zarray_add(fp, &eye_dir);

            matd_t *eye_dist_scalar = matd_create_scalar(matd_vec_dist(eye, lookat)); zarray_add(fp, &eye_dist_scalar);

            eye = matd_op("M + (M*M)", lookat, eye_dir, eye_dist_scalar); zarray_add(fp, &eye);

            // export results back to p:
            memcpy(p->eye, eye->data, sizeof(double)*3);
            memcpy(p->lookat, lookat->data, sizeof(double)*3);
            memcpy(p->up, up->data, sizeof(double)*3);

            zarray_vmap(fp, matd_destroy);
            zarray_destroy(fp);
        }
    }

    // Fix up for bad zoom
    if (1) {
        matd_t * eye = matd_create_data(3,1, p->eye);
        matd_t * lookat = matd_create_data(3,1, p->lookat);
        matd_t * up = matd_create_data(3,1, p->up);

        matd_t * lookeye = matd_subtract(lookat, eye);
        matd_t * lookdir = matd_vec_normalize(lookeye);
        double dist =  matd_vec_dist(eye, lookat);
        dist  = fmin(state->zclip_far / 3.0, dist);
        dist  = fmax(state->zclip_near * 3.0, dist);

        matd_scale_inplace(lookdir, dist);

        matd_t * eye_fixed = matd_subtract(lookat, lookdir);

        memcpy(p->eye, eye_fixed->data, sizeof(double)*3);

        matd_destroy(eye);
        matd_destroy(lookat);
        matd_destroy(up);
        matd_destroy(lookeye);
        matd_destroy(lookdir);
        matd_destroy(eye_fixed);
    }

    // copy the result back into 'state'
    {
        memcpy(state->eye0, p->eye, 3*sizeof(double));
        memcpy(state->up0, p->up, 3*sizeof(double));
        memcpy(state->lookat0, p->lookat, 3*sizeof(double));
        state->perspectiveness0 = p->perspectiveness;
        state->mtime0 = mtime;
    }

    return p;
}
Exemple #23
0
url_parser_t *
url_parser_create (const char *s)
{
    url_parser_t *urlp = calloc(1, sizeof(*urlp));

    int slen = strlen(s);

    urlp->keys = zarray_create(sizeof(char*));
    urlp->vals = zarray_create(sizeof(char*));

    int hostpos = strpos(s, "://") + 3;
    urlp->protocol = strndup(s, hostpos);

    // extract the hostport. it's between the slashpos and terminated by
    // either the third slash or a question mark or end of string.
    int hostportend = strposat(s, "/", hostpos);
    if (hostportend < 0)
        hostportend = strposat(s, "?", hostpos);
    if (hostportend < 0)
        hostportend = slen;

    char *hostport = strndup(&s[hostpos], hostportend-hostpos);

    // extract the path: it's between the 3rd slash and terminated by
    // either a ? or the end.
    int thirdslashpos = strposat(s, "/", hostpos);
    if (thirdslashpos >= 0) {
        int endpathpos = strposat(s, "?", thirdslashpos);
        if (endpathpos < 0)
            endpathpos = slen;

        urlp->path = strndup(&s[thirdslashpos], endpathpos - thirdslashpos );
    } else {
        urlp->path = strdup("/");
    }

    // e.g. "/search?q=a"
    int parampos = strpos(s, "?");

    while (parampos >= 0) {
        int nextparampos = strposat(s, "&", parampos+1);

        int eqpos = strposat(s, "=", parampos+1);
        char *key = strndup(&s[parampos+1], eqpos - parampos-1);
        char *val = strndup(&s[eqpos+1], nextparampos < 0 ? 9999 : nextparampos - eqpos - 1);

        zarray_add(urlp->keys, &key);
        zarray_add(urlp->vals, &val);

        parampos = nextparampos;
    }

    // chop up hostport into host and port.
    int colonpos = strpos(hostport, ":");
    if (colonpos >= 0) {
        urlp->host = strndup(hostport, colonpos);
        urlp->port = atoi(&hostport[colonpos+1]);
    } else {
        urlp->host = strdup(hostport);
        urlp->port = -1;
    }

    free(hostport);

    return urlp;
}
zarray_t *apriltag_quad_thresh(apriltag_detector_t *td, image_u8_t *im)
{
    ////////////////////////////////////////////////////////
    // step 1. threshold the image, creating the edge image.

    int w = im->width, h = im->height, s = im->stride;

    image_u8_t *threshim = threshold(td, im);
    assert(threshim->stride == s);

    image_u8_t *edgeim = image_u8_create(w, h);

    if (1) {
        image_u8_t *sumim = image_u8_create(w, h);

        // apply a horizontal sum kernel of width 3
        for (int y = 0; y < h; y++) {
            for (int x = 1; x+1 < w; x++) {

                sumim->buf[y*s + x] =
                    threshim->buf[y*s + x - 1] +
                    threshim->buf[y*s + x + 0] +
                    threshim->buf[y*s + x + 1];
            }
        }
        timeprofile_stamp(td->tp, "sumim");

        // deglitch
        if (td->qtp.deglitch) {
            for (int y = 1; y+1 < h; y++) {
                for (int x = 1; x+1 < w; x++) {
                    // edge: black pixel next to white pixel
                    if (threshim->buf[y*s + x] == 0 &&
                        sumim->buf[y*s + x - s] + sumim->buf[y*s + x] + sumim->buf[y*s + x + s] == 8) {
                        threshim->buf[y*s + x] = 1;
                        sumim->buf[y*s + x - 1]++;
                        sumim->buf[y*s + x + 0]++;
                        sumim->buf[y*s + x + 1]++;
                    }

                    if (threshim->buf[y*s + x] == 1 &&
                        sumim->buf[y*s + x - s] + sumim->buf[y*s + x] + sumim->buf[y*s + x + s] == 1) {
                        threshim->buf[y*s + x] = 0;
                        sumim->buf[y*s + x - 1]--;
                        sumim->buf[y*s + x + 0]--;
                        sumim->buf[y*s + x + 1]--;
                   }
                }
            }

            timeprofile_stamp(td->tp, "deglitch");
        }

        // apply a vertical sum kernel of width 3; check if any
        // over-threshold pixels are adjacent to an under-threshold
        // pixel.
        //
        // There are two types of edges: white pixels neighboring a
        // black pixel, and black pixels neighboring a white pixel. We
        // label these separately.  (Values 0xc0 and 0x3f are picked
        // such that they add to 255 (see below) and so that they can be
        // viewed as pixel intensities for visualization purposes.)
        //
        // symmetry of detection. We don't want to use JUST "black
        // near white" (or JUST "white near black"), because that
        // biases the detection towards one side of the edge. This
        // measurably reduces detection performance.
        //
        // On large tags, we could treat "neighbor" pixels the same
        // way. But on very small tags, there may be other edges very
        // near the tag edge. Since each of these edges is effectively
        // two pixels thick (the white pixel near the black pixel, and
        // the black pixel near the white pixel), it becomes likely
        // that these two nearby edges will actually touch.
        //
        // A partial solution to this problem is to define edges to be
        // adjacent white-near-black and black-near-white pixels.
        //

        for (int y = 1; y+1 < h; y++) {
            for (int x = 1; x+1 < w; x++) {
                if (threshim->buf[y*s + x] == 0) {
                    // edge: black pixel next to white pixel
                    if (sumim->buf[y*s + x - s] + sumim->buf[y*s + x] + sumim->buf[y*s + x + s] > 0)
                        edgeim->buf[y*s + x] = 0xc0;
                } else {
                    // edge: white pixel next to black pixel when both
                    // edge types are on, we get less bias towards one
                    // side of the edge.
                    if (sumim->buf[y*s + x - s] + sumim->buf[y*s + x] + sumim->buf[y*s + x + s] < 9)
                        edgeim->buf[y*s + x] = 0x3f;
                }
            }
        }

        if (td->debug) {
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    threshim->buf[y*s + x] *= 255;
                }
            }

            image_u8_write_pnm(threshim, "debug_threshold.pnm");
            image_u8_write_pnm(edgeim, "debug_edge.pnm");
//            image_u8_destroy(edgeim2);
        }

        image_u8_destroy(threshim);
        image_u8_destroy(sumim);
    }

    timeprofile_stamp(td->tp, "edges");

    ////////////////////////////////////////////////////////
    // step 2. find connected components.

    unionfind_t *uf = unionfind_create(w * h);

    for (int y = 1; y < h - 1; y++) {
        for (int x = 1; x < w -1; x++) {
            uint8_t v = edgeim->buf[y*s + x];
            if (v==0)
                continue;

            // (dx,dy) pairs for 8 connectivity:
            //          (REFERENCE) (1, 0)
            // (-1, 1)    (0, 1)    (1, 1)
            //
            // i.e., the minimum value of dx should be:
            //   y=0:   1
            //   y=1:  -1
            for (int dy = 0; dy <= 1; dy++) {
                for (int dx = 1-2*dy; dx <= 1; dx++) {
                    if (edgeim->buf[(y+dy)*s + (x+dx)] == v) {
                        unionfind_connect(uf, y*w + x, (y+dy)*w + x + dx);
                    }
                }
            }
        }
    }

    timeprofile_stamp(td->tp, "unionfind");

    zhash_t *clustermap = zhash_create(sizeof(uint64_t), sizeof(zarray_t*),
                                       zhash_uint64_hash, zhash_uint64_equals);

    for (int y = 1; y < h-1; y++) {
        for (int x = 1; x < w-1; x++) {

            uint8_t v0 = edgeim->buf[y*s + x];
            if (v0 == 0)
                continue;

            uint64_t rep0 = unionfind_get_representative(uf, y*w + x);

            // 8 connectivity. (4 neighbors to check).
//            for (int dy = 0; dy <= 1; dy++) {
//                for (int dx = 1-2*dy; dx <= 1; dx++) {

            // 4 connectivity. (2 neighbors to check)
            for (int n = 1; n <= 2; n++) {
                int dy = n & 1;
                int dx = (n & 2) >> 1;

                uint8_t v1 = edgeim->buf[(y+dy)*s + x + dx];
                if (v0 + v1 != 255)
                    continue;
                uint64_t rep1 = unionfind_get_representative(uf, (y+dy)*w + x+dx);

                uint64_t clusterid;
                if (rep0 < rep1)
                    clusterid = (rep1 << 32) + rep0;
                else
                    clusterid = (rep0 << 32) + rep1;

                zarray_t *cluster = NULL;
                if (!zhash_get(clustermap, &clusterid, &cluster)) {
                    cluster = zarray_create(sizeof(struct pt));
                    zhash_put(clustermap, &clusterid, &cluster, NULL, NULL);
                }

                // NB: We will add some points multiple times to a
                // given cluster.  I don't know an efficient way to
                // avoid that here; we remove them later on when we
                // sort points by pt_compare_theta.
                if (1) {
                    struct pt p = { .x = x, .y = y};
                    zarray_add(cluster, &p);
                }
                if (1) {
                    struct pt p = { .x = x+dx, .y = y+dy};
                    zarray_add(cluster, &p);
                }
            }
        }
    }

    // make segmentation image.
    if (td->debug) {
        image_u8_t *d = image_u8_create(w, h);
        assert(d->stride == s);

        uint8_t *colors = (uint8_t*) calloc(w*h, 1);

        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                uint32_t v = unionfind_get_representative(uf, y*w+x);
                uint32_t sz = unionfind_get_set_size(uf, y*w+x);
                if (sz < td->qtp.min_cluster_pixels)
                    continue;

                uint8_t color = colors[v];

                if (color == 0) {
                    const int bias = 20;
                    color = bias + (random() % (255-bias));
                    colors[v] = color;
                }

                float mix = 0.7;
                mix = 1.0;
                d->buf[y*d->stride + x] = mix*color + (1-mix)*im->buf[y*im->stride + x];
            }
        }

        free(colors);

        image_u8_write_pnm(d, "debug_segmentation.pnm");
        image_u8_destroy(d);
    }

    timeprofile_stamp(td->tp, "make clusters");


    ////////////////////////////////////////////////////////
    // step 3. process each connected component.

    zarray_t *clusters = zhash_values(clustermap);
    zhash_destroy(clustermap);

    zarray_t *quads = zarray_create(sizeof(struct quad));

    int sz = zarray_size(clusters);
    int chunksize = 1 + sz / (APRILTAG_TASKS_PER_THREAD_TARGET * td->nthreads);
    struct quad_task tasks[sz / chunksize + 1];

    int ntasks = 0;
    for (int i = 0; i < sz; i += chunksize) {
        tasks[ntasks].td = td;
        tasks[ntasks].cidx0 = i;
        tasks[ntasks].cidx1 = imin(sz, i + chunksize);
        tasks[ntasks].h = h;
        tasks[ntasks].w = w;
        tasks[ntasks].quads = quads;
        tasks[ntasks].clusters = clusters;
        tasks[ntasks].im = im;

        workerpool_add_task(td->wp, do_quad_task, &tasks[ntasks]);
        ntasks++;
    }

    workerpool_run(td->wp);

    timeprofile_stamp(td->tp, "fit quads to clusters");

    if (td->debug) {
        FILE *f = fopen("debug_lines.ps", "w");
        fprintf(f, "%%!PS\n\n");

        image_u8_t *im2 = image_u8_copy(im);
        image_u8_darken(im2);
        image_u8_darken(im2);

        // assume letter, which is 612x792 points.
        double scale = fmin(612.0/im->width, 792.0/im2->height);
        fprintf(f, "%.15f %.15f scale\n", scale, scale);
        fprintf(f, "0 %d translate\n", im2->height);
        fprintf(f, "1 -1 scale\n");

        postscript_image(f, im);

        for (int i = 0; i < zarray_size(quads); i++) {
            struct quad *q;
            zarray_get_volatile(quads, i, &q);

            float rgb[3];
            int bias = 100;

            for (int i = 0; i < 3; i++)
                rgb[i] = bias + (random() % (255-bias));

            fprintf(f, "%f %f %f setrgbcolor\n", rgb[0]/255.0f, rgb[1]/255.0f, rgb[2]/255.0f);
            fprintf(f, "%.15f %.15f moveto %.15f %.15f lineto %.15f %.15f lineto %.15f %.15f lineto %.15f %.15f lineto stroke\n",
                    q->p[0][0], q->p[0][1],
                    q->p[1][0], q->p[1][1],
                    q->p[2][0], q->p[2][1],
                    q->p[3][0], q->p[3][1],
                    q->p[0][0], q->p[0][1]);
        }

        fclose(f);
    }

//        printf("  %d %d %d %d\n", indices[0], indices[1], indices[2], indices[3]);

/*
        if (td->debug) {
            for (int i = 0; i < 4; i++) {
            int i0 = indices[i];
                int i1 = indices[(i+1)&3];

                if (i1 < i0)
                    i1 += zarray_size(cluster);

                for (int j = i0; j <= i1; j++) {
                    struct pt *p;
                    zarray_get_volatile(cluster, j % zarray_size(cluster), &p);

                    edgeim->buf[p->y*edgeim->stride + p->x] = 30+64*i;
                }
            }
            } */

    unionfind_destroy(uf);

    for (int i = 0; i < zarray_size(clusters); i++) {
        zarray_t *cluster;
        zarray_get(clusters, i, &cluster);
        zarray_destroy(cluster);
    }

    zarray_destroy(clusters);

    image_u8_destroy(edgeim);

    return quads;
}
Exemple #25
0
zarray_t *g2d_polygon_create_empty()
{
    return zarray_create(sizeof(double[2]));
}
Exemple #26
0
// creates and returns a zarray(double[2]). The resulting polygon is
// CCW and implicitly closed. Unnecessary colinear points are omitted.
zarray_t *g2d_convex_hull(const zarray_t *points)
{
    zarray_t *hull = zarray_create(sizeof(double[2]));

    // gift-wrap algorithm.

    // step 1: find left most point.
    int insz = zarray_size(points);

    double *pleft = NULL;
    for (int i = 0; i < insz; i++) {
        double *p;
        zarray_get_volatile(points, i, &p);

        if (pleft == NULL || p[0] < pleft[0])
            pleft = p;
    }

    zarray_add(hull, pleft);

    // step 2. gift wrap. Keep searching for points that make the
    // smallest-angle left-hand turn. This implementation is carefully
    // written to use only addition/subtraction/multiply. No division
    // or sqrts. This guarantees exact results for integer-coordinate
    // polygons (no rounding/precision problems).
    double *p = pleft;

    while (1) {
        double *q = NULL;
        double n0 = 0, n1 = 0; // the normal to the line (p, q) (not
                       // necessarily unit length).

        // Search for the point q for which the line (p,q) is most "to
        // the right of" the other points. (i.e., every time we find a
        // point that is to the right of our current line, we change
        // lines.)
        for (int i = 0; i < insz; i++) {
            double *thisq;
            zarray_get_volatile(points, i, &thisq);

            if (thisq == p)
                continue;

            if (q == NULL) {
                q = thisq;
                n0 = q[1] - p[1];
                n1 = -q[0] + p[0];
            } else {
                // is point thisq RIGHT OF line (p, q)?

                double e0 = thisq[0] - p[0], e1 = thisq[1] - p[1];
                double dot = e0*n0 + e1*n1;

                if (dot > 0) {
                    q = thisq;
                    n0 = q[1] - p[1];
                    n1 = -q[0] + p[0];
                }
            }
        }

        // loop completed?
        if (q == pleft)
            break;

        int colinear = 0;

        // is this new point colinear with the last two?
        if (zarray_size(hull) > 1) {
            double *o;
            zarray_get_volatile(hull, zarray_size(hull) - 2, &o);

            double e0 = o[0] - p[0];
            double e1 = o[1] - p[1];

            if (n0*e0 + n1*e1 == 0)
                colinear = 1;
        }

        // if it is colinear, overwrite the last one.
        if (colinear)
            zarray_set(hull, zarray_size(hull)-1, q, NULL);
        else
            zarray_add(hull, q);

        p = q;
    }

    return hull;
}
Exemple #27
0
vx_object_t * vxo_objmtl(const char * obj_filename)
{
    int  texture_flag = 0;

    FILE * fp_obj = fopen(obj_filename, "r");
    if (fp_obj == NULL)
        return NULL;

    #define LNSZ 1024
    char line_buffer[LNSZ];

    // Store 3D vertices by value
    zarray_t * vertices = zarray_create(sizeof(float)*3);
    zarray_t * textures = zarray_create(sizeof(float)*3);
    zarray_t * normals = zarray_create(sizeof(float)*3);

    wav_group_t * cur_group = NULL;
    zarray_t * group_list = zarray_create(sizeof(wav_group_t*));

    zhash_t * mtl_map = NULL; // created on reading mtllib entry
    //zhash_t * obj_map = zhash_create(sizeof(char*), sizeof(vx_object_t*), zhash_str_hash, zhash_str_equals);

    // Read in the entire file, save vertices, and indices for later processing.
    while (1) {
        int eof = fgets(line_buffer, LNSZ, fp_obj) == NULL;

        char * line = str_trim(line_buffer);

        // If possible, batch process the last group
        if (str_starts_with(line, "g ") || eof) {
            if (cur_group != NULL) {
                assert(cur_group->group_idx != NULL);

                zarray_add(group_list, &cur_group);
                cur_group = NULL;
            }
        }

        if (eof)
            break;


        if (str_starts_with(line, "#") || strlen(line) == 0 || !strcmp(line,"\r"))
            continue;

        if (str_starts_with(line, "g ")) {
            assert(mtl_map != NULL);

            char obj_name[LNSZ];
            sscanf(line, "g %s", obj_name);

            cur_group = calloc(1, sizeof(wav_group_t));
            cur_group->group_idx = zarray_create(sizeof(tri_idx_t));

        } else if (str_starts_with(line, "v ")) {
            float vertex[3];
            sscanf(line, "v %f %f %f", &vertex[0], &vertex[1], &vertex[2]);
            zarray_add(vertices, &vertex);
        } else if (str_starts_with(line, "vn ")) {
            float normal[3];
            sscanf(line, "vn %f %f %f", &normal[0], &normal[1], &normal[2]);
            zarray_add(normals, &normal);
        } else if (str_starts_with(line, "vt ")) {
            texture_flag = 1;
            float texture[3];
            sscanf(line, "vt %f %f %f", &texture[0], &texture[1], &texture[2]);
            zarray_add(textures, &texture);
        } else if (str_starts_with(line, "f ")) {
            tri_idx_t idxs;

            if (texture_flag) {
                sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d",
                       &idxs.vIdxs[0], &idxs.tIdxs[0], &idxs.nIdxs[0],
                       &idxs.vIdxs[1], &idxs.tIdxs[1], &idxs.nIdxs[1],
                       &idxs.vIdxs[2], &idxs.tIdxs[2], &idxs.nIdxs[2]);
            }
            else {
                sscanf(line, "f %d//%d %d//%d %d//%d",
                       &idxs.vIdxs[0], &idxs.nIdxs[0],
                       &idxs.vIdxs[1], &idxs.nIdxs[1],
                       &idxs.vIdxs[2], &idxs.nIdxs[2]);
            }

            zarray_add(cur_group->group_idx, &idxs);

        } else if (str_starts_with(line, "usemtl ")) {
            char *mname = calloc(1, sizeof(char)*1024);
            sscanf(line, "usemtl %s", mname);
            zhash_get(mtl_map, &mname, &cur_group->material);
            free(mname);
        } else if (str_starts_with(line, "s ")) {
            // No idea what to do with smoothing instructions
        } else if (str_starts_with(line, "mtllib ")) {
            char * cur_path = strdup(obj_filename);
            const char * dir_name = dirname(cur_path);

            char mtl_basename[LNSZ];
            sscanf(line, "mtllib %s", mtl_basename);

            char mtl_filename[LNSZ];
            sprintf(mtl_filename,"%s/%s", dir_name, mtl_basename);

            mtl_map = load_materials(mtl_filename);
            if (mtl_map == NULL) {
                zarray_destroy(vertices);
                zarray_destroy(normals);
                return NULL; // XXX cleanup!
            }
            free(cur_path);
        } else {
            printf("Did not parse: %s\n", line);

            for (int i = 0; i < strlen(line); i++) {
                printf("0x%x ", (int)line[i]);
            }
            printf("\n");
        }
    }

    if (1) // useful to enable when compensating for model scale
        print_bounds(vertices);

    // Process the model sections in two passes -- first add all the
    // objects which are not transparent. Then render transparent
    // objects after

    vx_object_t * vchain = vxo_chain_create();

    zarray_t * sorted_groups = zarray_create(sizeof(wav_group_t*));
    for (int i = 0, sz = zarray_size(group_list); i < sz; i++) {
        wav_group_t * group = NULL;
        zarray_get(group_list, i, &group);

        // add to front if solid
        if (group->material.d == 1.0f) {
            zarray_insert(sorted_groups, 0, &group);
        } else { // add to back if transparent
            zarray_add(sorted_groups, &group);
        }
    }

    int total_triangles = 0;
    for (int i = 0, sz = zarray_size(sorted_groups); i < sz; i++) {
        wav_group_t * group = NULL;
        zarray_get(sorted_groups, i, &group);

        int ntri =  zarray_size(group->group_idx);

        vx_resc_t * vert_resc = vx_resc_createf(ntri*9);
        vx_resc_t * norm_resc = vx_resc_createf(ntri*9);

        for (int j = 0; j < ntri; j++) {
            tri_idx_t idxs;
            zarray_get(group->group_idx, j, &idxs);

            for (int  i = 0; i < 3; i++) {
                zarray_get(vertices, idxs.vIdxs[i]-1, &((float*)vert_resc->res)[9*j + i*3]);
                zarray_get(normals,  idxs.nIdxs[i]-1, &((float*)norm_resc->res)[9*j + i*3]);
            }
        }

        vx_style_t * sty = vxo_mesh_style_fancy(group->material.Ka, group->material.Kd, group->material.Ks, group->material.d, group->material.Ns, group->material.illum);
        vxo_chain_add(vchain, vxo_mesh(vert_resc, ntri*3, norm_resc, GL_TRIANGLES, sty));

        total_triangles += ntri;
    }

    //Cleanup:
    // 1. Materials, names are by reference, but materials are by value
    zhash_vmap_keys(mtl_map, free);
    zhash_destroy(mtl_map);

    // 2. Geometry
    zarray_destroy(vertices); // stored by value
    zarray_destroy(normals); // stored by value

    // 2b wav_group_t are stored by reference

    zarray_vmap(group_list, wav_group_destroy);
    zarray_destroy(group_list);
    zarray_destroy(sorted_groups); // duplicate list, so don't need to free

    fclose(fp_obj);

    return vchain;
}
Exemple #28
0
static void * movie_run(void * params)
{
    state_t * state = params;

    zarray_t * frames = zarray_create(sizeof(movie_frame_t*));

    char * last_filename = NULL;
    char * current_filename = NULL;

    gzFile gzMovie = NULL;
    int movie_frames = 0;
    int lost_frames = 0;
    uint64_t movie_start_mtime = 0;

    while (state->rendering) {


        pthread_mutex_lock(&state->movie_mutex);
        while (state->rendering && current_filename == state->movie_file && zarray_size(state->movie_pending) == 0)
            pthread_cond_wait(&state->movie_cond, &state->movie_mutex);

        if (!state->rendering) // exit signaled while waiting on cond
            break;

        for (int i = 0; i < zarray_size(state->movie_pending); i++) {
            movie_frame_t * tmp = NULL;
            zarray_get(state->movie_pending, i, &tmp);
            zarray_add(frames, &tmp);
        }
        zarray_clear(state->movie_pending);
        current_filename = state->movie_file;

        pthread_mutex_unlock(&state->movie_mutex);


        // Depending on setup, execute different actions
        // 1) Open 2) Close 3) Write a frame

        if (zarray_size(frames) > 0 && current_filename != NULL) {

            // Write the most recent frame, dump the rest
            movie_frame_t * movie_img = NULL;
            zarray_get(frames, zarray_size(frames)-1, &movie_img);
            zarray_remove_index(frames, zarray_size(frames)-1, 0);

            char header[256];
            sprintf(header, "#mtime=%"PRIu64"\nP6 %d %d %d\n", movie_img->mtime, movie_img->width, movie_img->height, 255);
            int header_len = strlen(header);
            int imglen = movie_img->stride*movie_img->height;// RGB format

            gzwrite(gzMovie, header, header_len);
            gzwrite(gzMovie, movie_img->buf, imglen);
            int res = gzflush(gzMovie, Z_SYNC_FLUSH);

            if (res != Z_OK) {
                int errval = 0;
                printf("Error writing movie %s. Closing file\n", gzerror(gzMovie, &errval));
                gzclose(gzMovie);
                free(current_filename);
                current_filename = NULL;
            }
            movie_frames++;
            movie_frame_destroy (movie_img);
        }
        // cleanup the frames:
        lost_frames += zarray_size(frames);
        zarray_vmap(frames, movie_frame_destroy);
        zarray_clear(frames);


        // Got a new filename, need to start recording
        if (current_filename != NULL && last_filename == NULL)
        {

            gzMovie = gzopen(current_filename, "w3");
            movie_frames = 0;
            lost_frames = 0;
            movie_start_mtime = vx_mtime();

            printf("NFO: Starting movie at %s\n", current_filename);

            if (gzMovie == NULL) {
                printf("WRN: Unable to start movie at %s\n", current_filename);
                free(current_filename); // XXX Would need to edit
                                        // state->movie_file ?
                current_filename = NULL;
            }
        }


        if (current_filename == NULL && last_filename != NULL)
        {

            gzclose(gzMovie);

            printf("NFO: Wrote/lost %d/%d movie frames at %.2f fps to %s\n",
                   movie_frames, lost_frames, 1e3 * movie_frames / (vx_mtime() - movie_start_mtime), last_filename);

            free(last_filename);
        }


        last_filename = current_filename;
    }

    // XXX Cleanup? might shutdown while recording?

    return NULL;
}
// returns 1 if no error
int
getopt_parse (getopt_t *gopt, int argc, char *argv[], int showErrors)
{
    int okay = 1;
    zarray_t *toks = zarray_create (sizeof(char*));

    // take the input stream and chop it up into tokens
    for (int i = 1; i < argc; i++) {
        char *arg = strdup (argv[i]);

        if (arg[0] != '-') {
            // if this isn't an option, put the whole thing in the args list.
            zarray_add (toks, &arg);

        }
        else {
            // this is an option. It could be a flag (like -v), or an option
            // with arguments (--file=foobar.txt).
            char *eq = strstr (arg, "=");

            // no equal sign? Push the whole thing.
            if (eq == NULL) {
                zarray_add (toks, &arg);
            }
            else {
                // there was an equal sign. Push the part
                // before and after the equal sign
                char *val = strdup (&eq[1]);
                eq[0] = 0;
                zarray_add (toks, &arg);

                // if the part after the equal sign is
                // enclosed by quotation marks, strip them.
                if (val[0]=='\"') {
                    int last = strlen (val) - 1;
                    if (val[last]=='\"')
                        val[last] = 0;
                    char *valclean = strdup (&val[1]);
                    zarray_add (toks, &valclean);
                    free (val);
                }
                else
                    zarray_add (toks, &val);
            }
        }
    }

    // now loop over the elements and evaluate the arguments
    unsigned int i = 0;

    char *tok = NULL;

    while (i < zarray_size (toks)) {

        // rather than free statement throughout this while loop
        if (tok != NULL)
            free (tok);

        zarray_get (toks, i, &tok);

        if (0==strncmp (tok,"--", 2)) {
            char *optname = &tok[2];
            getopt_option_t *goo = NULL;
            zhash_get (gopt->lopts, &optname, &goo);
            if (goo == NULL) {
                okay = 0;
                if (showErrors)
                    printf ("Unknown option --%s\n", optname);
                i++;
                continue;
            }

            goo->was_specified = 1;

            if (goo->type == GOO_BOOL_TYPE) {
                if ((i+1) < zarray_size (toks)) {
                    char *val = NULL;
                    zarray_get (toks, i+1, &val);

                    if (0==strcmp (val,"true")) {
                        i+=2;
                        getopt_modify_string (&goo->svalue, val);
                        continue;
                    }
                    if (0==strcmp (val,"false")) {
                        i+=2;
                        getopt_modify_string (&goo->svalue, val);
                        continue;
                    }
                }
                getopt_modify_string (&goo->svalue, strdup("true"));
                i++;
                continue;
            }

            if (goo->type == GOO_STRING_TYPE) {
                // TODO: check whether next argument is an option, denoting missing argument
                if ((i+1) < zarray_size (toks)) {
                    char *val = NULL;
                    zarray_get (toks, i+1, &val);
                    i+=2;
                    getopt_modify_string (&goo->svalue, val);
                    continue;
                }

                okay = 0;
                if (showErrors)
                    printf ("Option %s requires a string argument.\n",optname);
            }
        }

        if (0==strncmp (tok,"-",1) && strncmp (tok,"--",2)) {
            int len = strlen (tok);
            int pos;
            for (pos = 1; pos < len; pos++) {
                char sopt[2];
                sopt[0] = tok[pos];
                sopt[1] = 0;
                char *sopt_ptr = (char*) &sopt;
                getopt_option_t *goo = NULL;
                zhash_get (gopt->sopts, &sopt_ptr, &goo);

                if (goo==NULL) {
                    // is the argument a numerical literal that happens to be negative?
                    if (pos==1 && isdigit (tok[pos])) {
                        zarray_add (gopt->extraargs, &tok);
                        tok = NULL;
                        break;
                    }
                    else {
                        okay = 0;
                        if (showErrors)
                            printf ("Unknown option -%c\n", tok[pos]);
                        i++;
                        continue;
                    }
                }

                goo->was_specified = 1;

                if (goo->type == GOO_BOOL_TYPE) {
                    getopt_modify_string (&goo->svalue, strdup("true"));
                    continue;
                }

                if (goo->type == GOO_STRING_TYPE) {
                    if ((i+1) < zarray_size (toks)) {
                        char *val = NULL;
                        zarray_get (toks, i+1, &val);
                        // TODO: allow negative numerical values for short-name options ?
                        if (val[0]=='-')
                        {
                            okay = 0;
                            if (showErrors)
                                printf ("Ran out of arguments for option block %s\n", tok);
                        }
                        i++;
                        getopt_modify_string (&goo->svalue, val);
                        continue;
                    }

                    okay = 0;
                    if (showErrors)
                        printf ("Option -%c requires a string argument.\n", tok[pos]);
                }
            }
            i++;
            continue;
        }

        // it's not an option-- it's an argument.
        zarray_add (gopt->extraargs, &tok);
        tok = NULL;
        i++;
    }
    if (tok != NULL)
        free (tok);

    zarray_destroy (toks);

    return okay;
}
Exemple #30
0
// Pass in a codes describing which resources are no longer in use. Decrement user counts,
// and return a list of all resources whos counts have reached zero, which therefore
// should be deleted from the display using a OP_DEALLOC_RESOURCES opcode
void vx_resc_manager_buffer_resources(vx_resc_manager_t * mgr, const uint8_t * data, int datalen)
{
    if (0) print_manager(mgr);

    vx_code_input_stream_t * cins = vx_code_input_stream_create(data, datalen);
    int code = cins->read_uint32(cins);
    assert(code == OP_BUFFER_RESOURCES);
    int worldID = cins->read_uint32(cins);
    char * name = strdup(cins->read_str(cins)); //freed when cur_resources is eventually removed from the buffer map
    int count = cins->read_uint32(cins);

    zhash_t * cur_resources = zhash_create(sizeof(uint64_t), sizeof(vx_resc_t*), zhash_uint64_hash, zhash_uint64_equals);
    vx_resc_t * vr = NULL;
    for (int i = 0; i < count; i++) {
        uint64_t id = cins->read_uint64(cins);
        zhash_put(cur_resources, &id, &vr, NULL, NULL);
    }
    assert(cins->pos == cins->len); // we've emptied the stream
    vx_code_input_stream_destroy(cins);

    // 1 Update our records
    zhash_t * worldBuffers = NULL;
    zhash_get(mgr->allLiveSets, &worldID, &worldBuffers);
    if (worldBuffers == NULL) {
        worldBuffers = zhash_create(sizeof(char*), sizeof(zhash_t*), zhash_str_hash, zhash_str_equals);
        zhash_put(mgr->allLiveSets, &worldID, &worldBuffers, NULL, NULL);
    }

    zhash_t * old_resources = NULL;
    char * old_name = NULL;
    zhash_put(worldBuffers, &name, &cur_resources, &old_name, &old_resources);
    free(old_name);

    // 2 Figure out which resources have become unused:
    if(old_resources != NULL) {
        removeAll(old_resources, cur_resources);

        zarray_t * dealloc = zarray_create(sizeof(uint64_t));

        // now 'old_resources' contains only the resources that are no longer referenced
        // iterate through each one, and see if there is a buffer somewhere that references it
        zhash_iterator_t prev_itr;
        zhash_iterator_init(old_resources, &prev_itr);
        uint64_t id = -1;
        vx_resc_t * vr = NULL;
        while(zhash_iterator_next(&prev_itr, &id, &vr)) {
            // Check all worlds
            zhash_iterator_t  world_itr;// gives us all worlds
            zhash_iterator_init(mgr->allLiveSets, &world_itr);
            uint32_t wIDl = -1;
            zhash_t * buffer_map = NULL;
            while(zhash_iterator_next(&world_itr, &wIDl, &buffer_map)) {
                zhash_iterator_t buffer_itr; // gives us all buffers
                zhash_iterator_init(buffer_map, &buffer_itr);
                char * bName = NULL;
                zhash_t * resc_map = NULL;
                while(zhash_iterator_next(&buffer_itr, &bName, &resc_map)) {
                    if (zhash_contains(resc_map, &id)) {
                        goto continue_outer_loop;
                    }
                }

            }

            // If none of the worlds have this resource, we need to flag removal
            zarray_add(dealloc, &id);

          continue_outer_loop:
            ;
        }


        // 3 Issue dealloc commands
        if (zarray_size(dealloc) > 0) {
            vx_code_output_stream_t * couts = vx_code_output_stream_create(512);
            couts->write_uint32(couts, OP_DEALLOC_RESOURCES);
            couts->write_uint32(couts, zarray_size(dealloc));
            for (int i = 0; i < zarray_size(dealloc); i++) {
                uint64_t id = 0;
                zarray_get(dealloc, i, &id);
                couts->write_uint64(couts, id);
            }

            mgr->disp->send_codes(mgr->disp, couts->data, couts->pos);

            vx_code_output_stream_destroy(couts);

            // Also remove the resources we deallocated from remoteResc
            for (int i = 0; i < zarray_size(dealloc); i++) {
                uint64_t id = 0;
                zarray_get(dealloc, i, &id);

                assert(zhash_contains(mgr->remoteResc, &id));
                zhash_remove(mgr->remoteResc, &id, NULL, NULL);
            }

        }
        zarray_destroy(dealloc);
        zhash_destroy(old_resources);

    }
    if (0) {
        print_manager(mgr);
        printf("\n\n");
    }
}