Ejemplo n.º 1
0
void subdivide_strand(Strand *parent, Strand_collection *children, double strand_r_final) {
    
    double *parent_start_point_pos, possible_child_start_point[3];
    double row_basis[3], col_basis[3], row_basis_length, col_basis_length;
    
    Segment *parent_segment;
    
    int half_num_rows, half_num_cols, row_i, col_i, start_of_strand_control_point_i;
    
    int num_new_children, total_num_new_children, debug;
    
    double col_indent;
    double child_disp[3], child_dist, *prev_child_point, *child_point, s[3], tang[3], v[3], mu,
            child_segment_disp[3], child_segment_length, child_segment_direction[3], child_angle,
            prev_child_segment_direction[3];
    double tang_norm;
    
    double proj_onto_parent;
    
    /* Get the vector tangent (angle halfway between pre_segment and start_segment) to the parent start point */
    tang[X] = parent->pre_segment->disp[X] / parent->pre_segment->length
            + parent->start_segment->disp[X] / parent->start_segment->length;
    tang[Y] = parent->pre_segment->disp[Y] / parent->pre_segment->length
            + parent->start_segment->disp[Y] / parent->start_segment->length;
    tang[Z] = parent->pre_segment->disp[Z] / parent->pre_segment->length
            + parent->start_segment->disp[Z] / parent->start_segment->length;
    
    tang_norm = vector_norm(tang);
    
    if (tang_norm < STARTING_ANGLE_THRESHOLD) {
        printf(
                "Error the pre and start segments of strand %d, double back on each other. Not able to proceed with subdivision.  Please check data and try again\n",
                parent->strand_i);
        exit(EXIT_FAILURE);
        
    } else if (abs(tang[X] / tang_norm) < LINEAR_DEPEND_THRESHOLD) {
        
        /*Cross the first tangent with [1;0;0] to get a vector perpendicular to the parent->pre_segment to be the row basis vector child start_points;*/
        row_basis[X] = 0;
        row_basis[Y] = tang[Z];
        row_basis[Z] = -tang[Y];
        
    } else {
        
        /*If tangent is colinear with [1;0;0] cross the first tangent with [0;1;0] instead to get a vector perpendicular to the parent->pre_segment to be the row basis vector child start_points;*/
        row_basis[X] = -tang[Z];
        row_basis[Y] = 0;
        row_basis[Z] = tang[X];
    }
    
    /*Cross the row basis with the tangent vector to get the col basis.*/
    col_basis[X] = row_basis[Y] * tang[Z] - row_basis[Z] * tang[Y];
    col_basis[Y] = row_basis[Z] * tang[X] - row_basis[X] * tang[Z];
    col_basis[Z] = row_basis[X] * tang[Y] - row_basis[Y] * tang[X];
    
    /*Normalize then rescale the basis vectors to the correct row and column increment (2 * strand_r_final and sqrt(3) * strand_r_final respectively)*/
    row_basis_length = sqrt(3) * strand_r_final
            / sqrt(
                    row_basis[X] * row_basis[X] + row_basis[Y] * row_basis[Y]
                    + row_basis[Z] * row_basis[Z]);
    col_basis_length = 2 * strand_r_final
            / sqrt(
                    col_basis[X] * col_basis[X] + col_basis[Y] * col_basis[Y]
                    + col_basis[Z] * col_basis[Z]);
    
    row_basis[X] = row_basis[X] * row_basis_length;
    row_basis[Y] = row_basis[Y] * row_basis_length;
    row_basis[Z] = row_basis[Z] * row_basis_length;
    
    col_basis[X] = col_basis[X] * col_basis_length;
    col_basis[Y] = col_basis[Y] * col_basis_length;
    col_basis[Z] = col_basis[Z] * col_basis_length;
    
    /* The number of children rows and cols tried (to see if they fall in the original strand radius) either side of the parent start_point */
    half_num_rows = floor(parent->radius / (sqrt(3) * strand_r_final)) + 1;
    half_num_cols = floor(parent->radius / (2 * strand_r_final));
    
    parent_start_point_pos = parent->start_segment->start_point.pos;
    
    num_new_children = 0;
    
    for (row_i = -half_num_rows; row_i <= half_num_rows; row_i++) {
        
        col_indent = ((double) (row_i % 2)) / 2;	//indent the colums by 1/2 if it is an odd row. 
                
        for (col_i = -half_num_cols; col_i <= half_num_cols; col_i++) {
            
            possible_child_start_point[X] = parent_start_point_pos[X]
                    + ((double) row_i) * row_basis[X]
                    + (((double) col_i) + col_indent) * col_basis[X];
            possible_child_start_point[Y] = parent_start_point_pos[Y]
                    + ((double) row_i) * row_basis[Y]
                    + (((double) col_i) + col_indent) * col_basis[Y];
            possible_child_start_point[Z] = parent_start_point_pos[Z]
                    + ((double) row_i) * row_basis[Z]
                    + (((double) col_i) + col_indent) * col_basis[Z];
            
            child_disp[X] = possible_child_start_point[X] - parent_start_point_pos[X];
            child_disp[Y] = possible_child_start_point[Y] - parent_start_point_pos[Y];
            child_disp[Z] = possible_child_start_point[Z] - parent_start_point_pos[Z];
            
            child_dist = sqrt(
                    child_disp[X] * child_disp[X] + child_disp[Y] * child_disp[Y]
                    + child_disp[Z] * child_disp[Z]);
            
            /* If possible child start point lies withinness parent strand extent then add it to the collection */
            if (child_dist <= parent->radius) {
                
                children->start_points[(children->num_strands + num_new_children) * 3 + X] =
                        possible_child_start_point[X];
                children->start_points[(children->num_strands + num_new_children) * 3 + Y] =
                        possible_child_start_point[Y];
                children->start_points[(children->num_strands + num_new_children) * 3 + Z] =
                        possible_child_start_point[Z];
                
                children->pre_points[(children->num_strands + num_new_children) * 3 + X] =
                        possible_child_start_point[X] + parent->pre_segment->disp[X];
                children->pre_points[(children->num_strands + num_new_children) * 3 + Y] =
                        possible_child_start_point[Y] + parent->pre_segment->disp[Y];
                children->pre_points[(children->num_strands + num_new_children) * 3 + Z] =
                        possible_child_start_point[Z] + parent->pre_segment->disp[Z];
                
                /*children->num_strand_control_points[children->num_strands + num_new_children] = parent->num_control_points;*/
                children->strand_r[children->num_strands + num_new_children] = strand_r_final;
                children->bundle_i_of_strand[children->num_strands + num_new_children] =
                        parent->bundle_i;
                
                num_new_children++;
            }
        }
    }
    
    total_num_new_children = children->num_strands + num_new_children;
    
    for (; children->num_strands < total_num_new_children; children->num_strands++) {
        
        parent_segment = parent->start_segment;
        prev_child_point = &(children->start_points[(children->num_strands) * 3]);
        
        prev_child_segment_direction[X] = parent->pre_segment->disp[X]
                / (parent->pre_segment->length);
        prev_child_segment_direction[Y] = parent->pre_segment->disp[Y]
                / (parent->pre_segment->length);
        prev_child_segment_direction[Z] = parent->pre_segment->disp[Z]
                / (parent->pre_segment->length);
        
        start_of_strand_control_point_i = children->num_control_points;
        children->num_strand_control_points[children->num_strands] = 0;
        
        child_point = &(children->control_points[(children->num_control_points) * 3]);
        
        int count = 0;
        
        /* While the current parent segment is not the post segment */
        while (parent_segment != parent->post_segment) {
            
            child_point = &(children->control_points[(children->num_control_points) * 3]);
            
            /* Normalised vector of the segment displacement */
            s[X] = parent_segment->disp[X] / parent_segment->length;
            s[Y] = parent_segment->disp[Y] / parent_segment->length;
            s[Z] = parent_segment->disp[Z] / parent_segment->length;
            
            /* Get the vector tangent (angle halfway between current segment and the next_segment) to the parent strand */
            tang[X] = s[X]
                    + parent_segment->next_segment->disp[X] / parent_segment->next_segment->length;
            tang[Y] = s[Y]
                    + parent_segment->next_segment->disp[Y] / parent_segment->next_segment->length;
            tang[Z] = s[Z]
                    + parent_segment->next_segment->disp[Z] / parent_segment->next_segment->length;
            
            if ((tang[X] == 0) && (tang[Y] == 0.0) && (tang[Z] == 0.0))
                printf(
                        "Warning! Consecutive segments (%d and %d of strand %d) completely double back on each other (will result in a NaN).\n",
                        parent_segment->segment_i, parent_segment->next_segment->segment_i,
                        parent_segment->strand->strand_i);
            
            /* The displacement vector between the previous child_point and the next parent control_point */
            v[X] = parent_segment->end_point.pos[X] - prev_child_point[X];
            v[Y] = parent_segment->end_point.pos[Y] - prev_child_point[Y];
            v[Z] = parent_segment->end_point.pos[Z] - prev_child_point[Z];
            
            /* The distance along s, it intersects with the normal plane at the control point */
            mu = dot_product(v, tang) / dot_product(s, tang);
            
            /* Calculate the control point value */
            child_point[X] = prev_child_point[X] + mu * s[X];
            child_point[Y] = prev_child_point[Y] + mu * s[Y];
            child_point[Z] = prev_child_point[Z] + mu * s[Z];
            
            child_segment_disp[X] = child_point[X] - prev_child_point[X];
            child_segment_disp[Y] = child_point[Y] - prev_child_point[Y];
            child_segment_disp[Z] = child_point[Z] - prev_child_point[Z];
            
            child_segment_length = vector_norm(child_segment_disp);
            
            child_segment_direction[X] = child_segment_disp[X] / child_segment_length;
            child_segment_direction[Y] = child_segment_disp[Y] / child_segment_length;
            child_segment_direction[Z] = child_segment_disp[Z] / child_segment_length;
            
            child_angle = dot_product(child_segment_direction, prev_child_segment_direction);
            
            if ((children->num_strands == 573) && (children->num_strand_control_points[children->num_strands]
                    == 34)) {
                debug = 0;
                debug = 2;
                
            }
            
            proj_onto_parent = dot_product(parent_segment->disp, child_segment_disp);
            
            proj_onto_parent /= (parent_segment->length * parent_segment->length);
            
//			printf("child_segment_direction: %g,%g,%g\n", child_segment_direction[X], child_segment_direction[Y], child_segment_direction[Z]);
//      printf("prev_child_segment_direction: %g,%g,%g\n", prev_child_segment_direction[X], prev_child_segment_direction[Y], prev_child_segment_direction[Z]);
            
            /* Check to see if the child segment doesn't double back on to itself, which is caused by "wobbling" in the parent strand coupled with a large bundle radius*/
            if ((child_angle > 0)) {
                
                /*To ensure an even spacing between the child segments (due to bunching/stretching on the inside/outside of bends) if the new segment is more than 1.5 times the parent segment length then a new control point is inserted in the middle. If the new segment is less than half the parent segment length then the control point is ignored*/

                if (proj_onto_parent > 0.5) {
                    
                    ++count;
                    
                    children->num_control_points++;
                    children->num_strand_control_points[children->num_strands]++;
                    prev_child_point = child_point;
                    
                    /* Save to check if next segment 'doubles back' */
                    prev_child_segment_direction[X] = child_segment_direction[X];
                    prev_child_segment_direction[Y] = child_segment_direction[Y];
                    prev_child_segment_direction[Z] = child_segment_direction[Z];
                }
            }
            
            /* Iterate */
            parent_segment = parent_segment->next_segment;
            
        }
        
        if (count == 0)
            printf(
                    "Warning !! no segments were wrtten to child strand %d as they all double back on the initial segment. Please rectify before continuing. \n\n",
                    children->num_strands);
        
        /* Reassign the last generated control to the end_point */
        children->end_points[(children->num_strands * 3) + X] = child_point[X];
        children->end_points[(children->num_strands * 3) + Y] = child_point[Y];
        children->end_points[(children->num_strands * 3) + Z] = child_point[Z];
        
        children->num_control_points--;
        children->num_strand_control_points[children->num_strands]--;
        
        /* Add the parent post segment to get the child strand post_point */
        children->post_points[(children->num_strands * 3) + X] = child_point[X]
                + parent->post_segment->disp[X];
        children->post_points[(children->num_strands * 3) + Y] = child_point[Y]
                + parent->post_segment->disp[Y];
        children->post_points[(children->num_strands * 3) + Z] = child_point[Z]
                + parent->post_segment->disp[Z];
        
        construct_strand(&(children->strands[children->num_strands]), children->num_strands,
                parent->bundle_i, &(children->control_points[start_of_strand_control_point_i]),
                &(children->start_points[children->num_strands]),
                &(children->end_points[children->num_strands]),
                &(children->pre_points[children->num_strands]),
                &(children->post_points[children->num_strands]),
                &(children->segments[start_of_strand_control_point_i + 3 * children->num_strands]),
                children->num_strand_control_points[children->num_strands], 0.0, strand_r_final);
    }
    
}
Ejemplo n.º 2
0
Strand_collection* convert_mr_to_nfg(Strand_collection* c, FTS::Fibre::Track::Set& tracks,
                                     std::vector<FTS::Triple<double> >& pre_points,
                                     std::vector<FTS::Triple<double> >& post_points) {
    
    if (tracks.size() == 0)
        throw FTS::Exception(
                "Track set supplied to FTSTrix to NFG conversion function does not have any tracks in it.");
    
    if (!tracks.has_extend_elem_prop(FTS::Fibre::Track::RADIUS_PROP))
        tracks.add_extend_elem_prop(FTS::Fibre::Track::RADIUS_PROP, "0.03");
    
    size_t total_num_control_points = 0;
    
    for (size_t tck_i = 0; tck_i < tracks.size(); ++tck_i)
        total_num_control_points += tracks[tck_i].size() - 2;
    
    collection_alloc(c, tracks.size(), total_num_control_points, 0);
    
    size_t control_point_count = 0;
    
    for (size_t strand_i = 0; strand_i < tracks.size(); strand_i++) {
        
        FTS::Fibre::Track tck = tracks[strand_i];
        
        c->num_strand_control_points[strand_i] = tck.size() - 2;    //Start and end points are not included.
                
        c->strand_r[strand_i] = atof(
                tracks.get_extend_elem_prop(FTS::Fibre::Track::RADIUS_PROP, strand_i).c_str());
        
        size_t bundle_i;
        if (tracks.has_extend_elem_prop(FTS::Fibre::Track::BUNDLE_INDEX_EPROP))
            bundle_i =
                    atoi(
                            tracks.get_extend_elem_prop(FTS::Fibre::Track::BUNDLE_INDEX_EPROP,
                                    strand_i).c_str());
        else
            bundle_i = strand_i;
        
        c->bundle_i_of_strand[strand_i] = bundle_i;
        
        pre_points[strand_i].copy_to(&(c->pre_points[strand_i * 3]));
        post_points[strand_i].copy_to(&(c->post_points[strand_i * 3]));
        
        tck[0].copy_to(&(c->start_points[strand_i * 3]));
        
        size_t point_i;
        
        for (point_i = 1; point_i < (tck.size() - 1); point_i++)
            tck[point_i].copy_to(&(c->control_points[(control_point_count + point_i - 1) * 3]));
        
        tck[point_i].copy_to(&(c->end_points[strand_i * 3]));
        
        construct_strand(&(c->strands[strand_i]), strand_i, bundle_i,
                &(c->control_points[control_point_count * 3]), &(c->start_points[strand_i * 3]),
                &(c->end_points[strand_i * 3]), &(c->pre_points[strand_i * 3]),
                &(c->post_points[strand_i * 3]), &(c->segments[control_point_count + 3 * strand_i]),
                c->num_strand_control_points[strand_i], 0.0, c->strand_r[strand_i]);
        
        control_point_count += c->num_strand_control_points[strand_i];
        
    }
    
    c->num_bundles = construct_bundles(c->bundles, c->bundle_i_of_strand, c->num_strands,
            c->strands);
    
    return c;
}