Compare commits

...

8 Commits

Author SHA1 Message Date
Troy Denton
2c312cfeb3 Merge branch '18600_zone_fill_segfault_zero_area' into 'master'
Draft: pcbnew/drc: dont process edge case zone w/ 0 area #18600

Closes #18600

See merge request kicad/code/kicad!2041
2025-09-12 06:25:01 -04:00
Seth Hillbrand
5dc6d43f43 Add via tenting/plugging representation to 3d-viewer
Fixes https://gitlab.com/kicad/code/kicad/issues/21704
2025-09-12 01:23:41 -07:00
jean-pierre charras
98dd5a68eb Fix a compil issue on gcc/msys2
gcc does not like implicit conversion from wxString to char*
2025-09-12 08:20:49 +02:00
Troy Denton
0a8ff763e1 drc/drc_rtree.h: dont admit "rule" copper zones 2024-10-22 22:43:42 -04:00
Troy Denton
7155e97dbf drc_rtree.h: check for 0 outlines instead of 0 size 2024-10-21 21:48:47 -04:00
Troy Denton
be2ef5686c drc_rctree.h: try limiting scope of workaround to avoid regressions elsewhere 2024-10-21 13:47:44 +00:00
Troy Denton
e160be74d3 pcbnew/drc: dont process 0-area zone pt2
If a filled zone is outside of the board outline, it gets reduced
to the interection of the two, which is zero.  This change stops
zero-area polygons from being added to the drc rtree in this case,
because they alias to the origin.

Commit pt2: lint fix

Fixes:
2024-10-20 23:37:49 -04:00
Troy Denton
516a9d8008 pcbnew/drc: dont process edge case zone w/ 0 area
If a filled zone is outside of the board outline, it gets reduced
to the interection of the two, which is zero.  This change stops
zero-area polygons from being added to the drc rtree in this case,
because they alias to the origin.

Fixes: https://gitlab.com/kicad/code/kicad/issues/18600
2024-10-20 23:24:27 -04:00
5 changed files with 154 additions and 1 deletions

View File

@ -26,6 +26,7 @@
#include "render_3d_opengl.h"
#include <board.h>
#include <footprint.h>
#include <pcb_track.h>
#include "../../3d_math.h"
#include "convert_basic_shapes_to_polygon.h"
#include <lset.h>
@ -726,6 +727,54 @@ void RENDER_3D_OPENGL::generateCylinder( const SFVEC2F& aCenter, float aInnerRad
}
void RENDER_3D_OPENGL::generateDisk( const SFVEC2F& aCenter, float aRadius, float aZ,
unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST* aDstLayer,
bool aTop )
{
const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
for( unsigned int i = 0; i < aNr_sides_per_circle; ++i )
{
float a0 = delta * i;
float a1 = delta * ( i + 1 );
const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
aCenter.y + sinf( a0 ) * aRadius, aZ );
const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
aCenter.y + sinf( a1 ) * aRadius, aZ );
const SFVEC3F c( aCenter.x, aCenter.y, aZ );
if( aTop )
aDstLayer->m_layer_top_triangles->AddTriangle( p1, p0, c );
else
aDstLayer->m_layer_bot_triangles->AddTriangle( p0, p1, c );
}
}
void RENDER_3D_OPENGL::generateDimple( const SFVEC2F& aCenter, float aRadius, float aZ,
float aDepth, unsigned int aNr_sides_per_circle,
TRIANGLE_DISPLAY_LIST* aDstLayer, bool aTop )
{
const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
const SFVEC3F c( aCenter.x, aCenter.y, aTop ? aZ - aDepth : aZ + aDepth );
for( unsigned int i = 0; i < aNr_sides_per_circle; ++i )
{
float a0 = delta * i;
float a1 = delta * ( i + 1 );
const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
aCenter.y + sinf( a0 ) * aRadius, aZ );
const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
aCenter.y + sinf( a1 ) * aRadius, aZ );
if( aTop )
aDstLayer->m_layer_top_triangles->AddTriangle( p0, p1, c );
else
aDstLayer->m_layer_bot_triangles->AddTriangle( p1, p0, c );
}
}
void RENDER_3D_OPENGL::generateViasAndPads()
{
if( !m_boardAdapter.GetBoard() )
@ -882,6 +931,63 @@ void RENDER_3D_OPENGL::generateViasAndPads()
delete layerTriangles;
}
}
TRIANGLE_DISPLAY_LIST* frontCover = new TRIANGLE_DISPLAY_LIST( m_boardAdapter.GetViaCount() );
TRIANGLE_DISPLAY_LIST* backCover = new TRIANGLE_DISPLAY_LIST( m_boardAdapter.GetViaCount() );
for( const PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
{
if( track->Type() != PCB_VIA_T )
continue;
const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
const float holediameter = via->GetDrillValue() * m_boardAdapter.BiuTo3dUnits();
const float hole_radius = holediameter / 2.0f + 2.0 * platingThickness3d;
const SFVEC2F center( via->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
-via->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
unsigned int seg = m_boardAdapter.GetCircleSegmentCount( via->GetDrillValue() );
PCB_LAYER_ID top_layer, bottom_layer;
via->LayerPair( &top_layer, &bottom_layer );
float ztop, zbot, dummy;
getLayerZPos( top_layer, ztop, dummy );
getLayerZPos( bottom_layer, dummy, zbot );
bool frontCovering = via->GetFrontCoveringMode() == COVERING_MODE::COVERED || via->IsTented( F_Mask );
bool backCovering = via->GetBackCoveringMode() == COVERING_MODE::COVERED || via->IsTented( B_Mask );
bool frontPlugged = via->GetFrontPluggingMode() == PLUGGING_MODE::PLUGGED;
bool backPlugged = via->GetBackPluggingMode() == PLUGGING_MODE::PLUGGED;
bool filled = via->GetFillingMode() == FILLING_MODE::FILLED
|| via->GetCappingMode() == CAPPING_MODE::CAPPED;
const float depth = hole_radius * 0.3f;
if( frontCovering )
{
if( filled || !frontPlugged )
generateDisk( center, hole_radius, ztop, seg, frontCover, true );
else
generateDimple( center, hole_radius, ztop, depth, seg, frontCover, true );
}
if( backCovering )
{
if( filled || !backPlugged )
generateDisk( center, hole_radius, zbot, seg, backCover, false );
else
generateDimple( center, hole_radius, zbot, depth, seg, backCover, false );
}
}
if( frontCover->m_layer_top_triangles->GetVertexSize() > 0 )
m_viaFrontCover = new OPENGL_RENDER_LIST( *frontCover, 0, 0.0f, 0.0f );
if( backCover->m_layer_bot_triangles->GetVertexSize() > 0 )
m_viaBackCover = new OPENGL_RENDER_LIST( *backCover, 0, 0.0f, 0.0f );
delete frontCover;
delete backCover;
}

View File

@ -72,6 +72,8 @@ RENDER_3D_OPENGL::RENDER_3D_OPENGL( EDA_3D_CANVAS* aCanvas, BOARD_ADAPTER& aAdap
m_outerViaThroughHoles = nullptr;
m_microviaHoles = nullptr;
m_padHoles = nullptr;
m_viaFrontCover = nullptr;
m_viaBackCover = nullptr;
m_circleTexture = 0;
m_grid = 0;
@ -947,6 +949,8 @@ void RENDER_3D_OPENGL::freeAllLists()
DELETE_AND_FREE( m_microviaHoles )
DELETE_AND_FREE( m_padHoles )
DELETE_AND_FREE( m_viaFrontCover )
DELETE_AND_FREE( m_viaBackCover )
}
@ -968,6 +972,17 @@ void RENDER_3D_OPENGL::renderSolderMaskLayer( PCB_LAYER_ID aLayerID, float aZPos
setLayerMaterial( aLayerID );
m_board->SetItIsTransparent( true );
m_board->DrawCulled( aShowThickness, solder_mask, via_holes );
if( aLayerID == F_Mask && m_viaFrontCover )
{
m_viaFrontCover->ApplyScalePosition( aZPos, 4 * m_boardAdapter.GetNonCopperLayerThickness() );
m_viaFrontCover->DrawTop();
}
else if( aLayerID == B_Mask && m_viaBackCover )
{
m_viaBackCover->ApplyScalePosition( aZPos, 4 * m_boardAdapter.GetNonCopperLayerThickness() );
m_viaBackCover->DrawBot();
}
}
}

