pathoutlineprovider.cpp revision 0ea208a87449db21773e592202c9320c92655813
#include "pathoutlineprovider.h"
namespace Geom
{
/**
* Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
From MathWorld--A Wolfram Web Resource.
*
* @return 0 if no intersection
* @return 1 if one circle is contained in the other
* @return 2 if intersections are found (they are written to p0 and p1)
*/
{
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
/* Determine the straight-line distance between the centers. */
double d = L2(D);
/* Check for solvability. */
{
/* no solution. circles do not intersect. */
return 0;
}
{
/* no solution. one circle is contained in the other */
return 1;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
/* Determine the coordinates of point 2. */
/* Determine the distance from point 2 to either of the
* intersection points.
*/
/* Now determine the offsets of the intersection points from
* point 2.
*/
/* Determine the absolute intersection points. */
return 2;
}
/**
* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
*/
{
}
}
double curv = k(t); // note that this value is signed
}
{
{
}
return out;
}
{
}
static boost::optional<Geom::Point> intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a,
{
}
}
}
namespace Outline
{
{
using namespace Geom;
//cast it
if (cbc) return 3;
if (qbc) return 2;
if (lbc) return 1;
return 0;
}
//returns true if the angle formed by the curves and their handles
//is >180 clockwise, otherwise false.
{
switch (order)
{
case 3:
break;
case 2:
break;
}
switch (order)
{
case 3:
break;
case 2:
break;
}
return false;
}
void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit)
{
{
//Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1);
if (solutions == 2)
{
{
// points[0] is bad, choose points[1]
}
// points[1] is bad, choose points[0]
}
else
{
// both points are good, choose nearest
}
Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true);
if (arc0)
{
delete arc0;
}
if (arc1)
{
delete arc1;
}
}
else
{
}
}
else
{
}
}
Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit)
{
unsigned m;
//load the first portion in before the loop starts
{
path_outline = Path();
//now half of first cusp has been loaded
path_tangent = Path();
//instead of array accessing twice, dereferencing used for clarity
path_outline = Path();
path_tangent = Path();
//always set pointers null after deleting
}
{
path_outline = Path();
}
return path_builder;
}
//Create a reflected outline join.
//Note: it is generally recommended to let half_outline do this for you!
//path_builder: the path to append the curves to
//cbc1: the curve before the join
//cbc2: the curve after the join
//endPt: the point to end at
//miter_limit: the miter parameter
void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit)
{
//the most important work for the reflected join is done here
//determine where we are in the path. If we're on the inside, ignore
//and just lineTo. On the outside, we'll do a little reflection magic :)
{
//probably on the outside of the corner
//reflect curves along the bevel
cbc1->finalPoint() );
cbc2->initialPoint() );
{
//std::cout << "Oops, no crossings!" << std::endl;
//curves didn't cross; default to miter
/*boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
cbc2->initialPoint(), tang2);
if (p)
{
path_builder.appendNew<Geom::LineSegment> (*p);
}*/
//bevel
}
else
{
//join
//@TODO joins have a strange tendency to cross themselves twice. Check this.
//sections commented out are for general stability
path_builder.appendNew <Geom::CubicBezier> (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] );
path_builder.appendNew <Geom::CubicBezier> (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt );
}
}
else // cross.empty()
{
//probably on the inside of the corner
}
}
/** @brief Converts a path to one half of an outline.
* path_in: The input path to use. (To create the other side use path_in.reverse() )
* line_width: the line width to use (usually you want to divide this by 2)
* linecap_type: (not used here) the cap to apply. Passed to libvarot.
* miter_limit: the miter parameter
*/
Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit)
{
unsigned m;
//needed for closing the path
//some issues prevented me from using a PathBuilder here
//it seems like PathBuilder::peek() gave me a null reference exception
//and I was unable to get a stack trace on Windows, so had to switch to Linux
//to see what the hell was wrong. :(
//I wasted five hours opening it in IDAPro, VS2012, and GDB Windows
/*Program received signal SIGSEGV, Segmentation fault.
0x00000000006539ac in get_curves (this=0x0)
at /usr/include/c++/4.6/bits/locale_facets.h:1077
1077 { return __c; }
*/
//load the first portion in before the loop starts
{
path_outline = Path();
//now half of first cusp has been loaded
path_tangent = Path();
//instead of array accessing twice, dereferencing used for clarity
path_outline = Path();
path_tangent = Path();
//always set pointers null after deleting
}
{
path_outline = Path();
}
return path_builder;
}
Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim)
{
{
}
{
{
{
miter_lim );
miter_lim );
//cap
if (butt == butt_straight) {
} else if (butt == butt_round) {
} else if (butt == butt_square) {
//don't know what to do
} else if (butt == butt_pointy) {
//don't know what to do
}
if (butt == butt_straight) {
} else if (butt == butt_round) {
} else if (butt == butt_square) {
//don't know what to do
} else if (butt == butt_pointy) {
//don't know what to do
//Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0);
//double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint());
}
}
else
{
//final join
//refer to half_outline for documentation
miter_lim );
miter_lim );
//this is a kludge, because I can't find how to make this work properly
if (lastIsLinear)
{
}
//outside test
{
//this is the outside path
//reuse the old one
}
else
{
//inside, carry on :-)
}
if (lastIsLinear)
{
}
{
//outside path
}
else
{
//inside
}
}
//pb.closePath();
//hack
{
}
}
else
{
//hack
delete pv_p;
}
}
return path_out;
}
Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim)
{
{
}
{
{
{
miter_lim );
miter_lim );
//cap
if (butt == butt_straight) {
} else if (butt == butt_round) {
} else if (butt == butt_square) {
//don't know what to do
} else if (butt == butt_pointy) {
//don't know what to do
}
if (butt == butt_straight) {
} else if (butt == butt_round) {
} else if (butt == butt_square) {
//don't know what to do
} else if (butt == butt_pointy) {
//don't know what to do
//Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0);
//double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint());
}
}
else
{
//final join
//refer to half_outline for documentation
miter_lim );
miter_lim );
//this is a kludge, because I can't find how to make this work properly
if (lastIsLinear)
{
}
//outside test
{
//this is the outside path
//reuse the old one
}
else
{
//inside, carry on :-)
}
if (lastIsLinear)
{
}
{
//outside path
}
else
{
//inside
}
}
//pb.closePath();
//hack
{
}
}
else
{
//hack
delete pv_p;
}
}
return path_out;
}
Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtType linecap_type,
{
{
return path_out;
}
{
}
//magic!
if (linejoin_type <= 2)
{
//fix memory leak
delete pv_p;
} else if (linejoin_type == 3) {
//reflected arc join
} else if (linejoin_type == 4) {
//extrapolated arc join
}
return path_out;
}
Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit)
{
path_outline.OutsideOutline(&path_tangent, line_width / 2, static_cast<join_typ>(linejoin_type), butt_straight, miter_lim);
delete pathvec;
return path_out;
}
else if (linejoin_type == LINEJOIN_REFLECTED) {
//reflected half outline
return path_out;
}
else if (linejoin_type == LINEJOIN_EXTRAPOLATED) {
return path_out;
}
return path_out;
}
} // namespace Outline
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :