/*****************************************************************************/ /* */ /* F I S T : Fast, Industrial-Strength Triangulation */ /* */ /*****************************************************************************/ /* */ /* (C) Martin Held */ /* (C) Universitaet Salzburg, Salzburg, Austria */ /* */ /* This code is not in the public domain. All rights reserved! Please make */ /* sure to read the full copyright statement contained in api_functions.cpp. */ /* */ /*****************************************************************************/ /* */ /* get standard libraries */ /* */ #include #include #include /* */ /* get my header files */ /* */ #include "fpkernel.h" #include "martin.h" #include "defs.h" #include "header.h" #include "list.h" #ifdef PARTITION_FIST #ifdef __APPLE__ #define omp_get_max_threads() (4) #else #include #endif #endif #define BLOCK_SIZE 65536 /* */ /* prototypes of functions provided in this file */ /* */ void InitGlobalStruct(global_struct *all, rt_options *rt_opt, boolean stand_alone); void InitDataDefaults(datadef *data); #ifdef EXT_APPL_SITES int StorePnt(datadef *data, double x, double y, eas_type eas_data); #else int StorePnt(datadef *data, double x, double y); #endif void DecrementPoints(datadef *data); void InitPnts(datadef *data,int number); void FreePnts(datadef *data); void SetBoundingBox(datadef *data, point *bb_min, point *bb_max); boolean InPointsList(datadef *data, int index); void InitStoragePnts(datadef *data, int number); void ScaleData(global_struct *all); /* */ /* Initialize the default values for FIST's structures and options */ /* */ void InitGlobalStruct(global_struct *all, rt_options *rt_opt, boolean stand_alone) { #ifdef PARTITION_FIST heapdef *hp; #endif if (rt_opt == (rt_options*)NULL) { InitDefaults(&all->rt_opt); } else { all->rt_opt = *rt_opt; } InitListDefaults(&all->c_list); InitBridgeDefaults(&all->c_bridge); InitVertexDef(&all->c_vertex); InitDataDefaults(&all->c_data); InitCleanDefaults(&all->c_clean); InitGridDefaults(&all->c_grid); InitQuadsDefaults(&all->c_quad); InitIOListDefaults(&all->c_iolist); Init3dDefaults(&all->c_io3d); #ifdef GRAPHICS InitRedrawDefaults(&all->c_redraw); #endif #ifdef DEBUG_MEMORY InitDebugMemDefaults(&all->c_mem); #endif InitEarDefaults(&all->c_ear); #ifdef PARTITION_FIST all->number_of_heaps = omp_get_max_threads(); all->partition_mode = true; InitPartitionedHeap(all); for(int i = 0; i < all->number_of_heaps; ++i) { hp = &all->c_heap[i]; #ifdef DEBUG_MEMORY hp->memptr = &all->c_mem; #endif InitHeapDefaults(hp); hp->sorted = hp->ears_sorted = all->rt_opt.ears_sorted; hp->ears_random = all->rt_opt.ears_random; } #else InitHeapDefaults(&all->c_heap); all->c_heap.sorted = all->c_heap.ears_sorted = all->rt_opt.ears_sorted; all->c_heap.ears_random = all->rt_opt.ears_random; #ifdef DEBUG_MEMORY all->c_heap.memptr = &all->c_mem; #endif #endif #ifdef DEBUG_MEMORY #ifdef GRAPHICS all->c_redraw.memptr = &all->c_mem; #endif all->c_data.memptr = &all->c_mem; all->c_list.memptr = &all->c_mem; all->c_clean.memptr = &all->c_mem; all->c_bridge.memptr = &all->c_mem; all->c_vertex.memptr = &all->c_mem; all->c_grid.memptr = &all->c_mem; #endif all->poly_area = (double*)NULL; all->max_num_poly_area = 0; #ifdef GRAPHICS all->draw_pnts = true; all->draw_point_idx = false; #endif all->ccw_loop = true; all->new_input = false; all->cpu_time = 0.0; all->curr_loop_main = 0; all->dxf_file = (FILE*)NULL; all->ipe_initialized = false; all->c_ipe_io.ipe7 = all->rt_opt.write_ipe7; all->done = false; all->reset = false; all->troubles = false; all->written = false; if (!stand_alone) { /* */ /* make sure that FIST does its job silently, without graphics. */ /* */ all->rt_opt.quiet = true; all->rt_opt.graphics = false; } all->c_ear.ears_fancy = all->rt_opt.ears_fancy; all->c_ear.ears_top = all->rt_opt.ears_top; all->c_ear.use_colors = all->rt_opt.use_colors; #ifdef CPUTIME_VIA_CLOCK all->cpu_time_initialized = false; #endif #ifdef CPUTIME_IN_MILLISECONDS all->total_secs = 0; all->total_usecs = 0; #endif #ifdef EXPR_WRAPPER all->returncore = false; #endif return; } void InitDataDefaults(datadef *data) { data->points = (point*)NULL; data->num_pnts = 0; data->max_num_pnts = 0; return; } #ifdef EXT_APPL_SITES int StorePnt(datadef *data, double x, double y, eas_type eas_data) #else int StorePnt(datadef *data, double x, double y) #endif { int i; if (data->num_pnts >= data->max_num_pnts) { data->max_num_pnts += BLOCK_SIZE; data->points = CORE_ReallocateArray(data->memptr, data->points, data->max_num_pnts - BLOCK_SIZE, data->max_num_pnts, point, "data:points"); } data->points[data->num_pnts].x = x; data->points[data->num_pnts].y = y; #ifdef EXT_APPL_SITES data->points[data->num_pnts].ext_appl = eas_data; #endif /* */ /* let the user call some application-specific function */ /* */ ExtApplFuncStorePnt; i = data->num_pnts; ++data->num_pnts; return i; } void DecrementPoints(datadef *data) { --data->num_pnts; return; } void InitPnts(datadef *data, int number) { if (data->max_num_pnts < number) { data->points = CORE_ReallocateArray(data->memptr, data->points, data->max_num_pnts, number, point, "data:points"); data->max_num_pnts = number; } data->num_pnts = 0; data->data_scaled = false; data->scale_factor = C_1_0; data->shift.x = C_0_0; data->shift.y = C_0_0; return; } void InitStoragePnts(datadef *data, int number) { if (data->max_num_pnts < number) { data->points = CORE_ReallocateArray(data->memptr, data->points, data->max_num_pnts, number, point, "data:points"); data->max_num_pnts = number; } return; } void FreePnts(datadef *data) { CORE_FreeMemory(data->memptr, &data->points, "data:points"); data->max_num_pnts = 0; data->num_pnts = 0; return; } /* */ /* this routine returns the bounding box of the sorted entries of "points" */ /* */ void SetBoundingBox(datadef *data, point *bb_min, point *bb_max) { int i; machine_double x_ext, y_ext; if (data->num_pnts > 0) { bb_min->x = data->points[0].x; bb_max->x = data->points[data->num_pnts-1].x; bb_min->y = data->points[0].y; bb_max->y = bb_min->y; for (i = 1; i < data->num_pnts; ++i) { if (data->points[i].y < bb_min->y) bb_min->y = data->points[i].y; else if (data->points[i].y > bb_max->y) bb_max->y = data->points[i].y; } x_ext = TO_MDOUBLE(bb_max->x) - TO_MDOUBLE(bb_min->x); y_ext = TO_MDOUBLE(bb_max->y) - TO_MDOUBLE(bb_min->y); data->bbox_diagonal_sqd = x_ext * x_ext + y_ext * y_ext; } return; } void ComputeBoundingBox(datadef *data, listdef *list, list_ind ind, point *bb_min, point *bb_max) { int i; list_ind ind1; machine_double x_ext, y_ext; ind1 = ind; i = GetIndex(list,ind1); bb_min->x = data->points[i].x; bb_max->x = data->points[i].x; bb_min->y = data->points[i].y; bb_max->y = data->points[i].y; do { i = GetIndex(list,ind1); if (data->points[i].x < bb_min->x) bb_min->x = data->points[i].x; else if (data->points[i].x > bb_max->x) bb_max->x = data->points[i].x; if (data->points[i].y < bb_min->y) bb_min->y = data->points[i].y; else if (data->points[i].y > bb_max->y) bb_max->y = data->points[i].y; ind1 = GetNextNode(list,ind1); } while (ind1 != ind); x_ext = TO_MDOUBLE(bb_max->x) - TO_MDOUBLE(bb_min->x); y_ext = TO_MDOUBLE(bb_max->y) - TO_MDOUBLE(bb_min->y); data->bbox_diagonal_sqd = x_ext * x_ext + y_ext * y_ext; return; } boolean InPointsList(datadef *data, int index) { return ((index >= 0) && (index < data->num_pnts) && (data->num_pnts <= data->max_num_pnts)); } /* */ /* scale the data if necessary. */ /* */ void ScaleData(global_struct *all) { datadef *data = &all->c_data; int i; machine_double xy, x_ext, y_ext; x_ext = TO_MDOUBLE(all->bb_max.x) - TO_MDOUBLE(all->bb_min.x); y_ext = TO_MDOUBLE(all->bb_max.y) - TO_MDOUBLE(all->bb_min.y); xy = Max(x_ext, y_ext); xy = Max(xy, ZERO_D); data->scale_factor = 1.0; if (xy > CD_3_0) { do { data->scale_factor /= C_2_0; } while ((xy * data->scale_factor) > C_3_0); data->data_scaled = true; } else if (xy < CD_0_3) { do { data->scale_factor *= C_2_0; } while ((xy * data->scale_factor) < C_0_3); data->data_scaled = true; } else if ((all->bb_max.x > C_2_0) || (all->bb_max.y > C_2_0) || (all->bb_min.x < C_m2_0) || (all->bb_min.y < C_m2_0)) { data->data_scaled = true; } if (data->data_scaled) { data->shift.x = (all->bb_min.x + all->bb_max.x) / C_2_0; data->shift.y = (all->bb_min.y + all->bb_max.y) / C_2_0; for (i = 0; i < data->num_pnts; ++i) { data->points[i].x = (data->points[i].x - data->shift.x) * data->scale_factor; data->points[i].y = (data->points[i].y - data->shift.y) * data->scale_factor; } all->bb_max.x = (all->bb_max.x - data->shift.x) * data->scale_factor; all->bb_max.y = (all->bb_max.y - data->shift.y) * data->scale_factor; all->bb_min.x = (all->bb_min.x - data->shift.x) * data->scale_factor; all->bb_min.y = (all->bb_min.y - data->shift.y) * data->scale_factor; } else { data->shift.x = C_0_0; data->shift.y = C_0_0; data->scale_factor = C_1_0; } x_ext = TO_MDOUBLE(all->bb_max.x) - TO_MDOUBLE(all->bb_min.x); y_ext = TO_MDOUBLE(all->bb_max.y) - TO_MDOUBLE(all->bb_min.y); data->bbox_diagonal_sqd = x_ext * x_ext + y_ext * y_ext; return; }