44 case CATEGORY::ADDED:
return aTheme.
added;
45 case CATEGORY::REMOVED:
return aTheme.
removed;
46 case CATEGORY::MODIFIED:
return aTheme.
modified;
47 case CATEGORY::CONFLICT:
return aTheme.
conflict;
50 wxFAIL_MSG( wxS(
"Unknown CATEGORY" ) );
57 struct NET_SHAPE_GROUP
67 bool bboxValid(
const BOX2I& aBox )
78 return const_cast<std::vector<SCENE_SHAPE>&
>(
ShapesFor( aScene, aCategory ) );
82 void mergeSceneBBox(
const BOX2I& aBBox,
BOX2I& aUnionBBox,
bool& aFirst )
91 aUnionBBox.
Merge( aBBox );
96 SHAPE_POLY_SET polygonSetFromDiffValue(
const DIFF_VALUE& aValue )
103 for(
const auto& poly : aValue.AsPolygonSet() )
110 for(
const VECTOR2I& pt : poly.front() )
111 out.
Append( pt.x, pt.y, outlineIdx, -1 );
113 for( std::size_t h = 1; h < poly.size(); ++h )
115 int holeIdx = out.
NewHole( outlineIdx );
118 out.
Append( pt.x, pt.y, outlineIdx, holeIdx );
132 const auto& polyRefs = aPoly.
CPolygon( o );
133 std::vector<std::vector<VECTOR2I>> contours;
135 for(
const auto& contour : polyRefs )
137 std::vector<VECTOR2I> pts;
138 pts.reserve( contour.PointCount() );
140 for(
int p = 0; p < contour.PointCount(); ++p )
141 pts.push_back( contour.CPoint( p ) );
143 contours.push_back( std::move( pts ) );
146 out.push_back( std::move( contours ) );
154 const ITEM_CHANGE& aChange,
const SHAPE_POLY_SET& aRegion,
BOX2I& aUnionBBox,
bool& aFirst )
161 shape.changeId = aChange.id;
164 shape.polygons = polygonsFromPolySet( aRegion );
166 mutableShapesFor( aScene, aCategory ).push_back( std::move( shape ) );
167 mergeSceneBBox( aRegion.
BBox(), aUnionBBox, aFirst );
172 BOX2I& aUnionBBox,
bool& aFirst )
174 bool emitted =
false;
183 if( d.name != wxS(
"Outline" ) && !d.name.StartsWith( wxS(
"Filled Area" ) ) )
186 SHAPE_POLY_SET before = polygonSetFromDiffValue( d.before );
187 SHAPE_POLY_SET after = polygonSetFromDiffValue( d.after );
189 SHAPE_POLY_SET added = after;
192 SHAPE_POLY_SET removed = before;
195 pushDeltaShape( aScene, aTheme, CATEGORY::ADDED, aChange, added, aUnionBBox, aFirst );
196 pushDeltaShape( aScene, aTheme, CATEGORY::REMOVED, aChange, removed, aUnionBBox, aFirst );
207 BOX2I& aUnionBBox,
bool& aFirst )
209 if( emitOutlineDelta( aChange, aTheme, aScene, aUnionBBox, aFirst ) )
212 if( !bboxValid( aChange.bbox ) )
218 shape.
bbox = aChange.bbox;
219 shape.changeId = aChange.id;
224 mutableShapesFor( aScene, cat ).push_back( shape );
225 mergeSceneBBox( aChange.bbox, aUnionBBox, aFirst );
230 BOX2I& aUnionBBox,
bool& aFirst,
231 std::map<std::pair<CHANGE_KIND, wxString>, NET_SHAPE_GROUP>& aNetGroups )
235 auto&
group = aNetGroups[std::make_pair( aChange.kind, *aChange.refdes )];
239 group.firstChangeId = aChange.id;
240 group.netName = *aChange.refdes;
241 group.kind = aChange.kind;
242 group.bbox = aChange.bbox;
243 group.hasBBox = bboxValid( aChange.bbox );
245 else if( bboxValid( aChange.bbox ) )
247 group.bbox.Merge( aChange.bbox );
252 addChangeShape( aChange, aTheme, aScene, aUnionBBox, aFirst );
256 collectShapes( child, aTheme, aScene, aUnionBBox, aFirst, aNetGroups );
261 const std::map<std::pair<CHANGE_KIND, wxString>, NET_SHAPE_GROUP>& aNetGroups )
263 for(
const auto& [key,
group] : aNetGroups )
272 shape.changeId =
group.firstChangeId;
274 shape.label = wxS(
"NET [" ) +
group.netName + wxS(
"]" );
276 mutableShapesFor( aScene, cat ).push_back( shape );
277 mergeSceneBBox(
group.bbox, aUnionBBox, aFirst );
286 std::optional<BOX2I> bbox;
288 auto addPoint = [&](
const VECTOR2I& aPt )
290 if( !bbox.has_value() )
296 auto addPointInflated = [&](
const VECTOR2I& aPt,
int aHalfStroke )
299 addPoint( aPt -
pad );
300 addPoint( aPt +
pad );
312 addPointInflated( s.
start, half );
313 addPointInflated( s.
end, half );
329 addPointInflated( pt, half );
365 auto visible = [&](
const LSET& aLayers )
367 return aLayers.none() || ( aLayers & aVisibleLayers ).
any();
394 aDst.
segments.insert( aDst.
segments.end(), std::make_move_iterator( aSrc.segments.begin() ),
395 std::make_move_iterator( aSrc.segments.end() ) );
396 aDst.
polygons.insert( aDst.
polygons.end(), std::make_move_iterator( aSrc.polygons.begin() ),
397 std::make_move_iterator( aSrc.polygons.end() ) );
398 aDst.
circles.insert( aDst.
circles.end(), std::make_move_iterator( aSrc.circles.begin() ),
399 std::make_move_iterator( aSrc.circles.end() ) );
405 return aChange.
refdes.has_value() && !aChange.
refdes->IsEmpty()
406 && ( aChange.
typeName == wxS(
"PCB_TRACK" ) || aChange.
typeName == wxS(
"PCB_ARC" )
407 || aChange.
typeName == wxS(
"PCB_VIA" ) );
415 if( aChange.
refdes.has_value() )
416 label += wxS(
" [" ) + *aChange.
refdes + wxS(
"]" );
427 std::map<std::pair<CHANGE_KIND, wxString>, NET_SHAPE_GROUP> netGroups;
430 collectShapes( c, aTheme, scene, unionBBox, first, netGroups );
432 addNetShapes( aTheme, scene, unionBBox, first, netGroups );
437 wxLogTrace(
traceDiffMerge, wxT(
"BuildScene: %zu changes -> added=%zu removed=%zu modified=%zu conflict=%zu" ),
447 std::optional<BOX2I> unionBBox;
452 auto merge = [&](
const std::optional<BOX2I>& aSrc )
454 if( !aSrc.has_value() )
457 if( !unionBBox.has_value() )
460 unionBBox->Merge( *aSrc );
466 if( unionBBox.has_value() )
478 if( change->bbox.GetWidth() > 0 || change->bbox.GetHeight() > 0 )
479 aOut.emplace(
id, change->bbox );
506 for(
const auto& poly : aPolygons )
508 if( poly.empty() || poly.front().size() < 3 )
513 for(
const VECTOR2I& pt : poly.front() )
514 out.
Append( pt.x, pt.y, outlineIdx, -1 );
516 for( std::size_t h = 1; h < poly.size(); ++h )
518 int holeIdx = out.
NewHole( outlineIdx );
521 out.
Append( pt.x, pt.y, outlineIdx, holeIdx );
540 wxFAIL_MSG( wxS(
"Unknown CHANGE_KIND" ) );
541 return CATEGORY::MODIFIED;
555 wxFAIL_MSG( wxS(
"Unknown CATEGORY" ) );
561 const std::array<bool, CATEGORY_COUNT>& aCategoryVisible )
563 std::optional<BOX2I>
result;
567 if( !aCategoryVisible[
static_cast<std::size_t
>( cat )] )
572 if( s.changeId != aChangeId )
constexpr const Vec GetEnd() const
constexpr size_type GetWidth() const
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr size_type GetHeight() const
constexpr const Vec & GetOrigin() const
A typed sum value used to carry the before/after of any single property.
A color representation with 4 components: red, green, blue, alpha.
LSET is a set of PCB_LAYER_IDs.
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int NewHole(int aOutline=-1)
Creates a new hole in a given outline.
int OutlineCount() const
Return the number of outlines in the set.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const POLYGON & CPolygon(int aIndex) const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
A type-safe container of any type.
const wxChar *const traceDiffMerge
Flag to enable diff/merge engine and renderer debugging output.
CHANGE_KIND
Coarse classification of a single item-level change between two documents.
wxString ChangeDisplayLabel(const ITEM_CHANGE &aChange)
User-facing item label used consistently by scene tooltips and change tree entries.
DIFF_SCENE BuildScene(const DOCUMENT_DIFF &aDiff, const DIFF_COLOR_THEME &aTheme)
Build a DIFF_SCENE from a DOCUMENT_DIFF, populating the shape lists and computing the union bbox.
DOCUMENT_POLYGON MakeBBoxOutline(const BOX2I &aBBox, const KIGFX::COLOR4D &aColor, int aLineWidth)
Build a DOCUMENT_POLYGON outlining a bounding box.
LSET GeometryLayerSet(const DOCUMENT_GEOMETRY &aGeometry)
Return the union of every non-empty layer set carried by the geometry.
constexpr int EffectivePlotWidth(int aWidth)
Return aWidth if positive, otherwise PLOT_HAIRLINE_IU.
void CollectChangeBBoxes(const DOCUMENT_DIFF &aDiff, std::map< KIID_PATH, BOX2I > &aOut)
Walk a DOCUMENT_DIFF and populate a (KIID_PATH → BOX2I) map with each changed item's bbox,...
KIGFX::COLOR4D ThemeColorFor(const DIFF_COLOR_THEME &aTheme, CATEGORY aCategory)
Map a CATEGORY to its color in a DIFF_COLOR_THEME.
std::optional< BOX2I > HighlightedBBox(const DIFF_SCENE &aScene, const KIID_PATH &aChangeId, const std::array< bool, CATEGORY_COUNT > &aCategoryVisible)
Union bbox of every visible SCENE_SHAPE whose changeId matches aChangeId.
void AppendGeometry(DOCUMENT_GEOMETRY &aDst, DOCUMENT_GEOMETRY &&aSrc)
Move all primitives from aSrc into aDst.
void ExpandBBoxToGeometry(DIFF_SCENE &aScene)
Grow the scene's documentBBox to also include the extent of any background geometry.
bool IsRoutingNetChange(const ITEM_CHANGE &aChange)
Presentation predicate for PCB routing changes that should be displayed as one net-level entry/shape.
CATEGORY
Visual category each ITEM_CHANGE belongs to in the scene.
std::map< KIID_PATH, const ITEM_CHANGE * > IndexChangesByKiid(const DOCUMENT_DIFF &aDiff)
Flatten a DOCUMENT_DIFF's ITEM_CHANGE tree into a KIID_PATH -> ITEM_CHANGE* map, recursing into child...
const std::vector< SCENE_SHAPE > & ShapesFor(const DIFF_SCENE &aScene, CATEGORY aCategory)
Read-only access to a DIFF_SCENE's shape list for a given category.
constexpr std::array< CATEGORY, 4 > PAINT_ORDER
Paint order.
SHAPE_POLY_SET PolySetFromPolygonList(const SCENE_SHAPE::PolygonList &aPolygons)
Build a SHAPE_POLY_SET from a SCENE_SHAPE::PolygonList.
std::optional< BOX2I > BBoxFromGeometry(const DOCUMENT_GEOMETRY &aGeometry)
Compute the tight bounding box of a DOCUMENT_GEOMETRY, inflating each primitive by half its stroke so...
CATEGORY CategoryFor(CHANGE_KIND aKind)
Map a CHANGE_KIND to the visual category it belongs to.
DOCUMENT_GEOMETRY FilterGeometryByVisibleLayers(const DOCUMENT_GEOMETRY &aGeometry, const LSET &aVisibleLayers)
Copy geometry primitives whose layer set intersects aVisibleLayers.
std::vector< SCENE_SHAPE > modifiedShapes
DOCUMENT_GEOMETRY referenceGeometry
Background geometry from the two source documents.
std::vector< SCENE_SHAPE > conflictShapes
std::vector< SCENE_SHAPE > addedShapes
DOCUMENT_GEOMETRY comparisonGeometry
std::vector< SCENE_SHAPE > removedShapes
Filled or stroked circle.
The full set of changes between two parsed documents of one type.
std::vector< ITEM_CHANGE > changes
Aggregate of background geometry extracted from one source document.
std::vector< DOCUMENT_SEGMENT > segments
std::vector< DOCUMENT_POLYGON > polygons
std::vector< DOCUMENT_CIRCLE > circles
Closed polygon outline from a source document.
std::vector< VECTOR2I > outline
Stroked line segment from one of the source documents.
One change record on a single item.
std::optional< wxString > refdes
std::vector< ITEM_CHANGE > children
Single (name, before, after) triple for one mutated property on an item.
Shared rendering model consumed by both the GAL renderer (interactive widget) and the plotter rendere...
std::vector< std::vector< std::vector< VECTOR2I > > > PolygonList
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I