Rectangle GeometricRecognizer::boundingBox(Path2D points)
	{
		double minX =  MAX_DOUBLE;
		double maxX = -MAX_DOUBLE;
		double minY =  MAX_DOUBLE; 
		double maxY = -MAX_DOUBLE;

		for (Path2DIterator i = points.begin(); i != points.end(); i++)
		{
			Point2D point = *i;
			if (point.x < minX)
				minX = point.x;
			if (point.x > maxX)
				maxX = point.x;
			if (point.y < minY)
				minY = point.y;
			if (point.y > maxY)
				maxY = point.y;
		}
		Rectangle bounds(minX, minY, (maxX - minX), (maxY - minY));
		return bounds;
	}
Ejemplo n.º 2
0
//use 40 point
Path2D CTemplateRecorder::OutputRectange()
{
	Path2D path;
	path.resize(40);
	int curIndex = 0;
	//left edge
	//four points 
	//left bottom 0,0
	//left top 0,100
	//right top 100,100
	//right bottom 100,0
	for(int i=0;i<10;++i)  //left bottom to left top
	{
		path[curIndex].x = 0.0f;
		path[curIndex].y = i*10.0f; 
		curIndex ++;
	}
	for(int i=0;i<10;++i) //left top to right top
	{
		path[curIndex].x = i*10.0f;
		path[curIndex].y = 100.0f; 
		curIndex ++;
	}
	for(int i=0;i<10;++i)  //right top to right bottom
	{
		path[curIndex].x = 100.0f;
		path[curIndex].y = 100.0f - i*10.0f;
		curIndex ++;
	}
	for(int i=0;i<10;++i)
	{
		path[curIndex].x = 100.0f - i*10.0f;
		path[curIndex].y = 0.0f; 
		curIndex ++;
	}
	return path;
}
Ejemplo n.º 3
0
std::vector<Vector2f> GeneratePathNormals(const Path2D& path, bool is_closed,
                                          bool outward) {
  assert(path.size() >= 2);
  // Here we are going to use a simple 3-point interpolation method
  // first we need to make the path in ccw direction
  ClipperLib::Path scaled_path = UScalePathDiaToClipper(path);
  if (!ClipperLib::Orientation(scaled_path)) {
    ClipperLib::ReversePath(scaled_path);
  }
  Path2D ccw_path = DScalePathClipperToDia(scaled_path);

  // Special treatment for the first and last point.
  std::vector<Vector2f> output_vecs(path.size());
  if (is_closed) {
    output_vecs[0] =
        GetNormalFromTwoPoints(ccw_path[ccw_path.size() - 1], ccw_path[1]);
    output_vecs.back() =
        GetNormalFromTwoPoints(ccw_path[ccw_path.size() - 2], ccw_path[0]);
  } else {
    output_vecs[0] = GetNormalFromTwoPoints(ccw_path[0], ccw_path[1]);
    output_vecs.back() = GetNormalFromTwoPoints(ccw_path[ccw_path.size() - 2],
                                                ccw_path[ccw_path.size() - 1]);
  }

  // We use the point before and after ith point to interpolate its normal.
  for (size_t i = 1; i < ccw_path.size() - 1; ++i) {
    output_vecs[i] = GetNormalFromTwoPoints(ccw_path[i - 1], ccw_path[i + 1]);
  }

  // Reverse normal direction
  if (!outward) {
    for (size_t i = 0; i < ccw_path.size(); ++i) {
      output_vecs[i] = -output_vecs[i];
    }
  }
  return output_vecs;
}
Ejemplo n.º 4
0
void Shape2D::add_ellipse(const Pointf &center, const Pointf &radius, bool reverse)
{
	float offset_x = 0;
	float offset_y = 0;

	int max_radius = max(radius.x, radius.y);

	int rotationcount = max(5, (max_radius - 3));
	float halfpi = 1.5707963267948966192313216916398f;
	float turn = halfpi / rotationcount;

	offset_x = center.x;
	offset_y = -center.y;

	Path2D path;

	rotationcount *= 4;

	std::vector<Pointf> points;
	points.resize(rotationcount);

	for(int i = 0; i < rotationcount ; i++)
	{
		float pos1 = radius.x * cos(i * turn);
		float pos2 = radius.y * sin(i * turn);

		points[i].x = (center.x + pos1);
		points[i].y = (center.y + pos2);
	}

	path.add_line_to(points);

	if (reverse)
		path.reverse();

	add_path(path);
}
Ejemplo n.º 5
0
Path2D Path2D::circle( CGFloat r, const CGPoint &i_center )
{
	Path2D p;
	r = std::abs( r );
	CGFloat c = r * 0.551915024494;
	p.move_to( i_center + CGPoint{ r, 0 } );
	p.curve_to( i_center + CGPoint{ r, c }, i_center + CGPoint{ c, r }, i_center + CGPoint{ 0, r } );
	p.curve_to( i_center + CGPoint{ -c, r }, i_center + CGPoint{ -r, c }, i_center + CGPoint{ -r, 0 } );
	p.curve_to( i_center + CGPoint{ -r, -c }, i_center + CGPoint{ -c, -r }, i_center + CGPoint{ 0, -r } );
	p.curve_to( i_center + CGPoint{ c, -r }, i_center + CGPoint{ r, -c }, i_center + CGPoint{ r, 0 } );
	p.close();
	return p;
}
Ejemplo n.º 6
0
void Shape2D_Impl::add_rotated_curve(Path2D &path, const Pointf &center, const Angle &angle, Pointf point_1,  Pointf point_2,  Pointf point_3)
{
	if (angle.to_radians() != 0.0f)
	{
		point_1.rotate(center, angle);
		point_2.rotate(center, angle);
		point_3.rotate(center, angle);
	}
	BezierCurve curve;
	curve.add_control_point(point_1);
	curve.add_control_point(point_2);
	curve.add_control_point(point_3);
	path.add_curve(curve);

}
        vector<double> GeometricRecognizer::vectorize(Path2D points) // for Protractor
        {
                double sum = 0.0;
                vector<double> vectorized;

                // Preprocessing, Move from .x.y notation to 1D vector notation
                // points[i](.x,.y) => vectorized(i, i+1, ...)
                for (unsigned int i = 0; i < points.size(); i++)
                {
                    vectorized.push_back(points[i].x);
                    vectorized.push_back(points[i].y);
                    sum += points[i].x * points[i].x + points[i].y * points[i].y;
                }
                // normalize values : dividing by magnitude
                // magnitude = sqrt ( sum_i(x²) + sum_i(y²) )
                double magnitude = sqrt(sum);
                for (unsigned int i = 0; i < vectorized.size(); i++)
                        vectorized[i] /= magnitude;
                return vectorized;
        }
