// src/services/pcb/crossProbing.ts
export class CrossProbingManager {
private componentNetMap = new Map<string, string[]>();
private netComponentMap = new Map<string, string[]>();
private listeners: CrossProbingListener[] = [];
constructor(components: TscircuitComponent[], nets: TscircuitNet[]) {
this.buildCrossReferenceMaps(components, nets);
}
private buildCrossReferenceMaps(
components: TscircuitComponent[],
nets: TscircuitNet[]
): void {
// Build component -> nets mapping
for (const component of components) {
const connectedNets = nets
.filter(net =>
net.connections.some(conn => conn.component === component.id)
)
.map(net => net.name);
this.componentNetMap.set(component.id, connectedNets);
}
// Build net -> components mapping
for (const net of nets) {
const connectedComponents = net.connections.map(conn => conn.component);
this.netComponentMap.set(net.name, connectedComponents);
}
}
probeComponent(componentId: string): CrossProbingResult {
const connectedNets = this.componentNetMap.get(componentId) || [];
const relatedComponents = new Set<string>();
// Find all components connected to the same nets
for (const netName of connectedNets) {
const netComponents = this.netComponentMap.get(netName) || [];
netComponents.forEach(compId => {
if (compId !== componentId) {
relatedComponents.add(compId);
}
});
}
const result: CrossProbingResult = {
sourceType: 'component',
sourceId: componentId,
connectedNets,
relatedComponents: Array.from(relatedComponents),
highlightAreas: this.calculateHighlightAreas(componentId, connectedNets)
};
this.notifyListeners('component_probed', result);
return result;
}
probeNet(netName: string): CrossProbingResult {
const connectedComponents = this.netComponentMap.get(netName) || [];
const relatedNets = this.findRelatedNets(netName, connectedComponents);
const result: CrossProbingResult = {
sourceType: 'net',
sourceId: netName,
connectedNets: [netName, ...relatedNets],
relatedComponents: connectedComponents,
highlightAreas: this.calculateNetHighlightAreas(netName)
};
this.notifyListeners('net_probed', result);
return result;
}
probePad(componentId: string, padName: string): CrossProbingResult {
// Find the specific net connected to this pad
const component = this.findComponent(componentId);
const connectedNet = this.findNetForPad(componentId, padName);
if (!connectedNet) {
return this.createEmptyResult('pad', `${componentId}.${padName}`);
}
const result: CrossProbingResult = {
sourceType: 'pad',
sourceId: `${componentId}.${padName}`,
connectedNets: [connectedNet],
relatedComponents: this.netComponentMap.get(connectedNet) || [],
highlightAreas: this.calculatePadHighlightAreas(componentId, padName, connectedNet)
};
this.notifyListeners('pad_probed', result);
return result;
}
// Advanced cross-probing: find signal paths
findSignalPath(
sourceComponent: string,
targetComponent: string
): SignalPath[] {
const paths: SignalPath[] = [];
const sourceNets = this.componentNetMap.get(sourceComponent) || [];
const targetNets = this.componentNetMap.get(targetComponent) || [];
// Find direct connections
for (const net of sourceNets) {
if (targetNets.includes(net)) {
paths.push({
type: 'direct',
sourceComponent,
targetComponent,
viaNet: net,
length: this.calculateNetLength(net),
layerTransitions: this.getNetLayerTransitions(net)
});
}
}
// Find indirect connections through components
// (e.g., through resistors, capacitors, connectors)
// This would require more complex graph traversal
return paths;
}
addListener(listener: CrossProbingListener): void {
this.listeners.push(listener);
}
removeListener(listener: CrossProbingListener): void {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
}
private notifyListeners(event: CrossProbingEvent, result: CrossProbingResult): void {
for (const listener of this.listeners) {
listener(event, result);
}
}
}
Phase 5: Advanced Features & Professional Tools
Parent Issue: #440
Duration: 4-5 days
Goal: Implement advanced professional-grade features that distinguish this from basic PCB viewers.
Overview
This phase adds sophisticated features typically found in professional PCB analysis tools, including layer stack management, 3D visualization, design rule checking, cross-probing, and advanced analysis capabilities. These features provide the professional polish that makes the viewer suitable for serious PCB work.
Detailed Development Steps
5.1 Layer Stack Management
Layer Stack Visualization
Layer Configuration Manager
5.2 3D Visualization Mode
3D Board Representation
Component 3D Models
5.3 Design Rule Checking (DRC)
Basic DRC Engine
DRC Results Viewer
5.4 Cross-Probing System
5.5 Electrical Analysis Tools
5.6 Gerber Export Preview
Acceptance Criteria
Testing Checklist
Output/Deliverables
Dependencies
Next Phase Dependencies
Phase 6 (Performance) depends on this phase providing:
Estimated Time: 4-5 days
Priority: Medium-High (Professional features)
Complexity: High