Arc *generate_circle_arc(float radius, Pixel center, float start_pos, float circle_part) { /** Generate an arc from radius radius * from center center * length from part of an circle circle_part * starting at offset start_pos. *******************************************/ if (circle_part == 0.0f) { fprintf(stderr,"You cannot givezero as circle_part argument !\n") ; return NULL ; } Arc *res = (Arc *) malloc(sizeof(Arc)) ; res->count = (uint16_t) roundf(360.0f/(360.0f/circle_part)) ; res->count = res->count == 0 ? 1 : res->count ; res->coords_calc.x= (float *) calloc((size_t) res->count,sizeof(float)) ; res->coords_calc.y= (float *) calloc((size_t) res->count,sizeof(float)) ; res->coords.x= (int16_t *) calloc((size_t) res->count,sizeof(int16_t)) ; res->coords.y= (int16_t *) calloc((size_t) res->count,sizeof(int16_t)) ; int i=0 ; while (i < (int) res->count) { Pixel tmp ; tmp=get_pixel_coords(i, 360.0f, radius, center , start_pos) ; res->coords_calc.x[i] = tmp.x ; res->coords_calc.y[i] = tmp.y ; res->coords.x[i] = (int16_t) roundf(tmp.x) ; res->coords.y[i] = (int16_t) roundf(tmp.y) ; i += 1 ; } res->center.x=center.x ; res->center.y=center.y ; //Arc *arc = remove_doubles_form(res) ; return res ; //return res ; }
void TextureView::export_triangle(math::Vec3f v1, math::Vec3f v2, math::Vec3f v3, std::string const & filename) const { assert(image != NULL); math::Vec2f p1 = get_pixel_coords(v1); math::Vec2f p2 = get_pixel_coords(v2); math::Vec2f p3 = get_pixel_coords(v3); assert(valid_pixel(p1) && valid_pixel(p2) && valid_pixel(p3)); Tri tri(p1, p2, p3); Rect<float> aabb = tri.get_aabb(); const int width = ceil(aabb.width()); const int height = ceil(aabb.height()); const int left = floor(aabb.min_x); const int top = floor(aabb.max_y); assert(width > 0 && height > 0); mve::image::save_png_file(mve::image::crop(image, width, height, left, top, *math::Vec3uc(255, 0, 255)), filename); }
Spiral *generate_simple_spiral(Pixel center, uint32_t turns, uint32_t base, float offset_exponent, float orientation, _Bool reverse) { /** Generate an spiral according following settings: * * center: the center of the spiral starts from. * turns: the number of turns around the center the spiral make. * base: the base number of points to make one turn (divided per 2). * offset_exponent: the distance of space for the spiral progression. * orientation: start position in degrees angle values. * reverse: drive the spiral reversed. * * @NOTE: if you generate too much vertice your application will block. * So use only 1 or few spirals from reasonable size(s). * By setting a new radius (a spiral doesn't really have a radius) take care of size limits. * The radius from the spiral is computed as the distance between the center and the endpoint. * // This limitations are due of the int16_t type used from the SDL2_gfx standart. * // @see the display function from SDL2_gfx. *************************************************************************************************************/ /** @NOTE: the radius is the end of the first entire revolution of the spiral. *****************************************************************************/ if (base <= 11) { fprintf(stderr, "base argument value to little: base must be base > 11 !\n"); exit(EXIT_FAILURE); } if (turns <= 0) { fprintf(stderr, "turns argument value to little: turns must be turns > 0 !\n"); exit(EXIT_FAILURE); } /** Compute the angle between 2 points from the spiral **/ float round_offset = 360.0f / base; int32_t c, cc, ii; uint32_t points_count = (uint32_t) 360.0f / round_offset; /** Array of relative angles between 2 points from one turn. **/ float base_point_range[points_count]; float turn_iterator; for (turn_iterator = 0.0f, c = 0; turn_iterator <= 360.0f; turn_iterator += round_offset, c++) { /** Generate the angles offsets. **/ base_point_range[c] = turn_iterator; } c = 0; cc = points_count; while (c < points_count) { /** Reverse the angles offsets array. **/ float tmp; tmp = base_point_range[c]; base_point_range[c] = base_point_range[cc]; base_point_range[cc] = tmp; c++; cc--; } /** Result spiral **/ Spiral *spiral = (Spiral *) malloc(sizeof(Spiral)); spiral->count = turns * points_count; spiral->coords.x = (float *) calloc((size_t) spiral->count, sizeof(float)); spiral->coords.y = (float *) calloc((size_t) spiral->count, sizeof(float)); float distance = offset_exponent; float incr = offset_exponent; Pixel radius; ii = 0; if (!reverse) { c = 0; while (c < turns) { /** Generate a turn from the spiral **/ cc = 0; while (cc < points_count) { /** Setting every pixel from the turn: **/ Pixel res; res = get_pixel_coords(cc, base, distance, center, base_point_range[cc]); spiral->coords.x[ii] = res.x; spiral->coords.y[ii] = res.y; if (cc == points_count - 1 && c == 0) { radius = res; } cc++; ii++; distance += incr; } c++; } } else { c = 0; ii = 0; while (c < turns) { /** Generate a turn from the spiral **/ cc = points_count - 1; while (cc >= 0) { /** Setting every pixel from the turn: **/ Pixel res; res = get_pixel_coords(cc, base, distance, center, base_point_range[cc]); spiral->coords.x[ii] = res.x; spiral->coords.y[ii] = res.y; if (cc == 0 && c == 0) { radius = res; } ii++; cc--; distance += incr; } c++; } } c = 0; if (orientation) { rotate_form(spiral, orientation); } Pixel px; px.x = spiral->coords.x[spiral->count - 1]; px.y = spiral->coords.y[spiral->count - 1]; spiral->center.x = center.x; spiral->center.y = center.y; spiral->length = get_distance_pixels(spiral->center, radius); spiral->orientation = orientation; spiral->real_length = get_distance_pixels(spiral->center, px); return spiral; }
void TextureView::get_face_info(math::Vec3f const & v1, math::Vec3f const & v2, math::Vec3f const & v3, ProjectedFaceInfo * face_info, Settings const & settings) const { assert(image != NULL); assert(settings.data_term != GMI || gradient_magnitude != NULL); math::Vec2f p1 = get_pixel_coords(v1); math::Vec2f p2 = get_pixel_coords(v2); math::Vec2f p3 = get_pixel_coords(v3); assert(valid_pixel(p1) && valid_pixel(p2) && valid_pixel(p3)); Tri tri(p1, p2, p3); float area = tri.get_area(); if (area < std::numeric_limits<float>::epsilon()) { face_info->quality = 0.0f; return; } std::size_t num_samples = 0; math::Vec3d colors(0.0); double gmi = 0.0; bool sampling_necessary = settings.data_term != AREA || settings.outlier_removal != NONE; if (sampling_necessary && area > 0.5f) { /* Sort pixels in ascending order of y */ while (true) if(p1[1] <= p2[1]) if(p2[1] <= p3[1]) break; else std::swap(p2, p3); else std::swap(p1, p2); /* Calculate line equations. */ float const m1 = (p1[1] - p3[1]) / (p1[0] - p3[0]); float const b1 = p1[1] - m1 * p1[0]; /* area != 0.0f => m1 != 0.0f. */ float const m2 = (p1[1] - p2[1]) / (p1[0] - p2[0]); float const b2 = p1[1] - m2 * p1[0]; float const m3 = (p2[1] - p3[1]) / (p2[0] - p3[0]); float const b3 = p2[1] - m3 * p2[0]; bool fast_sampling_possible = std::isfinite(m1) && m2 != 0.0f && std::isfinite(m2) && m3 != 0.0f && std::isfinite(m3); Rect<float> aabb = tri.get_aabb(); for (int y = std::floor(aabb.min_y); y < std::ceil(aabb.max_y); ++y) { float min_x = aabb.min_x - 0.5f; float max_x = aabb.max_x + 0.5f; if (fast_sampling_possible) { float const cy = static_cast<float>(y) + 0.5f; min_x = (cy - b1) / m1; if (cy <= p2[1]) max_x = (cy - b2) / m2; else max_x = (cy - b3) / m3; if (min_x >= max_x) std::swap(min_x, max_x); if (min_x < aabb.min_x || min_x > aabb.max_x) continue; if (max_x < aabb.min_x || max_x > aabb.max_x) continue; } for (int x = std::floor(min_x + 0.5f); x < std::ceil(max_x - 0.5f); ++x) { math::Vec3d color; const float cx = static_cast<float>(x) + 0.5f; const float cy = static_cast<float>(y) + 0.5f; if (!fast_sampling_possible && !tri.inside(cx, cy)) continue; if (settings.outlier_removal != NONE) { for (std::size_t i = 0; i < 3; i++){ color[i] = static_cast<double>(image->at(x, y, i)) / 255.0; } colors += color; } if (settings.data_term == GMI) { gmi += static_cast<double>(gradient_magnitude->at(x, y, 0)) / 255.0; } ++num_samples; } } } if (settings.data_term == GMI) { if (num_samples > 0) { gmi = (gmi / num_samples) * area; } else { double gmv1 = static_cast<double>(gradient_magnitude->linear_at(p1[0], p1[1], 0)) / 255.0; double gmv2 = static_cast<double>(gradient_magnitude->linear_at(p2[0], p2[1], 0)) / 255.0; double gmv3 = static_cast<double>(gradient_magnitude->linear_at(p3[0], p3[1], 0)) / 255.0; gmi = ((gmv1 + gmv2 + gmv3) / 3.0) * area; } } if (settings.outlier_removal != NONE) { if (num_samples > 0) { face_info->mean_color = colors / num_samples; } else { math::Vec3d c1, c2, c3; for (std::size_t i = 0; i < 3; ++i) { c1[i] = static_cast<double>(image->linear_at(p1[0], p1[1], i)) / 255.0; c2[i] = static_cast<double>(image->linear_at(p2[0], p2[1], i)) / 255.0; c3[i] = static_cast<double>(image->linear_at(p3[0], p3[1], i)) / 255.0; } face_info->mean_color = ((c1 + c2 + c3) / 3.0); } } switch (settings.data_term) { case AREA: face_info->quality = area; break; case GMI: face_info->quality = gmi; break; } }