Ejemplo n.º 8
0
std::vector<Vector2f> SimplifyPolyline(const Path2D& path, float rel_tol) {
  if (path.size() <= 2) {
    return path;
  }

  std::vector<Vector2f> out;
  if (true) {
    // we compute the boundary square size of the path
    AABB bound = GetAABBWithPadding(path, 0);
    Vector2f span = bound.upper_bound - bound.lower_bound;
    // set a tolerance to remove points that are too close to
    // each other. the relative tolerance is 0.5% of max size
    // so the simplified curve is still pretty smooth
    float tol = std::max(span(0), span(1)) * rel_tol;
    out = PolylineDouglasPeuckerIterative(path, tol);
  } else {
    // only one method implemented
    // the douglas_peucker method may change the topology of input curves
    assert(0);
  }
  return out;
}
Ejemplo n.º 9
0
Shape2D FontEngine_Freetype::load_glyph_outline(int c, int &out_advance_x)
{
	out_advance_x = 0;

	FT_UInt glyph_index;

	glyph_index = FT_Get_Char_Index( face, FT_ULong(c) );

	FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
	if ( error )
	{
		throw Exception("freetype: error loading glyph");
	}

	FT_Glyph glyph;

	error = FT_Get_Glyph( face->glyph, &glyph );

	if ( error )
	{
		throw Exception("freetype: error getting glyph");
	}

	FT_OutlineGlyph ft_outline_glyph_rec = (FT_OutlineGlyph)glyph;
	FT_Outline ft_outline = ft_outline_glyph_rec->outline;

	Shape2D outline;

//	cl_write_console_line(string_format("Num contours: %1", ft_outline.n_contours));

	for( int cont = 0; cont < ft_outline.n_contours; cont++ )
	{
//		cl_write_console_line(string_format("Num points in contour %1: %2", cont, ft_outline.contours[0]+1));

		Path2D contour;

		// debug: dump contents of points array to terminal
//		for( int i = 0; i <= ft_outline.contours[cont]; ++i )
//		{
//			FT_Vector pos = ft_outline.points[i];
//			cl_write_console_line(string_format("dump points[%1]: (%2,%3) \t type: %4", i, pos.x, pos.y, ft_outline.tags[i]));
//		}

		std::vector<TaggedPoint> points = get_contour_points(cont, &ft_outline);
		points.push_back(points.front()); // just to simplify, it's removed later.

		for( unsigned int i = 0; i < points.size()-1; i++ )
		{
			TaggedPoint &tp = points[i];

			if( tp.tag == FT_Curve_Tag_On )
			{
				contour.add_line_to(tp.pos);
			}
			else if( tp.tag == FT_Curve_Tag_Conic )
			{
				// TODO: i - 1 is safe here because we made sure the contour will start with a Tag_On.
				BezierCurve curve;
				curve.add_control_point( points[i-1].pos);
				curve.add_control_point( tp.pos );
				curve.add_control_point( points[i+1].pos );
				contour.add_curve(curve);
			}
			else if( tp.tag == FT_Curve_Tag_Cubic && points[i-1].tag == FT_Curve_Tag_Cubic )
			{
				BezierCurve curve;
				curve.add_control_point( points[i-2].pos);
				curve.add_control_point( points[i-1].pos);
				curve.add_control_point( tp.pos );
				curve.add_control_point( points[i+1].pos );
				contour.add_curve(curve);
			}
		}

		outline.add_path(contour);
	}

	FT_Done_Glyph(glyph);

	out_advance_x = get_advance_x( c );

	return outline;
}
	Path2D GeometricRecognizer::resample(Path2D points)
	{
        double interval = pathLength(points) / (numPointsInGesture - 1); // interval length
        double D = 0.0;
        Path2D newPoints;
        if (!points.empty()){
            //--- Store first point since we'll never resample it out of existence
            newPoints.push_back(points.front());
            for(int i = 1; i < (int)points.size(); i++)
            {
                Point2D currentPoint  = points[i];
                Point2D previousPoint = points[i-1];
                double d = getDistance(previousPoint, currentPoint);
                if ((D + d) >= interval)
                {
                    double qx = previousPoint.x + ((interval - D) / d) * (currentPoint.x - previousPoint.x);
                    double qy = previousPoint.y + ((interval - D) / d) * (currentPoint.y - previousPoint.y);
                    Point2D point(qx, qy);
                    newPoints.push_back(point);
                    points.insert(points.begin() + i, point);
                    D = 0.0;
                }
                else D += d;
            }
            
            // somtimes we fall a rounding-error short of adding the last point, so add it if so
            if (newPoints.size() == (numPointsInGesture - 1))
            {
                newPoints.push_back(points.back());
            }
        }
		return newPoints;
	}