Add a cache for TrueType contours and triangulation data.
Also returns minimumSegmentLength to its former value as it doesn't appear to be required to fix https://gitlab.com/kicad/code/kicad/-/issues/11463. Fixes: https://gitlab.com/kicad/code/kicad/-/issues/16568
This commit is contained in:
parent
fc66cb6805
commit
162e8962f7
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Ola Rinta-Koski <gitlab@rinta-koski.net>
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -122,10 +122,7 @@ void OUTLINE_GLYPH::Triangulate( std::function<void( const VECTOR2I& aPt1,
|
|||
const VECTOR2I& aPt2,
|
||||
const VECTOR2I& aPt3 )> aCallback ) const
|
||||
{
|
||||
// Only call CacheTriangulation if it has never been done before. Otherwise we'll hash
|
||||
// the triangulation to see if it has been edited, and glyphs after creation are read-only.
|
||||
if( TriangulatedPolyCount() == 0 )
|
||||
const_cast<OUTLINE_GLYPH*>( this )->CacheTriangulation( false );
|
||||
const_cast<OUTLINE_GLYPH*>( this )->CacheTriangulation( false );
|
||||
|
||||
for( unsigned int i = 0; i < TriangulatedPolyCount(); i++ )
|
||||
{
|
||||
|
@ -141,3 +138,30 @@ void OUTLINE_GLYPH::Triangulate( std::function<void( const VECTOR2I& aPt1,
|
|||
}
|
||||
|
||||
|
||||
void OUTLINE_GLYPH::CacheTriangulation( bool aPartition, bool aSimplify )
|
||||
{
|
||||
// Only call CacheTriangulation if it has never been done before. Otherwise we'll hash
|
||||
// the triangulation to see if it has been edited, and glyphs are invariant after creation.
|
||||
//
|
||||
// Also forces "partition" to false as we never want to partition a glyph.
|
||||
|
||||
if( TriangulatedPolyCount() == 0 )
|
||||
SHAPE_POLY_SET::CacheTriangulation( false, aSimplify );
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>> OUTLINE_GLYPH::GetTriangulationData() const
|
||||
{
|
||||
std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>> data;
|
||||
|
||||
for( const std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>& poly : m_triangulatedPolys )
|
||||
data.push_back( std::make_unique<SHAPE_POLY_SET::TRIANGULATED_POLYGON>( *poly ) );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void OUTLINE_GLYPH::CacheTriangulation( std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>>& aHintData )
|
||||
{
|
||||
cacheTriangulation( false, false, &aHintData );
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Ola Rinta-Koski <gitlab@rinta-koski.net>
|
||||
* Copyright (C) 2021 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Outline font class
|
||||
*
|
||||
|
@ -39,8 +39,8 @@ OUTLINE_DECOMPOSER::OUTLINE_DECOMPOSER( FT_Outline& aOutline ) :
|
|||
|
||||
static VECTOR2D toVector2D( const FT_Vector* aFreeTypeVector )
|
||||
{
|
||||
return VECTOR2D( aFreeTypeVector->x * GLYPH_SIZE_SCALER,
|
||||
aFreeTypeVector->y * GLYPH_SIZE_SCALER );
|
||||
return VECTOR2D( (double) aFreeTypeVector->x * GLYPH_SIZE_SCALER,
|
||||
(double) aFreeTypeVector->y * GLYPH_SIZE_SCALER );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Ola Rinta-Koski <gitlab@rinta-koski.net>
|
||||
* Copyright (C) 2021-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -255,6 +255,38 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
aOrigin, aTextStyle );
|
||||
}
|
||||
|
||||
|
||||
struct GLYPH_CACHE_KEY {
|
||||
FT_Face face;
|
||||
hb_codepoint_t codepoint;
|
||||
bool fakeItalic;
|
||||
bool fakeBold;
|
||||
bool mirror;
|
||||
EDA_ANGLE angle;
|
||||
|
||||
bool operator==(const GLYPH_CACHE_KEY& rhs ) const
|
||||
{
|
||||
return face == rhs.face && codepoint == rhs.codepoint
|
||||
&& fakeItalic == rhs.fakeItalic && fakeBold == rhs.fakeBold
|
||||
&& mirror == rhs.mirror && angle == rhs.angle;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<GLYPH_CACHE_KEY>
|
||||
{
|
||||
std::size_t operator()( const GLYPH_CACHE_KEY& k ) const
|
||||
{
|
||||
return hash<const void*>()( k.face ) ^ hash<unsigned>()( k.codepoint )
|
||||
^ hash<int>()( k.fakeItalic ) ^ hash<int>()( k.fakeBold )
|
||||
^ hash<int>()( k.mirror ) ^ hash<int>()( k.angle.AsTenthsOfADegree() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||
const wxString& aText, const VECTOR2I& aSize,
|
||||
|
@ -295,6 +327,10 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
|||
if( aGlyphs )
|
||||
aGlyphs->reserve( glyphCount );
|
||||
|
||||
// GLYPH_DATA is a collection of all outlines in the glyph; for example the 'o' glyph
|
||||
// generally contains 2 contours, one for the glyph outline and one for the hole
|
||||
static std::unordered_map<GLYPH_CACHE_KEY, GLYPH_DATA> s_glyphCache;
|
||||
|
||||
for( unsigned int i = 0; i < glyphCount; i++ )
|
||||
{
|
||||
// Don't process glyphs that were already included in a previous cluster
|
||||
|
@ -303,64 +339,67 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
|||
|
||||
if( aGlyphs )
|
||||
{
|
||||
if( m_fakeItal )
|
||||
GLYPH_CACHE_KEY key = { face, glyphInfo[i].codepoint, m_fakeItal, m_fakeBold,
|
||||
aMirror, aAngle };
|
||||
GLYPH_DATA& glyphData = s_glyphCache[ key ];
|
||||
|
||||
if( glyphData.m_Contours.empty() )
|
||||
{
|
||||
FT_Matrix matrix;
|
||||
// Create a 12 degree slant
|
||||
const float angle = (float)( -M_PI * 12.0f ) / 180.0f;
|
||||
matrix.xx = (FT_Fixed) ( cos( angle ) * 0x10000L );
|
||||
matrix.xy = (FT_Fixed) ( -sin( angle ) * 0x10000L );
|
||||
matrix.yx = (FT_Fixed) ( 0 * 0x10000L ); // Don't rotate in the y direction
|
||||
matrix.yy = (FT_Fixed) ( 1 * 0x10000L );
|
||||
if( m_fakeItal )
|
||||
{
|
||||
FT_Matrix matrix;
|
||||
// Create a 12 degree slant
|
||||
const float angle = (float)( -M_PI * 12.0f ) / 180.0f;
|
||||
matrix.xx = (FT_Fixed) ( cos( angle ) * 0x10000L );
|
||||
matrix.xy = (FT_Fixed) ( -sin( angle ) * 0x10000L );
|
||||
matrix.yx = (FT_Fixed) ( 0 * 0x10000L ); // Don't rotate in the y direction
|
||||
matrix.yy = (FT_Fixed) ( 1 * 0x10000L );
|
||||
|
||||
FT_Set_Transform( face, &matrix, 0 );
|
||||
}
|
||||
FT_Set_Transform( face, &matrix, nullptr );
|
||||
}
|
||||
|
||||
FT_Load_Glyph( face, glyphInfo[i].codepoint, FT_LOAD_NO_BITMAP );
|
||||
FT_Load_Glyph( face, glyphInfo[i].codepoint, FT_LOAD_NO_BITMAP );
|
||||
|
||||
if( m_fakeBold )
|
||||
FT_Outline_Embolden( &face->glyph->outline, 1 << 6 );
|
||||
if( m_fakeBold )
|
||||
FT_Outline_Embolden( &face->glyph->outline, 1 << 6 );
|
||||
|
||||
// contours is a collection of all outlines in the glyph; for example the 'o' glyph
|
||||
// generally contains 2 contours, one for the glyph outline and one for the hole
|
||||
std::vector<CONTOUR> contours;
|
||||
OUTLINE_DECOMPOSER decomposer( face->glyph->outline );
|
||||
|
||||
OUTLINE_DECOMPOSER decomposer( face->glyph->outline );
|
||||
if( !decomposer.OutlineToSegments( &glyphData.m_Contours ) )
|
||||
{
|
||||
double hb_advance = glyphPos[i].x_advance * GLYPH_SIZE_SCALER;
|
||||
BOX2D tofuBox( { scaler * 0.03, 0.0 },
|
||||
{ hb_advance - scaler * 0.02, scaler * 0.72 } );
|
||||
|
||||
if( !decomposer.OutlineToSegments( &contours ) )
|
||||
{
|
||||
double hb_advance = glyphPos[i].x_advance * GLYPH_SIZE_SCALER;
|
||||
BOX2D tofuBox( { scaler * 0.03, 0.0 },
|
||||
{ hb_advance - scaler * 0.02, scaler * 0.72 } );
|
||||
glyphData.m_Contours.clear();
|
||||
|
||||
contours.clear();
|
||||
CONTOUR outline;
|
||||
outline.m_Winding = 1;
|
||||
outline.m_Orientation = FT_ORIENTATION_TRUETYPE;
|
||||
outline.m_Points.push_back( tofuBox.GetPosition() );
|
||||
outline.m_Points.push_back( { tofuBox.GetSize().x, tofuBox.GetPosition().y } );
|
||||
outline.m_Points.push_back( tofuBox.GetSize() );
|
||||
outline.m_Points.push_back( { tofuBox.GetPosition().x, tofuBox.GetSize().y } );
|
||||
glyphData.m_Contours.push_back( outline );
|
||||
|
||||
CONTOUR outline;
|
||||
outline.m_Winding = 1;
|
||||
outline.m_Orientation = FT_ORIENTATION_TRUETYPE;
|
||||
outline.m_Points.push_back( tofuBox.GetPosition() );
|
||||
outline.m_Points.push_back( { tofuBox.GetSize().x, tofuBox.GetPosition().y } );
|
||||
outline.m_Points.push_back( tofuBox.GetSize() );
|
||||
outline.m_Points.push_back( { tofuBox.GetPosition().x, tofuBox.GetSize().y } );
|
||||
contours.push_back( outline );
|
||||
|
||||
CONTOUR hole;
|
||||
tofuBox.Move( { scaler * 0.06, scaler * 0.06 } );
|
||||
tofuBox.SetSize( { tofuBox.GetWidth() - scaler * 0.06,
|
||||
tofuBox.GetHeight() - scaler * 0.06 } );
|
||||
hole.m_Winding = 1;
|
||||
hole.m_Orientation = FT_ORIENTATION_NONE;
|
||||
hole.m_Points.push_back( tofuBox.GetPosition() );
|
||||
hole.m_Points.push_back( { tofuBox.GetSize().x, tofuBox.GetPosition().y } );
|
||||
hole.m_Points.push_back( tofuBox.GetSize() );
|
||||
hole.m_Points.push_back( { tofuBox.GetPosition().x, tofuBox.GetSize().y } );
|
||||
contours.push_back( hole );
|
||||
CONTOUR hole;
|
||||
tofuBox.Move( { scaler * 0.06, scaler * 0.06 } );
|
||||
tofuBox.SetSize( { tofuBox.GetWidth() - scaler * 0.06,
|
||||
tofuBox.GetHeight() - scaler * 0.06 } );
|
||||
hole.m_Winding = 1;
|
||||
hole.m_Orientation = FT_ORIENTATION_NONE;
|
||||
hole.m_Points.push_back( tofuBox.GetPosition() );
|
||||
hole.m_Points.push_back( { tofuBox.GetSize().x, tofuBox.GetPosition().y } );
|
||||
hole.m_Points.push_back( tofuBox.GetSize() );
|
||||
hole.m_Points.push_back( { tofuBox.GetPosition().x, tofuBox.GetSize().y } );
|
||||
glyphData.m_Contours.push_back( hole );
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>();
|
||||
std::vector<SHAPE_LINE_CHAIN> holes;
|
||||
|
||||
for( CONTOUR& c : contours )
|
||||
for( CONTOUR& c : glyphData.m_Contours )
|
||||
{
|
||||
std::vector<VECTOR2D> points = c.m_Points;
|
||||
SHAPE_LINE_CHAIN shape;
|
||||
|
@ -411,6 +450,16 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
|||
}
|
||||
}
|
||||
|
||||
if( glyphData.m_TriangulationData.empty() )
|
||||
{
|
||||
glyph->CacheTriangulation( false, false );
|
||||
glyphData.m_TriangulationData = glyph->GetTriangulationData();
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph->CacheTriangulation( glyphData.m_TriangulationData );
|
||||
}
|
||||
|
||||
aGlyphs->push_back( std::move( glyph ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -2891,30 +2891,9 @@ void OPENGL_GAL::DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>&
|
|||
}
|
||||
else if( allGlyphsAreOutline )
|
||||
{
|
||||
// Optimized path for stroke fonts that pre-reserves glyph triangles.
|
||||
// Optimized path for outline fonts that pre-reserves glyph triangles.
|
||||
int triangleCount = 0;
|
||||
|
||||
if( aGlyphs.size() > 0 )
|
||||
{
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
|
||||
tp.push_loop( aGlyphs.size(),
|
||||
[&]( const int a, const int b)
|
||||
{
|
||||
for( int ii = a; ii < b; ++ii )
|
||||
{
|
||||
auto glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( aGlyphs.at( ii ).get() );
|
||||
|
||||
// Only call CacheTriangulation() if it has never been done before.
|
||||
// Otherwise we'll hash the triangulation to see if it has been edited,
|
||||
// and all our glpyh editing ops update the triangulation anyway.
|
||||
if( glyph->TriangulatedPolyCount() == 0 )
|
||||
glyph->CacheTriangulation( false );
|
||||
}
|
||||
} );
|
||||
tp.wait_for_tasks();
|
||||
}
|
||||
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||
{
|
||||
const auto& outlineGlyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( *glyph );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Ola Rinta-Koski
|
||||
* Copyright (C) 2021-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -82,6 +82,20 @@ public:
|
|||
void Triangulate( std::function<void( const VECTOR2I& aPt1,
|
||||
const VECTOR2I& aPt2,
|
||||
const VECTOR2I& aPt3 )> aCallback ) const;
|
||||
|
||||
void CacheTriangulation( bool aPartition = true, bool aSimplify = false ) override;
|
||||
|
||||
/**
|
||||
* @return a set of triangulated polygons from the glyph. CacheTriangulation() will use this
|
||||
* data as hint data the next time around.
|
||||
*/
|
||||
std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>> GetTriangulationData() const;
|
||||
|
||||
/**
|
||||
* Cache the triangulation for the glyph from a known set of triangle indexes.
|
||||
* (See GetTriangulationData() above for more info.)
|
||||
*/
|
||||
void CacheTriangulation( std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>>& aHintData );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Ola Rinta-Koski
|
||||
* Copyright (C) 2021 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Outline font class
|
||||
*
|
||||
|
@ -48,6 +48,15 @@ struct CONTOUR
|
|||
FT_Orientation m_Orientation;
|
||||
};
|
||||
|
||||
struct GLYPH_DATA
|
||||
{
|
||||
std::vector<CONTOUR> m_Contours;
|
||||
|
||||
// Cache of the triangulation data. We'll use this as a hint for triangulating the actual
|
||||
// OUTLINE_GLYPHs.
|
||||
std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>> m_TriangulationData;
|
||||
};
|
||||
|
||||
|
||||
class OUTLINE_DECOMPOSER
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Modifications Copyright (C) 2018-2023 KiCad Developers
|
||||
* Modifications Copyright (C) 2018-2024 KiCad Developers
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -64,7 +64,8 @@ public:
|
|||
m_result( aResult )
|
||||
{};
|
||||
|
||||
bool TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly )
|
||||
bool TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly,
|
||||
SHAPE_POLY_SET::TRIANGULATED_POLYGON* aHintData )
|
||||
{
|
||||
m_bbox = aPoly.BBox();
|
||||
m_result.Clear();
|
||||
|
@ -82,9 +83,17 @@ public:
|
|||
|
||||
firstVertex->updateList();
|
||||
|
||||
auto retval = earcutList( firstVertex );
|
||||
m_vertices.clear();
|
||||
return retval;
|
||||
if( aHintData )
|
||||
{
|
||||
m_result.Triangles() = aHintData->Triangles();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto retval = earcutList( firstVertex );
|
||||
m_vertices.clear();
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2019 CERN
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
|
@ -517,7 +517,10 @@ public:
|
|||
* But not good for Gerbview (1e7 = 10cm), however using a partition is not useful.
|
||||
* @param aSimplify = force the algorithm to simplify the POLY_SET before triangulating
|
||||
*/
|
||||
void CacheTriangulation( bool aPartition = true, bool aSimplify = false );
|
||||
virtual void CacheTriangulation( bool aPartition = true, bool aSimplify = false )
|
||||
{
|
||||
cacheTriangulation( aPartition, aSimplify, nullptr );
|
||||
}
|
||||
bool IsTriangulationUpToDate() const;
|
||||
|
||||
MD5_HASH GetHash() const;
|
||||
|
@ -1428,6 +1431,10 @@ public:
|
|||
aBuffer.Append( *this );
|
||||
}
|
||||
|
||||
protected:
|
||||
void cacheTriangulation( bool aPartition, bool aSimplify,
|
||||
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>>* aHintData );
|
||||
|
||||
private:
|
||||
enum DROP_TRIANGULATION_FLAG { SINGLETON };
|
||||
|
||||
|
@ -1526,11 +1533,13 @@ private:
|
|||
|
||||
MD5_HASH checksum() const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::vector<POLYGON> m_polys;
|
||||
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>> m_triangulatedPolys;
|
||||
|
||||
bool m_triangulationValid = false;
|
||||
|
||||
private:
|
||||
MD5_HASH m_hash;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2019 CERN
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
|
@ -2981,7 +2981,8 @@ static SHAPE_POLY_SET partitionPolyIntoRegularCellGrid( const SHAPE_POLY_SET& aP
|
|||
}
|
||||
|
||||
|
||||
void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
|
||||
void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
|
||||
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>>* aHintData )
|
||||
{
|
||||
bool recalculate = !m_hash.IsValid();
|
||||
MD5_HASH hash;
|
||||
|
@ -3005,10 +3006,15 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
|
|||
|
||||
auto triangulate =
|
||||
[]( SHAPE_POLY_SET& polySet, int forOutline,
|
||||
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>>& dest )
|
||||
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>>& dest,
|
||||
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>>* hintData )
|
||||
{
|
||||
bool triangulationValid = false;
|
||||
int pass = 0;
|
||||
int index = 0;
|
||||
|
||||
if( hintData && hintData->size() != (unsigned) polySet.OutlineCount() )
|
||||
hintData = nullptr;
|
||||
|
||||
while( polySet.OutlineCount() > 0 )
|
||||
{
|
||||
|
@ -3021,7 +3027,8 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
|
|||
// If the tessellation fails, we re-fracture the polygon, which will
|
||||
// first simplify the system before fracturing and removing the holes
|
||||
// This may result in multiple, disjoint polygons.
|
||||
if( !tess.TesselatePolygon( polySet.Polygon( 0 ).front() ) )
|
||||
if( !tess.TesselatePolygon( polySet.Polygon( 0 ).front(),
|
||||
hintData ? hintData->at( index ).get() : nullptr ) )
|
||||
{
|
||||
++pass;
|
||||
|
||||
|
@ -3033,10 +3040,12 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
|
|||
break;
|
||||
|
||||
triangulationValid = false;
|
||||
hintData = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
polySet.DeletePolygon( 0 );
|
||||
index++;
|
||||
triangulationValid = true;
|
||||
}
|
||||
|
||||
|
@ -3067,7 +3076,7 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
|
|||
|
||||
// This pushes the triangulation for all polys in partitions
|
||||
// to be referenced to the ii-th polygon
|
||||
if( !triangulate( partitions, ii , m_triangulatedPolys ) )
|
||||
if( !triangulate( partitions, ii , m_triangulatedPolys, aHintData ) )
|
||||
{
|
||||
wxLogTrace( TRIANGULATE_TRACE, "Failed to triangulate partitioned polygon %d", ii );
|
||||
}
|
||||
|
@ -3081,7 +3090,7 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
|
|||
|
||||
tmpSet.Fracture( PM_FAST );
|
||||
|
||||
if( !triangulate( tmpSet, -1, m_triangulatedPolys ) )
|
||||
if( !triangulate( tmpSet, -1, m_triangulatedPolys, aHintData ) )
|
||||
{
|
||||
wxLogTrace( TRIANGULATE_TRACE, "Failed to triangulate polygon" );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue