47 *color = color->Brightened( 0.4 );
58 case CATEGORY::ADDED:
return aTheme.
added;
59 case CATEGORY::REMOVED:
return aTheme.
removed;
60 case CATEGORY::MODIFIED:
return aTheme.
modified;
61 case CATEGORY::CONFLICT:
return aTheme.
conflict;
64 wxFAIL_MSG( wxS(
"Unknown CATEGORY" ) );
71 struct NET_SHAPE_GROUP
81 bool bboxValid(
const BOX2I& aBox )
92 return const_cast<std::vector<SCENE_SHAPE>&
>(
ShapesFor( aScene, aCategory ) );
96 void mergeSceneBBox(
const BOX2I& aBBox,
BOX2I& aUnionBBox,
bool& aFirst )
105 aUnionBBox.
Merge( aBBox );
110 SHAPE_POLY_SET polygonSetFromDiffValue(
const DIFF_VALUE& aValue )
117 for(
const auto& poly : aValue.AsPolygonSet() )
124 for(
const VECTOR2I& pt : poly.front() )
125 out.
Append( pt.x, pt.y, outlineIdx, -1 );
127 for( std::size_t h = 1; h < poly.size(); ++h )
129 int holeIdx = out.
NewHole( outlineIdx );
132 out.
Append( pt.x, pt.y, outlineIdx, holeIdx );
146 const auto& polyRefs = aPoly.
CPolygon( o );
147 std::vector<std::vector<VECTOR2I>> contours;
149 for(
const auto& contour : polyRefs )
151 std::vector<VECTOR2I> pts;
152 pts.reserve( contour.PointCount() );
154 for(
int p = 0; p < contour.PointCount(); ++p )
155 pts.push_back( contour.CPoint( p ) );
157 contours.push_back( std::move( pts ) );
160 out.push_back( std::move( contours ) );
168 const ITEM_CHANGE& aChange,
const SHAPE_POLY_SET& aRegion,
BOX2I& aUnionBBox,
bool& aFirst )
175 shape.changeId = aChange.id;
178 shape.polygons = polygonsFromPolySet( aRegion );
180 mutableShapesFor( aScene, aCategory ).push_back( std::move( shape ) );
181 mergeSceneBBox( aRegion.
BBox(), aUnionBBox, aFirst );
186 BOX2I& aUnionBBox,
bool& aFirst )
188 bool emitted =
false;
197 if( d.name != wxS(
"Outline" ) && !d.name.StartsWith( wxS(
"Filled Area" ) ) )
200 SHAPE_POLY_SET before = polygonSetFromDiffValue( d.before );
201 SHAPE_POLY_SET after = polygonSetFromDiffValue( d.after );
203 SHAPE_POLY_SET added = after;
206 SHAPE_POLY_SET removed = before;
209 pushDeltaShape( aScene, aTheme, CATEGORY::ADDED, aChange, added, aUnionBBox, aFirst );
210 pushDeltaShape( aScene, aTheme, CATEGORY::REMOVED, aChange, removed, aUnionBBox, aFirst );
221 BOX2I& aUnionBBox,
bool& aFirst )
223 if( emitOutlineDelta( aChange, aTheme, aScene, aUnionBBox, aFirst ) )
226 if( !bboxValid( aChange.bbox ) )
232 shape.
bbox = aChange.bbox;
233 shape.changeId = aChange.id;
238 mutableShapesFor( aScene, cat ).push_back( shape );
239 mergeSceneBBox( aChange.bbox, aUnionBBox, aFirst );
244 BOX2I& aUnionBBox,
bool& aFirst,
245 std::map<std::pair<CHANGE_KIND, wxString>, NET_SHAPE_GROUP>& aNetGroups )
249 auto&
group = aNetGroups[std::make_pair( aChange.kind, *aChange.refdes )];
253 group.firstChangeId = aChange.id;
254 group.netName = *aChange.refdes;
255 group.kind = aChange.kind;
256 group.bbox = aChange.bbox;
257 group.hasBBox = bboxValid( aChange.bbox );
259 else if( bboxValid( aChange.bbox ) )
261 group.bbox.Merge( aChange.bbox );
266 addChangeShape( aChange, aTheme, aScene, aUnionBBox, aFirst );
270 collectShapes( child, aTheme, aScene, aUnionBBox, aFirst, aNetGroups );
275 const std::map<std::pair<CHANGE_KIND, wxString>, NET_SHAPE_GROUP>& aNetGroups )
277 for(
const auto& [key,
group] : aNetGroups )
286 shape.changeId =
group.firstChangeId;
288 shape.label = wxS(
"NET [" ) +
group.netName + wxS(
"]" );
290 mutableShapesFor( aScene, cat ).push_back( shape );
291 mergeSceneBBox(
group.bbox, aUnionBBox, aFirst );
300 std::optional<BOX2I> bbox;
302 auto addPoint = [&](
const VECTOR2I& aPt )
304 if( !bbox.has_value() )
310 auto addPointInflated = [&](
const VECTOR2I& aPt,
int aHalfStroke )
313 addPoint( aPt -
pad );
314 addPoint( aPt +
pad );
326 addPointInflated( s.
start, half );
327 addPointInflated( s.
end, half );
343 addPointInflated( pt, half );
379 auto visible = [&](
const LSET& aLayers )
381 return aLayers.none() || ( aLayers & aVisibleLayers ).
any();
408 aDst.
segments.insert( aDst.
segments.end(), std::make_move_iterator( aSrc.segments.begin() ),
409 std::make_move_iterator( aSrc.segments.end() ) );
410 aDst.
polygons.insert( aDst.
polygons.end(), std::make_move_iterator( aSrc.polygons.begin() ),
411 std::make_move_iterator( aSrc.polygons.end() ) );
412 aDst.
circles.insert( aDst.
circles.end(), std::make_move_iterator( aSrc.circles.begin() ),
413 std::make_move_iterator( aSrc.circles.end() ) );
419 return aChange.
refdes.has_value() && !aChange.
refdes->IsEmpty()
420 && ( aChange.
typeName == wxS(
"PCB_TRACK" ) || aChange.
typeName == wxS(
"PCB_ARC" )
421 || aChange.
typeName == wxS(
"PCB_VIA" ) );
429 if( aChange.
refdes.has_value() )
430 label += wxS(
" [" ) + *aChange.
refdes + wxS(
"]" );
441 std::map<std::pair<CHANGE_KIND, wxString>, NET_SHAPE_GROUP> netGroups;
444 collectShapes( c, aTheme, scene, unionBBox, first, netGroups );
446 addNetShapes( aTheme, scene, unionBBox, first, netGroups );
451 wxLogTrace(
traceDiffMerge, wxT(
"BuildScene: %zu changes -> added=%zu removed=%zu modified=%zu conflict=%zu" ),
479 std::optional<BOX2I> unionBBox;
484 auto merge = [&](
const std::optional<BOX2I>& aSrc )
486 if( !aSrc.has_value() )
489 if( !unionBBox.has_value() )
492 unionBBox->Merge( *aSrc );
498 if( unionBBox.has_value() )
510 if( change->bbox.GetWidth() > 0 || change->bbox.GetHeight() > 0 )
511 aOut.emplace(
id, change->bbox );
538 for(
const auto& poly : aPolygons )
540 if( poly.empty() || poly.front().size() < 3 )
545 for(
const VECTOR2I& pt : poly.front() )
546 out.
Append( pt.x, pt.y, outlineIdx, -1 );
548 for( std::size_t h = 1; h < poly.size(); ++h )
550 int holeIdx = out.
NewHole( outlineIdx );
553 out.
Append( pt.x, pt.y, outlineIdx, holeIdx );
572 wxFAIL_MSG( wxS(
"Unknown CHANGE_KIND" ) );
573 return CATEGORY::MODIFIED;
587 wxFAIL_MSG( wxS(
"Unknown CATEGORY" ) );
593 const std::array<bool, CATEGORY_COUNT>& aCategoryVisible )
595 std::optional<BOX2I>
result;
599 if( !aCategoryVisible[
static_cast<std::size_t
>( cat )] )
604 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.
SIDE_BY_SIDE_SCENES SplitSceneBySide(const DIFF_SCENE &aScene)
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.
Diff colors with defaults for light backgrounds.
static DIFF_COLOR_THEME ForText(bool aDarkTheme)
Resolve change colors for UI text. Pass the desktop theme captured on the UI thread.
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
The two halves of a side by side view.
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I