/// <summary> /// Returns true if the passed point is inside a net. /// If this is the case, then the net id is passed /// to the out parameter. /// </summary> /// <param name="x">Abscissa of the point to check.</param> /// <param name="y">Ordinate of the point to check.</param> /// <param name="netId">Net Id of the net touched by the point, if any.</param> /// <returns>True if the passed point lies inside a net, i.e. copper.</returns> public bool TryGetNetAt(float x, float y, out int netId) { Console.WriteLine($"\nTryGetNetAt {x},{y}"); var reference = new Scanline() { Y = (int)y, }; var index = this.scanlines.BinarySearch(reference, new ScanlineComparer()); netId = 1; if (index < 0) { // No scanline at the passed orindate return(false); } // A scanline exists at the passed ordinate Scanline found = this.scanlines[index]; for (int i = 0; i < found.Length; i++) { Segment segment = this.segments[found.InitialIndex + i]; Console.WriteLine($"{segment}"); if (segment.ContainsAbscissa(x)) { Console.WriteLine("Qui"); netId = segment.NetList; return(true); } } return(false); }
/// <summary> /// Scans the bitmap, i.e. builds the list of scanned segments. /// </summary> public void Scan() { Segment currentSegment = new Segment(); bool isSegmentOpen = false; for (int y = 0; y < this.bitmap.Height; y++) { // Console.WriteLine($"Y={y}"); var currentScanline = new Scanline() { Y = y, InitialIndex = this.segments.Count, }; bool previousPixel = false; for (int x = 0; x <= this.bitmap.Width; x++) { bool currentPixel = x < this.bitmap.Width ? this.bitmap.PixelAt(x, y) : false; if (!previousPixel && currentPixel) { // Console.WriteLine($"Start at {x}"); // Starts a contiguous segment currentSegment = new Segment() { Y = y, XMin = x, }; isSegmentOpen = true; } if (previousPixel && !currentPixel) { // Console.WriteLine($"End at {x-1}"); // Ends a contiguous segment Debug.Assert(isSegmentOpen, "The segment must be open in this case."); currentSegment.XMax = x - 1; currentScanline.Length++; this.segments.Add(currentSegment); isSegmentOpen = false; } previousPixel = currentPixel; } if (currentScanline.Length > 0) { this.scanlines.Add(currentScanline); } } }
/// <summary> /// Checks which segments are connected together and sets an identical net identifier to all of them. /// </summary> public void ComputeNetlists() { int netlist = 1; Scanline previousScanline = null; foreach (var scanline in this.scanlines) { scanline.Foreach( this.segments, (segment) => { segment.NetList = netlist++; if ((previousScanline == null) || (previousScanline.Y < scanline.Y - 1)) { return; } var touchingSegments = previousScanline.GetTouchingSegments(this.segments, segment); Console.WriteLine($"Touching segments count {touchingSegments.Count}"); bool isFirst = true; foreach (var touchingSegment in touchingSegments) { if (isFirst) { segment.NetList = touchingSegment.NetList; isFirst = false; } else { scanline.BackPropagate(this.segments, segment.NetList, touchingSegment.NetList); } } }); previousScanline = scanline; } }