void ft_impact(t_draw_suite *val, t_ray *ray, t_tool *t) { val->impact->o = vectoradd(ray->o, vectorscale(val->curobject->dist, ray->d)); find_normal(val->impact, val->curobject); vectornorm(val->impact->d); init_color(t, val->curobject->color, val->final_color); val->curlight = t->l_lights; while (val->curlight) { val->lightray->o = vectorcopy(val->curlight->o); val->lightray->d = vectorsub(val->impact->o, val->lightray->o); vectornorm(val->lightray->d); if ((val->curobject2 = intersection(t->l_objects, val->lightray)) && val->curobject2 == val->curobject) ft_impact2(val); val->curlight = val->curlight->next; } }
void process(void) { /*--------------------------------------------------------------------------*/ /* INITIALISE */ /*--------------------------------------------------------------------------*/ DCELL *row_in, /* Buffer large enough to hold `wsize' */ *row_out = NULL, /* raster rows. When GRASS reads in a */ /* raster row, each element is of type */ /* DCELL */ *window_ptr, /* Stores local terrain window. */ centre; /* Elevation of central cell in window. */ CELL *featrow_out = NULL; /* store features in CELL */ struct Cell_head region; /* Structure to hold region information */ int nrows, /* Will store the current number of */ ncols, /* rows and columns in the raster. */ row, col, /* Counts through each row and column */ /* of the input raster. */ wind_row, /* Counts through each row and column */ wind_col, /* of the local neighbourhood window. */ *index_ptr; /* Row permutation vector for LU decomp. */ double **normal_ptr, /* Cross-products matrix. */ *obs_ptr, /* Observed vector. */ temp; /* Unused */ double *weight_ptr; /* Weighting matrix for observed values. */ /*--------------------------------------------------------------------------*/ /* GET RASTER AND WINDOW DETAILS */ /*--------------------------------------------------------------------------*/ G_get_window(®ion); /* Fill out the region structure (the */ /* geographical limits etc.) */ nrows = Rast_window_rows(); /* Find out the number of rows and */ ncols = Rast_window_cols(); /* columns of the raster. */ if ((region.ew_res / region.ns_res >= 1.01) || /* If EW and NS resolns are */ (region.ns_res / region.ew_res >= 1.01)) { /* >1% different, warn user. */ G_warning(_("E-W and N-S grid resolutions are different. Taking average.")); resoln = (region.ns_res + region.ew_res) / 2; } else resoln = region.ns_res; /*--------------------------------------------------------------------------*/ /* RESERVE MEMORY TO HOLD Z VALUES AND MATRICES */ /*--------------------------------------------------------------------------*/ row_in = (DCELL *) G_malloc(ncols * sizeof(DCELL) * wsize); /* Reserve `wsize' rows of memory. */ if (mparam != FEATURE) row_out = Rast_allocate_buf(DCELL_TYPE); /* Initialise output row buffer. */ else featrow_out = Rast_allocate_buf(CELL_TYPE); /* Initialise output row buffer. */ window_ptr = (DCELL *) G_malloc(SQR(wsize) * sizeof(DCELL)); /* Reserve enough memory for local wind. */ weight_ptr = (double *)G_malloc(SQR(wsize) * sizeof(double)); /* Reserve enough memory weights matrix. */ normal_ptr = dmatrix(0, 5, 0, 5); /* Allocate memory for 6*6 matrix */ index_ptr = ivector(0, 5); /* and for 1D vector holding indices */ obs_ptr = dvector(0, 5); /* and for 1D vector holding observed z */ /* ---------------------------------------------------------------- */ /* - CALCULATE LEAST SQUARES COEFFICIENTS - */ /* ---------------------------------------------------------------- */ /*--- Calculate weighting matrix. ---*/ find_weight(weight_ptr); /* Initial coefficients need only be found once since they are constant for any given window size. The only element that changes is the observed vector (RHS of normal equations). */ /*--- Find normal equations in matrix form. ---*/ find_normal(normal_ptr, weight_ptr); /*--- Apply LU decomposition to normal equations. ---*/ if (constrained) { G_ludcmp(normal_ptr, 5, index_ptr, &temp); /* To constrain the quadtratic through the central cell, ignore the calculations involving the coefficient f. Since these are all in the last row and column of the matrix, simply redimension. */ /* disp_matrix(normal_ptr,obs_ptr,obs_ptr,5); */ } else { G_ludcmp(normal_ptr, 6, index_ptr, &temp); /* disp_matrix(normal_ptr,obs_ptr,obs_ptr,6); */ } /*--------------------------------------------------------------------------*/ /* PROCESS INPUT RASTER AND WRITE OUT RASTER LINE BY LINE */ /*--------------------------------------------------------------------------*/ if (mparam != FEATURE) for (wind_row = 0; wind_row < EDGE; wind_row++) Rast_put_row(fd_out, row_out, DCELL_TYPE); /* Write out the edge cells as NULL. */ else for (wind_row = 0; wind_row < EDGE; wind_row++) Rast_put_row(fd_out, featrow_out, CELL_TYPE); /* Write out the edge cells as NULL. */ for (wind_row = 0; wind_row < wsize - 1; wind_row++) Rast_get_row(fd_in, row_in + (wind_row * ncols), wind_row, DCELL_TYPE); /* Read in enough of the first rows to */ /* allow window to be examined. */ for (row = EDGE; row < (nrows - EDGE); row++) { G_percent(row + 1, nrows - EDGE, 2); Rast_get_row(fd_in, row_in + ((wsize - 1) * ncols), row + EDGE, DCELL_TYPE); for (col = EDGE; col < (ncols - EDGE); col++) { /* Find central z value */ centre = *(row_in + EDGE * ncols + col); for (wind_row = 0; wind_row < wsize; wind_row++) for (wind_col = 0; wind_col < wsize; wind_col++) /* Express all window values relative */ /* to the central elevation. */ *(window_ptr + (wind_row * wsize) + wind_col) = *(row_in + (wind_row * ncols) + col + wind_col - EDGE) - centre; /*--- Use LU back substitution to solve normal equations. ---*/ find_obs(window_ptr, obs_ptr, weight_ptr); /* disp_wind(window_ptr); disp_matrix(normal_ptr,obs_ptr,obs_ptr,6); */ if (constrained) { G_lubksb(normal_ptr, 5, index_ptr, obs_ptr); /* disp_matrix(normal_ptr,obs_ptr,obs_ptr,5); */ } else { G_lubksb(normal_ptr, 6, index_ptr, obs_ptr); /* disp_matrix(normal_ptr,obs_ptr,obs_ptr,6); */ } /*--- Calculate terrain parameter based on quad. coefficients. ---*/ if (mparam == FEATURE) *(featrow_out + col) = (CELL) feature(obs_ptr); else *(row_out + col) = param(mparam, obs_ptr); if (mparam == ELEV) *(row_out + col) += centre; /* Add central elevation back */ } if (mparam != FEATURE) Rast_put_row(fd_out, row_out, DCELL_TYPE); /* Write the row buffer to the output */ /* raster. */ else /* write FEATURE to CELL */ Rast_put_row(fd_out, featrow_out, CELL_TYPE); /* Write the row buffer to the output */ /* raster. */ /* 'Shuffle' rows down one, and read in */ /* one new row. */ for (wind_row = 0; wind_row < wsize - 1; wind_row++) for (col = 0; col < ncols; col++) *(row_in + (wind_row * ncols) + col) = *(row_in + ((wind_row + 1) * ncols) + col); } for (wind_row = 0; wind_row < EDGE; wind_row++) { if (mparam != FEATURE) Rast_put_row(fd_out, row_out, DCELL_TYPE); /* Write out the edge cells as NULL. */ else Rast_put_row(fd_out, featrow_out, CELL_TYPE); /* Write out the edge cells as NULL. */ } /*--------------------------------------------------------------------------*/ /* FREE MEMORY USED TO STORE RASTER ROWS, LOCAL WINDOW AND MATRICES */ /*--------------------------------------------------------------------------*/ G_free(row_in); if (mparam != FEATURE) G_free(row_out); else G_free(featrow_out); G_free(window_ptr); free_dmatrix(normal_ptr, 0, 5, 0, 5); free_dvector(obs_ptr, 0, 5); free_ivector(index_ptr, 0, 5); }
int main( int argc, char ** argv ) { double inset_distance = 5; double hole_radius = 1.15; const char * input_file = NULL; const char * output_file = NULL; int show_model = 0; int option_index = 0; while (1) { const int c = getopt_long( argc, argv, "vmI:r:i:O:", long_options, &option_index ); if (c == -1) break; switch(c) { case 'm': show_model = 1; break; case 'v': verbose++; break; case 'i': inset_distance = atof(optarg); break; case 'r': hole_radius = atof(optarg); break; case 'I': input_file = optarg; break; case 'O': output_file = optarg; break; case 'h': case '?': usage(stdout); return 0; default: usage(stderr); return -1; } } int input_fd; if (!input_file) { fprintf(stderr, "Input STL must be specified\n"); return -1; } else { input_fd = open(input_file, O_RDONLY); if (input_fd < 0) { perror(input_file); return -1; } } if (!output_file) { output_file = "stdout"; output = stdout; } else { output = fopen(output_file, "w"); if (!output) { perror(output_file); return -1; } } stl_3d_t * const stl = stl_3d_parse(input_fd); if (!stl) { fprintf(stderr, "%s: Unable to parse STL\n", input_file); return EXIT_FAILURE; } close(input_fd); if (verbose) fprintf(stderr, "%s: %d faces, %d vertex\n", input_file, stl->num_face, stl->num_vertex ); fprintf(output, "module model() {\n" "render() difference() {\n" "import(\"%s\");\n", input_file ); //printf("%%model();\n"); int * const face_used = calloc(sizeof(*face_used), stl->num_face); const stl_vertex_t ** const vertex_list = calloc(sizeof(*vertex_list), stl->num_vertex); // for face, generate the set of coplanar points that go with it // and "drill" holes in the model for those corners. for (int i = 0 ; i < stl->num_face ; i++) { if (face_used[i]) continue; const stl_face_t * const f = &stl->face[i]; const int vertex_count = stl_trace_face( stl, f, vertex_list, face_used, 0 ); refframe_t ref; refframe_init( &ref, f->vertex[0]->p, f->vertex[1]->p, f->vertex[2]->p ); // replace the origin with the actual origin //ref.origin.p[0] = 0; //ref.origin.p[1] = 0; //ref.origin.p[2] = 0; fprintf(output, "translate([%f,%f,%f])", f->vertex[0]->p.p[0], f->vertex[0]->p.p[1], f->vertex[0]->p.p[2] ); print_multmatrix(&ref, 0); fprintf(output, "{\n"); // generate a bolt hole for each non-copolanar corner for (int j = 0 ; j < vertex_count ; j++) { double x, y; refframe_inset( &ref, inset_distance, &x, &y, vertex_list[(j+0) % vertex_count]->p, vertex_list[(j+1) % vertex_count]->p, vertex_list[(j+2) % vertex_count]->p ); fprintf(output, "translate([%f,%f,0]) cylinder(r=%f, h=%f, center=true);\n", x, y, hole_radius, 10.0 ); } fprintf(output, "}\n"); } fprintf(output, "}\n}\n"); if (show_model) fprintf(output, "model();\n"); // For each vertex, extract a small region around the corner const int div = sqrt(stl->num_vertex); const double spacing = 32; for(int i = 0 ; i < stl->num_vertex ; i++) { const stl_vertex_t * const v = &stl->vertex[i]; const v3_t origin = v->p; v3_t avg = {{ 0, 0, 0}}; find_normal(stl, v, inset_distance, &avg); if (!show_model) { fprintf(output, "translate([%f,%f,20])", (i/div)*spacing, (i%div)*spacing); fprintf(output, "render() intersection()"); } fprintf(output, "{\n"); //printf("%%\n"); if (!show_model) { print_normal(&avg, show_model); fprintf(output, "translate([%f,%f,%f])", -origin.p[0], -origin.p[1], -origin.p[2]); fprintf(output, "model();\n"); fprintf(output, "translate([0,0,-20]) cylinder(r=15,h=20);\n"); } else { fprintf(output, "translate([%f,%f,%f])", origin.p[0], origin.p[1], origin.p[2]); print_normal(&avg, show_model); fprintf(output, "%%translate([0,0,-20]) cylinder(r=15,h=20);\n"); } //avg = v3_norm(avg); fprintf(output, "}\n"); } return 0; }
void tess_test_polygon(GLUtriangulatorObj * tobj) { tess_polygon *polygon = tobj->current_polygon; /* any vertices defined? */ if (polygon->vertex_cnt < 3) { free_current_polygon(polygon); return; } /* wrap pointers */ polygon->last_vertex->next = polygon->vertices; polygon->vertices->previous = polygon->last_vertex; /* determine the normal */ if (find_normal(tobj) == GLU_ERROR) return; /* compare the normals of previously defined contours and this one */ /* first contour define ? */ if (tobj->contours == NULL) { tobj->A = polygon->A; tobj->B = polygon->B; tobj->C = polygon->C; tobj->D = polygon->D; /* determine the best projection to use */ if (fabs(polygon->A) > fabs(polygon->B)) if (fabs(polygon->A) > fabs(polygon->C)) tobj->projection = OYZ; else tobj->projection = OXY; else if (fabs(polygon->B) > fabs(polygon->C)) tobj->projection = OXZ; else tobj->projection = OXY; } else { GLdouble a[3], b[3]; tess_vertex *vertex = polygon->vertices; a[0] = tobj->A; a[1] = tobj->B; a[2] = tobj->C; b[0] = polygon->A; b[1] = polygon->B; b[2] = polygon->C; /* compare the normals */ if (fabs(a[1] * b[2] - a[2] * b[1]) > EPSILON || fabs(a[2] * b[0] - a[0] * b[2]) > EPSILON || fabs(a[0] * b[1] - a[1] * b[0]) > EPSILON) { /* not coplanar */ tess_call_user_error(tobj, GLU_TESS_ERROR9); return; } /* the normals are parallel - test for plane equation */ if (fabs(a[0] * vertex->location[0] + a[1] * vertex->location[1] + a[2] * vertex->location[2] + tobj->D) > EPSILON) { /* not the same plane */ tess_call_user_error(tobj, GLU_TESS_ERROR9); return; } } prepare_projection_info(tobj); if (verify_edge_vertex_intersections(tobj) == GLU_ERROR) return; if (test_for_overlapping_contours(tobj) == GLU_ERROR) return; if (store_polygon_as_contour(tobj) == GLU_ERROR) return; }