View File

@ -123,6 +123,14 @@ private:
float aZtop, float aZbot, unsigned int aNr_sides_per_circle,
TRIANGLE_DISPLAY_LIST* aDstLayer );
void generateDisk( const SFVEC2F& aCenter, float aRadius, float aZ,
unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST* aDstLayer,
bool aTop );
void generateDimple( const SFVEC2F& aCenter, float aRadius, float aZ, float aDepth,
unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST* aDstLayer,
bool aTop );
void generateViasAndPads();
/**
@ -236,6 +244,8 @@ private:
OPENGL_RENDER_LIST* m_microviaHoles;
OPENGL_RENDER_LIST* m_padHoles;
OPENGL_RENDER_LIST* m_viaFrontCover;
OPENGL_RENDER_LIST* m_viaBackCover;
// Caches
std::map<wxString, MODEL_3D*> m_3dModelMap;

View File

@ -542,7 +542,8 @@ void DRC_ENGINE::compileRules()
}
if( error_semaphore.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) )
THROW_PARSE_ERROR( wxT( "Parse error" ), rule->m_Name, rule->m_Condition->GetExpression(), 0, 0 );
THROW_PARSE_ERROR( wxT( "Parse error" ), rule->m_Name,
TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
{

View File

@ -39,6 +39,7 @@
#include <math/vector2d.h>
#include "geometry/shape_null.h"
#include "board.h"
#include "zone.h"
/**
* Implement an R-tree for fast spatial and layer indexing of connectable items.
@ -118,6 +119,15 @@ public:
if( aItem->Type() == PCB_FIELD_T && !static_cast<PCB_FIELD*>( aItem )->IsVisible() )
return;
if( aItem->Type() == PCB_ZONE_T )
{
ZONE* aZone = static_cast<ZONE*>( aItem );
if( !aZone->IsConnected() && aZone->IsOnCopperLayer() )
{
return;
}
}
std::vector<const SHAPE*> subshapes;
std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( aRefLayer );
@ -135,6 +145,17 @@ public:
BOX2I bbox = subshape->BBox();
// there is an edge case where filled zones can get reduced to a point,
// e.g. when they exist outside of the board outline, the intersection
// w/ the board outline becomes a polygon of area 0
if( aItem->Type() == PCB_ZONE_T )
{
wxASSERT( dynamic_cast<const SHAPE_POLY_SET*>( subshape ) );
const SHAPE_POLY_SET* poly = dynamic_cast<const SHAPE_POLY_SET*>( subshape );
if( poly->OutlineCount() == 0 )
continue;
}
bbox.Inflate( aWorstClearance );
const int mmin[2] = { bbox.GetX(), bbox.GetY() };