Custom_person* add_custom_person( int reference, short x, short y, const FONTINFO* font_ptr, int parent_number ) { Custom_person* Cp_ptr ; Cp_ptr = (Custom_person*) checked_malloc( sizeof( Custom_person ) ) ; if( Cp_ptr ) { if( font_ptr ) { Cp_ptr->font_ptr = (FONTINFO*) checked_malloc( sizeof( FONTINFO ) ) ; if( Cp_ptr->font_ptr ) *(Cp_ptr->font_ptr) = *font_ptr ; else { free( Cp_ptr ) ; Cp_ptr = NULL ; } } else Cp_ptr->font_ptr = NULL ; } if( Cp_ptr ) { if( custom_tree.end_person != NULL ) { custom_tree.end_person->next_person = Cp_ptr ; Cp_ptr->list_number = custom_tree.end_person->list_number + 1 ; } else { Cp_ptr->list_number = 1 ; custom_tree.start_person = Cp_ptr ; } Cp_ptr->reference = reference ; Cp_ptr->x = x ; Cp_ptr->y = y ; Cp_ptr->status = CUST_SELECTED ; Cp_ptr->attributes = 0 ; Cp_ptr->font_ptr = NULL ; Cp_ptr->parent_number = parent_number ; Cp_ptr->coupling_list = NULL ; /* initialised zero, set by */ Cp_ptr->couplings = 0 ; /* draw_custom_person if necessary */ Cp_ptr->couplings_drawn = 0 ; Cp_ptr->parent_line_data = NULL ; Cp_ptr->previous_person = custom_tree.end_person ; custom_tree.end_person = Cp_ptr ; Cp_ptr->next_person = NULL ; /* When adding to tree, calculate box. When */ /* loading from file don't calculate. */ /* Likewise for setting tree changed flag. */ if( reference != 0 ) { Cp_ptr->box = calculate_box( reference, x, y, Cp_ptr->attributes, Cp_ptr->font_ptr, Cp_ptr->parent_number ) ; custom_tree_changed = TRUE ; } } return Cp_ptr ; }
EXPORT void rotate_and_zoom_rect_grid( RECT_GRID *gr, double *L, double *U, double **Q) { double **Qi = NULL; int i, j, dim = gr->dim; static double **pc = NULL; if (pc == NULL) bi_array(&pc,MAXNCORNERS,MAXD,FLOAT); if (Q != NULL) { static double** M = NULL; if (M == NULL) bi_array(&M,MAXD,MAXD,FLOAT); Qi = M; for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) Qi[i][j] = Q[j][i]; } calculate_box(L,U,pc,Q,Qi,dim); for (i = 0; i < dim; i++) { gr->gmax[i] = irint(_scaled_separation(pc[1<<i],pc[0],gr->h,dim)); if (gr->gmax[i] < 1) gr->gmax[i] = 1; } if (Qi != NULL) { rotate_point(L,U,Qi,gr->U,dim); rotate_point(L,gr->GU,Qi,gr->GU,dim); rotate_point(L,gr->GL,Qi,gr->GL,dim); } set_rect_grid(L,gr->U,gr->GL,gr->GU,gr->lbuf,gr->ubuf,gr->gmax, dim,&gr->Remap,gr); } /*end rotate_and_zoom_rect_grid*/
/*ARGSUSED*/ EXPORT INTERFACE *i_zoom_interface( INTERFACE *given_intfc, RECT_GRID *gr, double *L, double *U, double **Q) { INTERFACE *cur_intfc; INTERFACE *zoom_intfc; RECT_GRID *t_gr; int dim = given_intfc->dim; int i, j; double **Qi = NULL; static double **pc = NULL; debug_print("zoom","Entered zoom_interface()\n"); cur_intfc = current_interface(); if ((zoom_intfc = copy_interface(given_intfc)) == NULL) { Error(ERROR,"Unable to copy interface."); clean_up(ERROR); } if (debugging("zoom")) { (void) output(); (void) printf("INTERFACE before zoom:\n\n"); print_interface(zoom_intfc); } if (Q != NULL) { static double** M = NULL; if (M == NULL) bi_array(&M,MAXD,MAXD,FLOAT); Qi = M; for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) Qi[i][j] = Q[j][i]; } if (pc == NULL) bi_array(&pc,MAXNCORNERS,MAXD,FLOAT); calculate_box(L,U,pc,Q,Qi,dim); /* Shrink topological grid to cutting boundary */ t_gr = &topological_grid(zoom_intfc); rotate_and_zoom_rect_grid(t_gr,L,U,Q); switch(dim) { case 1: /* TODO */ return NULL; case 2: insert_cuts_and_bdry2d(zoom_intfc,pc); clip_interface2d(zoom_intfc); break; case 3: /* TODO */ return NULL; } rotate_interface(zoom_intfc,pc[0],Qi); if (set_boundary(zoom_intfc,t_gr,component(pc[0],given_intfc), grid_tolerance(gr) != FUNCTION_SUCCEEDED)) { screen("ERROR in i_zoom_interface(), set_boundary failed\n"); clean_up(ERROR); } set_current_interface(cur_intfc); if (debugging("zoom")) { (void) printf("INTERFACE after zoom:\n\n"); print_interface(zoom_intfc); } debug_print("zoom","Leaving zoom_interface()\n"); return zoom_intfc; } /*end i_zoom_interface*/
Custom_couple* add_custom_parents( Custom_person* Cp_ptr ) { Custom_couple* Cc_ptr ; int siblings[MAX_CHILDREN] ; Custom_person* mCp_ptr = NULL ; /* pointer to male parent */ Custom_person* fCp_ptr = NULL ; /* pointer to female parent */ Person* pptr ; Couple* cptr ; int parents ; int father, mother ; int ref ; /* temporary reference */ short child ; /* loop counter */ short children ; /* number of siblings, inc original */ char* child_refs_ptr ; /* pointer to references */ short base_position_y ; /* y position of original child */ short upper_limit, lower_limit ; short leftest_sibling_x, rightest_sibling_x ; short highest_position_y ; short father_x, mother_x ; GRECT box_father, box_mother ; short parent_box_bottom ; short block ; /* block number for get_[p/c]data_ptr */ BOOLEAN fail = FALSE ; Cc_ptr = new_custom_couple() ; if( Cc_ptr == NULL ) return Cc_ptr ; pptr = get_pdata_ptr( Cp_ptr->reference, &block ) ; assert( pptr != NULL ) ; parents = pptr->parents ; assert( parents != 0 ) ; Cc_ptr->reference = parents ; Cp_ptr->parent_number = Cc_ptr->list_number ; cptr = get_cdata_ptr( parents, &block ) ; child_refs_ptr = cptr->children ; assert( child_refs_ptr ) ; /* Force temporary father number in order that */ /* auto_fname will work for add children. */ /* Note that male_reference is wrongly used, it */ /* will later be replaced with list number. */ Cc_ptr->male_number = couples[parents].male_reference ; /* if person has auto fname, their size will change */ /* with the addition of their father. Adjust their */ /* position to allow for this if they are coupled. */ if( cptr->male_reference != 0 && ( Cp_ptr->attributes & FNAME_AUTO_BIT || ( (Cp_ptr->attributes & FNAME_BITS) == 0 && custom_tree.attributes & FNAME_AUTO_BIT ) ) ) { Custom_couple* xCc_ptr ; short old_edge_x ; /* active edge of person's box */ short x_correction ; short reversed = FALSE ; short not_reversed = FALSE ; short coupling_index = 0 ; BOOLEAN left_partner = FALSE ; if( Cp_ptr->couplings_drawn != 0 ) { while( *(Cp_ptr->coupling_list + coupling_index) ) { xCc_ptr = get_Cc_ptr( *(Cp_ptr->coupling_list + coupling_index) ) ; assert( xCc_ptr ) ; if( xCc_ptr->status & CUST_REVERSED ) reversed = TRUE ; else not_reversed = TRUE ; coupling_index++ ; } /* check if adjustment is possible, i.e. all */ /* couplings on same side */ if( reversed && !not_reversed || not_reversed && !reversed ) { if( !reversed && xCc_ptr->male_number == Cp_ptr->list_number ) left_partner = TRUE ; if( left_partner ) old_edge_x = rect_end( &(Cp_ptr->box) ) ; else old_edge_x = Cp_ptr->box.g_x ; } } Cp_ptr->box = calculate_box( Cp_ptr->reference, Cp_ptr->x, Cp_ptr->y, Cp_ptr->attributes, Cp_ptr->font_ptr, Cp_ptr->parent_number ) ; if( Cp_ptr->couplings_drawn != 0 ) { if( left_partner ) x_correction = old_edge_x - rect_end( &(Cp_ptr->box) ) ; else x_correction = old_edge_x - Cp_ptr->box.g_x ; Cp_ptr->x += x_correction ; Cp_ptr->box.g_x += x_correction ; } } child = 0 ; while( ( ref = form_ref( &child_refs_ptr ) ) && ( child < MAX_CHILDREN ) ) { siblings[child] = ref ; child++ ; } siblings[child] = 0 ; children = child ; /* find current person in sibling array */ child = 0 ; while( siblings[child] != Cp_ptr->reference ) child++ ; Cc_ptr->child_numbers = (int*) checked_malloc( (children + 1) * sizeof( int ) ) ; if( Cc_ptr->child_numbers == NULL ) { Cp_ptr->parent_number = 0 ; remove_custom_coupling( Cc_ptr ) ; return NULL ; } Cc_ptr->child_numbers[child] = Cp_ptr->list_number ; Cc_ptr->child_numbers[children] = 0 ; /* terminate list */ upper_limit = Cp_ptr->box.g_x + Cp_ptr->box.g_w / 2 ; leftest_sibling_x = upper_limit ; /* initialise limits to centre of original */ rightest_sibling_x = upper_limit ; lower_limit = Cp_ptr->box.g_x ; base_position_y = Cp_ptr->box.g_y - Cp_ptr->box.g_h / 2 ; highest_position_y = Cp_ptr->box.g_y ; /* add any children to the left */ if( child >= 1 ) fail = add_children( siblings, child-1, Cc_ptr, FALSE, upper_limit, lower_limit, base_position_y, &leftest_sibling_x, &highest_position_y) ; else leftest_sibling_x = Cp_ptr->x ; if( fail ) { Cp_ptr->parent_number = 0 ; remove_custom_coupling( Cc_ptr ) ; return NULL ; } /* add any children to the right */ if( child+1 < children ) fail = add_children( siblings, child+1, Cc_ptr, TRUE, upper_limit, lower_limit, base_position_y, &rightest_sibling_x, &highest_position_y) ; else rightest_sibling_x = Cp_ptr->x ; if( fail ) { if( child >= 1 ) while( --child >= 0 ) remove_custom_person( get_Cp_ptr( Cc_ptr->child_numbers[child] ) ) ; Cp_ptr->parent_number = 0 ; remove_custom_coupling( Cc_ptr ) ; return NULL ; } if( father = couples[parents].male_reference ) box_father = get_box_size( father, 0, 0, custom_tree.attributes, NULL, 0 ) ; if( mother = couples[parents].female_reference ) box_mother = get_box_size( mother, 0, 0, custom_tree.attributes, NULL, 0 ) ; if( father ) Cc_ptr->y = highest_position_y - box_father.g_h - generation_gap ; else Cc_ptr->y = highest_position_y - box_mother.g_h - generation_gap ; Cc_ptr->x = (leftest_sibling_x + rightest_sibling_x) / 2 ; if( father && mother ) { father_x = Cc_ptr->x - box_father.g_w / 2 - couple_gap ; mother_x = Cc_ptr->x + box_mother.g_w / 2 + couple_gap ; } else { father_x = Cc_ptr->x ; mother_x = Cc_ptr->x ; } if( father ) { mCp_ptr = add_custom_person( father, father_x, Cc_ptr->y, NULL, 0 ) ; if( mCp_ptr != NULL ) { mCp_ptr->couplings_drawn = 1 ; Cc_ptr->male_number = mCp_ptr->list_number ; mCp_ptr->coupling_list = (int *) checked_malloc( 2 * sizeof( int ) ) ; if( mCp_ptr->coupling_list != NULL ) { *(mCp_ptr->coupling_list) = Cc_ptr->list_number ; *(mCp_ptr->coupling_list + 1) = 0 ; /* terminate list */ } else fail = TRUE ; parent_box_bottom = rect_bottom( &(mCp_ptr->box) ) ; } else fail = TRUE ; } if( !fail && mother ) { fCp_ptr = add_custom_person( mother, mother_x, Cc_ptr->y, NULL, 0 ) ; if( fCp_ptr != NULL ) { fCp_ptr->couplings_drawn = 1 ; Cc_ptr->female_number = fCp_ptr->list_number ; fCp_ptr->coupling_list = (int *) checked_malloc( 2 * sizeof( int ) ) ; if( fCp_ptr->coupling_list != NULL ) { *(fCp_ptr->coupling_list) = Cc_ptr->list_number ; *(fCp_ptr->coupling_list + 1) = 0 ; /* terminate list */ } else fail = TRUE ; } else fail = TRUE ; if( father ) { if( rect_bottom( &(fCp_ptr->box) ) > parent_box_bottom ) parent_box_bottom = rect_bottom( &(fCp_ptr->box) ) ; } else parent_box_bottom = rect_bottom( &(fCp_ptr->box) ) ; } Cc_ptr->hline_x0 = leftest_sibling_x ; Cc_ptr->hline_x1 = rightest_sibling_x ; Cc_ptr->hline_y = parent_box_bottom + generation_gap / 2 ; if( fail ) { /* remove children */ child = 0 ; while( child < children ) { if( Cc_ptr->child_numbers[child] != Cp_ptr->list_number ) remove_custom_person( get_Cp_ptr( Cc_ptr->child_numbers[child] ) ) ; child++ ; } if( mCp_ptr ) remove_custom_person( mCp_ptr ) ; if( fCp_ptr ) remove_custom_person( fCp_ptr ) ; Cp_ptr->parent_number = 0 ; remove_custom_coupling( Cc_ptr ) ; Cc_ptr = NULL ; } return Cc_ptr ; }