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 ;

}
Example #2
0
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);
}
Example #3
0
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;

}
Example #4
0
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;
    }
}