|
|
|
@ -21,8 +21,10 @@ |
|
|
|
* or you may write to the Free Software Foundation, Inc., |
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|
|
|
*/ |
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "kbool/booleng.h"
|
|
|
|
// For some unknown reasons, polygon.hpp shoul be included first
|
|
|
|
#include "boost/polygon/polygon.hpp"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
@ -34,13 +36,24 @@ |
|
|
|
#include "potracelib.h"
|
|
|
|
#include "auxiliary.h"
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef max
|
|
|
|
#define max( a, b ) ( ( (a) > (b) ) ? (a) : (b) )
|
|
|
|
#endif
|
|
|
|
#ifndef min
|
|
|
|
#endif
|
|
|
|
#ifndef min
|
|
|
|
#define min( a, b ) ( ( (a) < (b) ) ? (a) : (b) )
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Define some types used here from boost::polygon
|
|
|
|
namespace bpl = boost::polygon; // bpl = boost polygon library
|
|
|
|
using namespace bpl::operators; // +, -, =, ...
|
|
|
|
|
|
|
|
typedef int coordinate_type; |
|
|
|
|
|
|
|
typedef bpl::polygon_data<coordinate_type> KPolygon; // define a basic polygon
|
|
|
|
typedef std::vector<KPolygon> KPolygonSet; // define a set of polygons
|
|
|
|
|
|
|
|
typedef bpl::point_data<coordinate_type> KPolyPoint; // define a corner of a polygon
|
|
|
|
|
|
|
|
enum output_format { |
|
|
|
POSTSCRIPT_FMT = 1, |
|
|
|
@ -48,11 +61,13 @@ enum output_format { |
|
|
|
EESCHEMA_FMT |
|
|
|
}; |
|
|
|
/* free a potrace bitmap */ |
|
|
|
static void bm_free(potrace_bitmap_t *bm) { |
|
|
|
if (bm != NULL) { |
|
|
|
free(bm->map); |
|
|
|
} |
|
|
|
free(bm); |
|
|
|
static void bm_free( potrace_bitmap_t* bm ) |
|
|
|
{ |
|
|
|
if( bm != NULL ) |
|
|
|
{ |
|
|
|
free( bm->map ); |
|
|
|
} |
|
|
|
free( bm ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -69,8 +84,7 @@ public: |
|
|
|
double m_ScaleY; // the conversion scale
|
|
|
|
potrace_path_t* m_Paths; // the list of paths, from potrace (list of lines and bezier curves)
|
|
|
|
FILE* m_Outfile; |
|
|
|
public: |
|
|
|
BITMAPCONV_INFO(); |
|
|
|
public: BITMAPCONV_INFO(); |
|
|
|
}; |
|
|
|
|
|
|
|
static void BezierToPolyline( std::vector <potrace_dpoint_t>& aCornersBuffer, |
|
|
|
@ -96,105 +110,10 @@ BITMAPCONV_INFO::BITMAPCONV_INFO() |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function ArmBoolEng |
|
|
|
* Initialise parameters used in kbool |
|
|
|
* @param aBooleng = pointer to the Bool_Engine to initialise |
|
|
|
* @param aConvertHoles = mode for holes when a boolean operation is made |
|
|
|
* true: in resulting polygon, holes are linked into outer contours by double overlapping segments |
|
|
|
* false: in resulting polygons, holes are not linked: they are separate polygons |
|
|
|
*/ |
|
|
|
void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) |
|
|
|
int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFormat ) |
|
|
|
{ |
|
|
|
// set some global vals to arm the boolean engine
|
|
|
|
|
|
|
|
// input points are scaled up with GetDGrid() * GetGrid()
|
|
|
|
|
|
|
|
// DGRID is only meant to make fractional parts of input data which
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The input data scaled up with DGrid is related to the accuracy the user has in his input data. |
|
|
|
* User data with a minimum accuracy of 0.001, means set the DGrid to 1000. |
|
|
|
* The input data may contain data with a minimum accuracy much smaller, but by setting the DGrid |
|
|
|
* everything smaller than 1/DGrid is rounded. |
|
|
|
* |
|
|
|
* DGRID is only meant to make fractional parts of input data which can be |
|
|
|
* doubles, part of the integers used in vertexes within the boolean algorithm. |
|
|
|
* And therefore DGRID bigger than 1 is not usefull, you would only loose accuracy. |
|
|
|
* Within the algorithm all input data is multiplied with DGRID, and the result |
|
|
|
* is rounded to an integer. |
|
|
|
*/ |
|
|
|
double DGRID = 1000.0; // round coordinate X or Y value in calculations to this (initial value = 1000.0 in kbool example)
|
|
|
|
// kbool uses DGRID to convert float user units to integer
|
|
|
|
// kbool unit = (int)(user unit * DGRID)
|
|
|
|
// Note: in kicad, coordinates are already integer so DGRID could be set to 1
|
|
|
|
// we can choose 1.0,
|
|
|
|
// but choose DGRID = 1000.0 solves some filling problems
|
|
|
|
// (perhaps because this allows a better precision in kbool internal calculations
|
|
|
|
|
|
|
|
double MARGE = 1.0 / DGRID; // snap with in this range points to lines in the intersection routines
|
|
|
|
// should always be >= 1/DGRID a MARGE >= 10/DGRID is ok
|
|
|
|
// this is also used to remove small segments and to decide when
|
|
|
|
// two segments are in line. ( initial value = 0.001 )
|
|
|
|
// For kicad we choose MARGE = 1/DGRID
|
|
|
|
|
|
|
|
double CORRECTIONFACTOR = 0.0; // correct the polygons by this number: used in BOOL_CORRECTION operation
|
|
|
|
// this operation shrinks a polygon if CORRECTIONFACTOR < 0
|
|
|
|
// or stretch it if CORRECTIONFACTOR > 0
|
|
|
|
// the size change is CORRECTIONFACTOR (holes are correctly handled)
|
|
|
|
double CORRECTIONABER = 1.0; // the accuracy for the rounded shapes used in correction
|
|
|
|
double ROUNDFACTOR = 1.5; // when will we round the correction shape to a circle
|
|
|
|
double SMOOTHABER = 10.0; // accuracy when smoothing a polygon
|
|
|
|
double MAXLINEMERGE = 1000.0; // leave as is, segments of this length in smoothen
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Grid makes sure that the integer data used within the algorithm has room for extra intersections |
|
|
|
* smaller than the smallest number within the input data. |
|
|
|
* The input data scaled up with DGrid is related to the accuracy the user has in his input data. |
|
|
|
* Another scaling with Grid is applied on top of it to create space in the integer number for |
|
|
|
* even smaller numbers. |
|
|
|
*/ |
|
|
|
int GRID = (int) ( 10000 / DGRID ); // initial value = 10000 in kbool example
|
|
|
|
|
|
|
|
// But we use 10000/DGRID because the scalling is made
|
|
|
|
// by DGRID on integer pcbnew units and
|
|
|
|
// the global scalling ( GRID*DGRID) must be < 30000 to avoid
|
|
|
|
// overflow in calculations (made in long long in kbool)
|
|
|
|
if( GRID <= 1 ) // Cannot be null!
|
|
|
|
GRID = 1; |
|
|
|
|
|
|
|
aBooleng->SetMarge( MARGE ); |
|
|
|
aBooleng->SetGrid( GRID ); |
|
|
|
aBooleng->SetDGrid( DGRID ); |
|
|
|
aBooleng->SetCorrectionFactor( CORRECTIONFACTOR ); |
|
|
|
aBooleng->SetCorrectionAber( CORRECTIONABER ); |
|
|
|
aBooleng->SetSmoothAber( SMOOTHABER ); |
|
|
|
aBooleng->SetMaxlinemerge( MAXLINEMERGE ); |
|
|
|
aBooleng->SetRoundfactor( ROUNDFACTOR ); |
|
|
|
aBooleng->SetWindingRule( true ); // This is the default kbool value
|
|
|
|
|
|
|
|
if( aConvertHoles ) |
|
|
|
{ |
|
|
|
#if 1 // Can be set to 1 for kbool version >= 2.1, must be set to 0 for previous versions
|
|
|
|
// SetAllowNonTopHoleLinking() exists only in kbool >= 2.1
|
|
|
|
aBooleng->SetAllowNonTopHoleLinking( false ); // Default = , but i have problems (filling errors) when true
|
|
|
|
#endif
|
|
|
|
aBooleng->SetLinkHoles( true ); // holes will be connected by double overlapping segments
|
|
|
|
aBooleng->SetOrientationEntryMode( false ); // all polygons are contours, not holes
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
aBooleng->SetLinkHoles( false ); // holes will not be connected by double overlapping segments
|
|
|
|
aBooleng->SetOrientationEntryMode( true ); // holes are entered counter clockwise
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE * aOutfile, int aFormat ) |
|
|
|
{ |
|
|
|
potrace_param_t* param; |
|
|
|
potrace_state_t* st; |
|
|
|
potrace_param_t* param; |
|
|
|
potrace_state_t* st; |
|
|
|
|
|
|
|
|
|
|
|
/* set tracing parameters, starting from defaults */ |
|
|
|
@ -232,19 +151,19 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE * aOutfile, int aF |
|
|
|
case 1: |
|
|
|
info.m_Format = EESCHEMA_FMT; |
|
|
|
info.m_ScaleX = 1000.0 / 300; // the conversion scale
|
|
|
|
info.m_ScaleY = - info.m_ScaleX; // Y axis is bottom to Top for components in libs
|
|
|
|
info.m_ScaleY = -info.m_ScaleX; // Y axis is bottom to Top for components in libs
|
|
|
|
CreateOutputFile( info ); |
|
|
|
break; |
|
|
|
|
|
|
|
case 0: |
|
|
|
info.m_Format = PCBNEW_FMT; |
|
|
|
info.m_ScaleX = 10000.0 / 300; // the conversion scale
|
|
|
|
info.m_ScaleY = info.m_ScaleX; // Y axis is top to bottom in modedit
|
|
|
|
info.m_ScaleX = 10000.0 / 300; // the conversion scale
|
|
|
|
info.m_ScaleY = info.m_ScaleX; // Y axis is top to bottom in modedit
|
|
|
|
CreateOutputFile( info ); |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -282,12 +201,12 @@ static void OuputHeader( BITMAPCONV_INFO& aInfo ) |
|
|
|
fprintf( aInfo.m_Outfile, "# pixmap w = %d, h = %d\n#\n", |
|
|
|
aInfo.m_PixmapWidth, aInfo.m_PixmapHeight ); |
|
|
|
fprintf( aInfo.m_Outfile, "$MODULE %s\n", CmpName ); |
|
|
|
fprintf( aInfo.m_Outfile, "Po 0 0 0 15 00000000 00000000 ~~\n"); |
|
|
|
fprintf( aInfo.m_Outfile, "Po 0 0 0 15 00000000 00000000 ~~\n" ); |
|
|
|
fprintf( aInfo.m_Outfile, "Li %s\n", CmpName ); |
|
|
|
fprintf( aInfo.m_Outfile, "T0 0 %d %d %d 0 %d N I %d \"G***\"\n", |
|
|
|
Ypos, fieldSize, fieldSize, fieldSize/5, FIELD_LAYER ); |
|
|
|
Ypos, fieldSize, fieldSize, fieldSize / 5, FIELD_LAYER ); |
|
|
|
fprintf( aInfo.m_Outfile, "T1 0 %d %d %d 0 %d N I %d \"%s\"\n", |
|
|
|
-Ypos, fieldSize, fieldSize, fieldSize/5, FIELD_LAYER, CmpName ); |
|
|
|
-Ypos, fieldSize, fieldSize, fieldSize / 5, FIELD_LAYER, CmpName ); |
|
|
|
break; |
|
|
|
|
|
|
|
case EESCHEMA_FMT: |
|
|
|
@ -329,25 +248,32 @@ static void OuputEnd( BITMAPCONV_INFO& aInfo ) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void OuputOnePolygon( BITMAPCONV_INFO& aInfo, |
|
|
|
std::vector <potrace_dpoint_t>& aPolygonBuffer ) |
|
|
|
/**
|
|
|
|
* Function OuputOnePolygon |
|
|
|
* write one polygon to output file. |
|
|
|
* Polygon coordinates are expected scaled by the polugon extraction function |
|
|
|
*/ |
|
|
|
static void OuputOnePolygon( BITMAPCONV_INFO& aInfo, KPolygon & aPolygon ) |
|
|
|
{ |
|
|
|
unsigned ii; |
|
|
|
KPolyPoint currpoint; |
|
|
|
|
|
|
|
double offsetX = aInfo.m_PixmapWidth / 2 * aInfo.m_ScaleX; |
|
|
|
double offsetY = aInfo.m_PixmapHeight / 2 * aInfo.m_ScaleY; |
|
|
|
int offsetX = (int)( aInfo.m_PixmapWidth / 2 * aInfo.m_ScaleX ); |
|
|
|
int offsetY = (int)( aInfo.m_PixmapHeight / 2 * aInfo.m_ScaleY ); |
|
|
|
|
|
|
|
KPolyPoint startpoint = *aPolygon.begin(); |
|
|
|
|
|
|
|
switch( aInfo.m_Format ) |
|
|
|
{ |
|
|
|
case POSTSCRIPT_FMT: |
|
|
|
fprintf( aInfo.m_Outfile, "%f %f moveto\n", |
|
|
|
aPolygonBuffer[0].x * aInfo.m_ScaleX, |
|
|
|
aPolygonBuffer[0].y * aInfo.m_ScaleY ); |
|
|
|
for( ii = 1; ii < aPolygonBuffer.size(); ii++ ) |
|
|
|
fprintf( aInfo.m_Outfile, "%f %f lineto\n", |
|
|
|
aPolygonBuffer[ii].x * aInfo.m_ScaleX, |
|
|
|
aPolygonBuffer[ii].y * aInfo.m_ScaleY ); |
|
|
|
fprintf( aInfo.m_Outfile, "%d %d moveto\n", |
|
|
|
startpoint.x(), startpoint.y() ); |
|
|
|
for( ii = 1; ii < aPolygon.size(); ii++ ) |
|
|
|
{ |
|
|
|
currpoint = *(aPolygon.begin() + ii); |
|
|
|
fprintf( aInfo.m_Outfile, "%d %d lineto\n", |
|
|
|
currpoint.x(), currpoint.y() ); |
|
|
|
} |
|
|
|
|
|
|
|
fprintf( aInfo.m_Outfile, "0 setgray fill\n" ); |
|
|
|
break; |
|
|
|
@ -358,31 +284,34 @@ static void OuputOnePolygon( BITMAPCONV_INFO& aInfo, |
|
|
|
int layer = SILKSCREEN_N_FRONT; |
|
|
|
int width = 1; |
|
|
|
fprintf( aInfo.m_Outfile, "DP %d %d %d %d %d %d %d\n", |
|
|
|
0, 0, 0, 0, |
|
|
|
int(aPolygonBuffer.size()+1), |
|
|
|
width, layer ); |
|
|
|
0, 0, 0, 0, |
|
|
|
aPolygon.size() + 1, width, layer ); |
|
|
|
|
|
|
|
for( ii = 0; ii < aPolygonBuffer.size(); ii++ ) |
|
|
|
for( ii = 0; ii < aPolygon.size(); ii++ ) |
|
|
|
{ |
|
|
|
currpoint = *( aPolygon.begin() + ii ); |
|
|
|
fprintf( aInfo.m_Outfile, "Dl %d %d\n", |
|
|
|
(int) ( aPolygonBuffer[ii].x * aInfo.m_ScaleX - offsetX ), |
|
|
|
(int) ( aPolygonBuffer[ii].y * aInfo.m_ScaleY - offsetY ) ); |
|
|
|
currpoint.x() - offsetX, currpoint.y() - offsetY ); |
|
|
|
} |
|
|
|
|
|
|
|
// Close polygon
|
|
|
|
fprintf( aInfo.m_Outfile, "Dl %d %d\n", |
|
|
|
(int) ( aPolygonBuffer[0].x * aInfo.m_ScaleX - offsetX ), |
|
|
|
(int) ( aPolygonBuffer[0].y * aInfo.m_ScaleY - offsetY ) ); |
|
|
|
startpoint.x() - offsetX, startpoint.y() - offsetY ); |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case EESCHEMA_FMT: |
|
|
|
fprintf( aInfo.m_Outfile, "P %d 0 0 1", int(aPolygonBuffer.size()+1) ); |
|
|
|
for( ii = 0; ii < aPolygonBuffer.size(); ii++ ) |
|
|
|
fprintf( aInfo.m_Outfile, "P %d 0 0 1", aPolygon.size() + 1 ); |
|
|
|
for( ii = 0; ii < aPolygon.size(); ii++ ) |
|
|
|
{ |
|
|
|
currpoint = *(aPolygon.begin() + ii); |
|
|
|
fprintf( aInfo.m_Outfile, " %d %d", |
|
|
|
(int) ( aPolygonBuffer[ii].x * aInfo.m_ScaleX - offsetX ), |
|
|
|
(int) ( aPolygonBuffer[ii].y * aInfo.m_ScaleY - offsetY ) ); |
|
|
|
// Close polygon
|
|
|
|
currpoint.x() - offsetX, currpoint.y() - offsetY ); |
|
|
|
} |
|
|
|
|
|
|
|
// Close polygon
|
|
|
|
fprintf( aInfo.m_Outfile, " %d %d", |
|
|
|
(int) ( aPolygonBuffer[0].x * aInfo.m_ScaleX - offsetX ), |
|
|
|
(int) ( aPolygonBuffer[0].y * aInfo.m_ScaleY - offsetY ) ); |
|
|
|
startpoint.x() - offsetX, startpoint.y() - offsetY ); |
|
|
|
|
|
|
|
fprintf( aInfo.m_Outfile, " F\n" ); |
|
|
|
break; |
|
|
|
@ -392,16 +321,21 @@ static void OuputOnePolygon( BITMAPCONV_INFO& aInfo, |
|
|
|
|
|
|
|
static void CreateOutputFile( BITMAPCONV_INFO& aInfo ) |
|
|
|
{ |
|
|
|
unsigned int i, n; |
|
|
|
int* tag; |
|
|
|
KPolyPoint currpoint; |
|
|
|
|
|
|
|
std::vector <potrace_dpoint_t> cornersBuffer; |
|
|
|
|
|
|
|
// This KPolygonSet polyset_areas is a complex polygon to draw
|
|
|
|
// and can be complex depending on holes inside this polygon
|
|
|
|
KPolygonSet polyset_areas; |
|
|
|
|
|
|
|
// This KPolygonSet polyset_holes is the set of holes inside polyset_areas
|
|
|
|
KPolygonSet polyset_holes; |
|
|
|
|
|
|
|
potrace_dpoint_t( *c )[3]; |
|
|
|
OuputHeader( aInfo ); |
|
|
|
|
|
|
|
bool main_outline = true; |
|
|
|
Bool_Engine* booleng = NULL; |
|
|
|
bool main_outline = true; |
|
|
|
|
|
|
|
/* draw each as a polygon with no hole.
|
|
|
|
* Bezier curves are approximated by a polyline |
|
|
|
@ -409,17 +343,11 @@ static void CreateOutputFile( BITMAPCONV_INFO& aInfo ) |
|
|
|
potrace_path_t* paths = aInfo.m_Paths; // the list of paths
|
|
|
|
while( paths != NULL ) |
|
|
|
{ |
|
|
|
n = paths->curve.n; |
|
|
|
tag = paths->curve.tag; |
|
|
|
c = paths->curve.c; |
|
|
|
potrace_dpoint_t startpoint = c[n - 1][2]; |
|
|
|
cornersBuffer.push_back( startpoint ); |
|
|
|
if( booleng == NULL ) |
|
|
|
{ |
|
|
|
booleng = new Bool_Engine(); |
|
|
|
ArmBoolEng( booleng, true ); |
|
|
|
} |
|
|
|
for( i = 0; i < n; i++ ) |
|
|
|
int cnt = paths->curve.n; |
|
|
|
int* tag = paths->curve.tag; |
|
|
|
c = paths->curve.c; |
|
|
|
potrace_dpoint_t startpoint = c[cnt - 1][2]; |
|
|
|
for( int i = 0; i < cnt; i++ ) |
|
|
|
{ |
|
|
|
switch( tag[i] ) |
|
|
|
{ |
|
|
|
@ -440,46 +368,53 @@ static void CreateOutputFile( BITMAPCONV_INFO& aInfo ) |
|
|
|
if( main_outline ) |
|
|
|
{ |
|
|
|
main_outline = false; |
|
|
|
booleng->StartPolygonAdd( GROUP_A ); |
|
|
|
for( i = 1; i < cornersBuffer.size(); i++ ) |
|
|
|
booleng->AddPoint( cornersBuffer[i].x, cornersBuffer[i].y ); |
|
|
|
|
|
|
|
booleng->EndPolygonAdd(); |
|
|
|
// build the current main polygon
|
|
|
|
std::vector<KPolyPoint> cornerslist; // a simple boost polygon
|
|
|
|
for( unsigned int i = 0; i < cornersBuffer.size(); i++ ) |
|
|
|
{ |
|
|
|
currpoint.x( (coordinate_type) (cornersBuffer[i].x * aInfo.m_ScaleX) ); |
|
|
|
currpoint.y( (coordinate_type) (cornersBuffer[i].y * aInfo.m_ScaleY) ); |
|
|
|
cornerslist.push_back( currpoint ); |
|
|
|
} |
|
|
|
|
|
|
|
KPolygon poly; |
|
|
|
bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); |
|
|
|
polyset_areas.push_back( poly ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
booleng->StartPolygonAdd( GROUP_B ); |
|
|
|
for( i = 1; i < cornersBuffer.size(); i++ ) |
|
|
|
booleng->AddPoint( cornersBuffer[i].x, cornersBuffer[i].y ); |
|
|
|
// Add current hole in polyset_holes
|
|
|
|
std::vector<KPolyPoint> cornerslist; // a simple boost polygon
|
|
|
|
for( unsigned int i = 0; i < cornersBuffer.size(); i++ ) |
|
|
|
{ |
|
|
|
currpoint.x( (coordinate_type) (cornersBuffer[i].x * aInfo.m_ScaleX) ); |
|
|
|
currpoint.y( (coordinate_type) (cornersBuffer[i].y * aInfo.m_ScaleY) ); |
|
|
|
cornerslist.push_back( currpoint ); |
|
|
|
} |
|
|
|
|
|
|
|
booleng->EndPolygonAdd(); |
|
|
|
KPolygon poly; |
|
|
|
bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); |
|
|
|
polyset_holes.push_back( poly ); |
|
|
|
} |
|
|
|
cornersBuffer.clear(); |
|
|
|
|
|
|
|
/* at the end of a group of a positive path and its negative
|
|
|
|
* children, fill. */ |
|
|
|
/* at the end of a group of a positive path and its negative children, fill.
|
|
|
|
*/ |
|
|
|
if( paths->next == NULL || paths->next->sign == '+' ) |
|
|
|
{ |
|
|
|
booleng->Do_Operation( BOOL_A_SUB_B ); |
|
|
|
std::vector <potrace_dpoint_t> PolygonBuffer; |
|
|
|
while( booleng->StartPolygonGet() ) |
|
|
|
// Substract holes to main polygon:
|
|
|
|
polyset_areas -= polyset_holes; |
|
|
|
|
|
|
|
// Output current resulting polygon(s)
|
|
|
|
for( unsigned ii = 0; ii < polyset_areas.size(); ii++ ) |
|
|
|
{ |
|
|
|
potrace_dpoint_t corner; |
|
|
|
PolygonBuffer.clear(); |
|
|
|
while( booleng->PolygonHasMorePoints() ) |
|
|
|
{ |
|
|
|
corner.x = booleng->GetPolygonXPoint(); |
|
|
|
corner.y = booleng->GetPolygonYPoint(); |
|
|
|
PolygonBuffer.push_back( corner ); |
|
|
|
} |
|
|
|
|
|
|
|
booleng->EndPolygonGet(); |
|
|
|
OuputOnePolygon( aInfo, PolygonBuffer ); |
|
|
|
PolygonBuffer.clear(); |
|
|
|
KPolygon& poly = polyset_areas[ii]; |
|
|
|
OuputOnePolygon( aInfo, poly ); |
|
|
|
} |
|
|
|
|
|
|
|
delete booleng; |
|
|
|
booleng = NULL; |
|
|
|
polyset_areas.clear(); |
|
|
|
polyset_holes.clear(); |
|
|
|
main_outline = true; |
|
|
|
} |
|
|
|
paths = paths->next; |
|
|
|
@ -505,7 +440,7 @@ void BezierToPolyline( std::vector <potrace_dpoint_t>& aCornersBuffer, |
|
|
|
* between the true curve and its approximation does not exceed the |
|
|
|
* desired accuracy delta. */ |
|
|
|
|
|
|
|
delta = 0.5; /* desired accuracy, in pixels */ |
|
|
|
delta = 0.25; /* desired accuracy, in pixels */ |
|
|
|
|
|
|
|
/* let dd = maximal value of 2nd derivative over curve - this must
|
|
|
|
* occur at an endpoint. */ |
|
|
|
@ -521,7 +456,7 @@ void BezierToPolyline( std::vector <potrace_dpoint_t>& aCornersBuffer, |
|
|
|
intermediate_point.x = p1.x * cu( 1 - t ) + |
|
|
|
3* p2.x* sq( 1 - t ) * t + |
|
|
|
3 * p3.x * (1 - t) * sq( t ) + |
|
|
|
p4.x* cu( t ); |
|
|
|
p4.x* cu( t ); |
|
|
|
|
|
|
|
intermediate_point.y = p1.y * cu( 1 - t ) + |
|
|
|
3* p2.y* sq( 1 - t ) * t + |
|
|
|
|