Tuesday, April 19, 2022

31-Microwave Tools Feature Integration

In this post, the code for component rotation, selection, deletion, and wire stretch will be integrated into the MicrowaveTools project. Note that all of these features are available in the TestStrechWires project. Set MicrowaveTools as the startup project.

No changes are required for the Circuit.cs class.

Component Classes

Copy the following classes from TestStretchWires to the MicrowaveTools project.

  • Comp.cs
  • InPort.cs
  • OutPort.cs
  • RES.cs
  • Wire.cs
Don't forget to change the namespace to MicrowaveTools.

Ground Class (Ground.cs)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace MicrowaveTools.Components.Ideal
{
    public class Ground : Comp
    {
        public Ground()
        {
 
        }
 
        public Ground(Point pt)
        {
            Loc.X = pt.X;
            Loc.Y = pt.Y;
            Width = 60;
            Height = 60;
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            Pout = new Point(Loc.X + compSize, Loc.Y + halfCompSize);
        }
 
        // Let the Ground draw itself called from the canvas paint event
        public override void Draw(Graphics gr)
        {
            checkSelect();
            drawSelectRect(gr, new Point(Loc.X, Loc.Y + 30));
 
            GraphicsPath gp = new GraphicsPath();
 
            // Define the points
            Point p1 = Loc;
            Point p2 = new Point(p1.X, p1.Y + leadL);
            Point p3 = new Point(p2.X - 10, p2.Y);
            Point p4 = new Point(p2.X + 10, p2.Y);
            Point p5 = new Point(p3.X + 5, p3.Y + 5);
            Point p6 = new Point(p5.X + 10, p5.Y);
            Point p7 = new Point(p5.X + 3, p5.Y + 5);
            Point p8 = new Point(p7.X + 4, p7.Y);
 
            // Draw the input lead
            gp.AddLine(p1, p2);
            gp.AddLine(p3, p4);
            gp.AddLine(p5, p6);
            gp.AddLine(p7, p8);
 
            // Set rotation angle
            if (isRotated)
                angle = 90;
            else
                angle = 0;
 
            // Rotate the component by angle deg
            PointF rotatePoint = new PointF(Loc.X + 30, Loc.Y + 30); // Rotate about component center point
            Matrix myMatrix = new Matrix();
            myMatrix.RotateAt(angle, rotatePoint, MatrixOrder.Append);
            gr.Transform = myMatrix;
 
            // Update the bounding box location
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            // Draw the component path
            gr.DrawPath(drawPen, gp);
 
            // Draw the bounding box for debug
            //gr.DrawRectangle(redPen, boundBox);
 
            gp.Dispose();
        }
    }
}

Inductor Class (IND.cs)

// C# Libraries
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace MicrowaveTools.Components.Lumped
{
    public class IND : Comp
    {
        public IND()
        {
 
        }
 
        public IND(double value, Point pt)
        {
            Loc.X = pt.X;
            Loc.Y = pt.Y;
            Width = 60;
            Height = 60;
            Value = value;
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            Pin = new Point(Loc.X, Loc.Y + 30);
            Pout = new Point(Loc.X + compSize, Loc.Y + 30);
        }
 
        public override void Draw(Graphics gr)
        {
            // Component selection
            checkSelect();
            drawSelectRect(gr, new Point(Loc.X, Loc.Y + 30));
            drawSelectRect(gr, new Point(Loc.X + compL - endcap_radius, Loc.Y + 30));
 
            GraphicsPath gp = new GraphicsPath();
 
            // Draw the input leads
            gp.AddLine(Loc.X, Loc.Y + 30, Loc.X + leadL, Loc.Y + 30);
 
            // Draw the inductor body curves
            for (int i = 1; i < 5; i++)
            {
                float startAngle = 180;
                float sweepAngle = 180;
                Rectangle rect = new Rectangle(Loc.X + leadL * (i), Loc.Y - leadL - 5 + 30, leadL, leadL);
                gp.AddArc(rect, startAngle, sweepAngle);
            }
 
            // Draw the inductor body vertical lines
            for (int i = 1; i < 6; i++)
            {
                gr.DrawLine(drawPen, Loc.X + leadL * (i), Loc.Y + 30, Loc.X + leadL * (i), Loc.Y - leadL + 30);
            }
 
            // Draw the output leads
            gp.AddLine(Loc.X + bodyL + leadL, Loc.Y + 30, Loc.X + compL, Loc.Y + 30);   // Output lead
 
            // Draw the component text
            compText = "L = " + this.Value + "nH";
            pt = new Point(Loc.X + 5, Loc.Y);
            gp.AddString(compText, family, fontStyle, emSize, pt, format);
 
            // Set rotation angle
            if (isRotated)
                angle = 90;
            else
                angle = 0;
 
            // Rotate the component by angle deg
            PointF rotatePoint = new PointF(Loc.X + 30, Loc.Y + 30); // Rotate about component center point
            Matrix myMatrix = new Matrix();
            myMatrix.RotateAt(angle, rotatePoint, MatrixOrder.Append);
            gr.Transform = myMatrix;
 
            // Update the bounding box location
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            // Draw the component path
            gr.DrawPath(drawPen, gp);
 
            // Draw the bounding box for debug
            //gr.DrawRectangle(redPen, boundBox);
 
            gp.Dispose();
        }
    }
}

Capacitor Class (CAP.cs)

// C# Libraries
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace MicrowaveTools.Components.Lumped
{
    public class CAP : Comp
    {
        public CAP()
        {
 
        }
 
        public CAP(double value, Point pt)
        {
            Loc.X = pt.X;
            Loc.Y = pt.Y;
            Width = 60;
            Height = 60;
            Value = value;
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            Pin = new Point(Loc.X, Loc.Y + 30);
            Pout = new Point(Loc.X + compSize, Loc.Y + 30);
        }
 
        // Let the Capacitor draw itself called from the canvas paint event
        public override void Draw(Graphics gr)
        {
            // Component selection
            checkSelect();
            drawSelectRect(gr, new Point(Loc.X, Loc.Y + 30));
            drawSelectRect(gr, new Point(Loc.X + compL - endcap_radius, Loc.Y + 30));
 
            GraphicsPath gp = new GraphicsPath();
 
            // Draw the input leads
            gp.AddLine(Loc.X, Loc.Y + 30, Loc.X + 2 * leadL + 5, Loc.Y + 30);
 
            // Draw the capacitor body vertical line
            gp.AddLine(Loc.X + 2 * leadL + 5, Loc.Y - leadL + 30, Loc.X + 2 * leadL + 5, Loc.Y + leadL + 30);
 
            gp.StartFigure(); // Starts a new figure without closing the current figure.
 
            // Draw the capacitor body curves
            float startAngle = 90;
            float sweepAngle = 180;
            Rectangle rect = new Rectangle(Loc.X + 3 * leadL, Loc.Y - 10 + 30, leadL, leadL * 2);
            gp.AddArc(rect, startAngle, sweepAngle);
 
            // Draw the output leads
            gp.AddLine(Loc.X + 3 * leadL, Loc.Y + 30, Loc.X + compL, Loc.Y + 30);
 
            // Draw the component text
            compText = "C = " + this.Value + "pF";
            pt = new Point(Loc.X + 5, Loc.Y);
            gp.AddString(compText, family, fontStyle, emSize, pt, format);
 
            // Set rotation angle
            if (isRotated)
                angle = 90;
            else
                angle = 0;
 
            // Rotate the component by angle deg
            PointF rotatePoint = new PointF(Loc.X + 30, Loc.Y + 30); // Rotate about component center point
            Matrix myMatrix = new Matrix();
            myMatrix.RotateAt(angle, rotatePoint, MatrixOrder.Append);
            gr.Transform = myMatrix;
 
            // Update the bounding box location
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            // Draw the component path
            gr.DrawPath(drawPen, gp);
 
            // Draw the bounding box for debug
            //gr.DrawRectangle(redPen, boundBox);
 
            gp.Dispose();
        }
    }
} 

Microstrip Line Class (MLIN.cs)

// C# Libraries
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace MicrowaveTools.Components.Microstrip
{
    public class MLIN : Comp
    {
        public MLIN()
        {
 
        }
 
        public MLIN(double value, Point pt)
        {
            Loc.X = pt.X;
            Loc.Y = pt.Y;
            Width = 60;
            Height = 60;
            Value = value;
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            Pin = new Point(Loc.X, Loc.Y + 30);
            Pout = new Point(Loc.X + compSize, Loc.Y + 30);
        }
 
        // Let the MLIN draw itself called from the canvas paint event
        public override void Draw(Graphics gr)
        {
            // Component selection
            checkSelect();
            drawSelectRect(gr, new Point(Loc.X, Loc.Y + 30));
            drawSelectRect(gr, new Point(Loc.X + compL - endcap_radius, Loc.Y + 30));
 
            GraphicsPath gp = new GraphicsPath();
 
            Point p1 = Loc;             // Assume p1 is the end of the lead at the output of Pin
            Point p2 = new Point(p1.X + 10, p1.Y);
            Point p3 = new Point(p2.X, p2.Y - 10); // Location of MLIN rectangle
            Point p4 = new Point(p2.X + 40, p2.Y);
            Point p5 = new Point(p4.X + 10, p4.Y);
 
            gp.AddLine(p1, p2);
            gp.AddLine(p4, p5);
            gp.AddRectangle(new Rectangle(p3.X, p3.Y, 40, 20));
 
            // Draw the component text
            compText = "W = " + this.Value + " mils";
            pt = new Point(Loc.X + 5, Loc.Y + 5);
            gp.AddString(compText, family, fontStyle, emSize, pt, format);
 
            // Set rotation angle
            if (isRotated)
                angle = 90;
            else
                angle = 0;
 
            // Rotate the component by angle deg
            PointF rotatePoint = new PointF(Loc.X + 30, Loc.Y + 30); // Rotate about component center point
            Matrix myMatrix = new Matrix();
            myMatrix.RotateAt(angle, rotatePoint, MatrixOrder.Append);
            gr.Transform = myMatrix;
 
            // Update the bounding box location
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            // Draw the component path
            gr.DrawPath(drawPen, gp);
 
            // Draw the bounding box for debug
            //gr.DrawRectangle(redPen, boundBox);
 
            gp.Dispose();
        }
    }
}

Microstirp Cross Class (MCROS.cs)

// C# Libraries
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace MicrowaveTools.Components.Microstrip
{
    public class MCROS : Comp
    {
        Point[] p = new Point[21];
 
        public MCROS()
        {
 
        }
 
        public MCROS(double value, Point pt)
        {
            Loc.X = pt.X;
            Loc.Y = pt.Y;
            Width = 60;
            Height = 60;
            Value = value;
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            Pin = new Point(Loc.X, Loc.Y + 30);
            Pout = new Point(Loc.X + compSize, Loc.Y + 30);
        }
 
        // Let the MCROS draw itself called from the canvas paint event
        public override void Draw(Graphics gr)
        {
            // Component selection
            checkSelect();
            drawSelectRect(gr, new Point(Loc.X, Loc.Y + 30));
            drawSelectRect(gr, new Point(Loc.X + compL - endcap_radius, Loc.Y + 30));
 
            GraphicsPath gp = new GraphicsPath();
 
            p[1] = Loc;            // Assume p1 is the input lead to the left
            p[2] = new Point(p[1].X + 10, p[1].Y);
            p[3] = new Point(p[2].X, p[2].Y - 10);
            p[4] = new Point(p[3].X + 10, p[3].Y);
            p[5] = new Point(p[4].X, p[4].Y - 10);
            p[6] = new Point(p[5].X + 20, p[5].Y);
            p[7] = new Point(p[6].X, p[6].Y + 10);
            p[8] = new Point(p[7].X + 10, p[7].Y);
            p[9] = new Point(p[8].X, p[8].Y + 20);
            p[10] = new Point(p[9].X - 10, p[9].Y);
            p[11] = new Point(p[10].X, p[10].Y + 10);
            p[12] = new Point(p[11].X - 20, p[11].Y);
            p[13] = new Point(p[12].X, p[12].Y - 10);
            p[14] = new Point(p[13].X - 10, p[13].Y);
            p[15] = new Point(p[5].X + 10, p[5].Y - 10);
            p[16] = new Point(p[15].X, p[15].Y + 10);
            p[17] = new Point(p[8].X + 10, p[8].Y + 10);
            p[18] = new Point(p[17].X - 10, p[17].Y);
            p[19] = new Point(p[11].X - 10, p[11].Y + 10);
            p[20] = new Point(p[19].X, p[19].Y - 10);
 
            for (int i = 1; i < 14; i++)
                gp.AddLine(p[i], p[i + 1]);
            gp.AddLine(p[14], p[2]);
            for (int i = 15; i < 21; i += 2)
                gp.AddLine(p[i], p[i + 1]);
 
             // Draw the component text
            compText = "W = " + this.Value + " mils";
            pt = new Point(Loc.X + 5, Loc.Y + 5);
            gp.AddString(compText, family, fontStyle, emSize, pt, format);
 
            // Set rotation angle
            if (isRotated)
                angle = 90;
            else
                angle = 0;
 
            // Rotate the component by angle deg
            PointF rotatePoint = new PointF(Loc.X + 30, Loc.Y + 30); // Rotate about component center point
            Matrix myMatrix = new Matrix();
            myMatrix.RotateAt(angle, rotatePoint, MatrixOrder.Append);
            gr.Transform = myMatrix;
 
            // Update the bounding box location
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            // Draw the component path
            gr.DrawPath(drawPen, gp);
 
            // Draw the bounding box for debug
            //gr.DrawRectangle(redPen, boundBox);
 
            gp.Dispose();
        }
    }
}

Microstrip Tee Class (MTEE)

// C# Libraries
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace MicrowaveTools.Components.Microstrip
{
    public class MTEE : Comp
    {
        public MTEE()
        {
 
        }
 
        public MTEE(double value, Point pt)
        {
            Loc.X = pt.X;
            Loc.Y = pt.Y;
            Width = 60;
            Height = 60;
            Value = value;
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            Pin = new Point(Loc.X, Loc.Y + 30);
            Pout = new Point(Loc.X + compSize, Loc.Y + 30);
        }
 
        // Let the MTEE draw itself called from the canvas paint event
        public override void Draw(Graphics gr)
        {
            // Component selection
            checkSelect();
            drawSelectRect(gr, new Point(Loc.X, Loc.Y + 30));
            drawSelectRect(gr, new Point(Loc.X + compL - endcap_radius, Loc.Y + 30));
 
            GraphicsPath gp = new GraphicsPath();
 
            Point[] p = new Point[21];
            p[1] = Loc;            // Assume p1 is the input lead to the left
            p[2] = new Point(p[1].X + 10, p[1].Y);
            p[3] = new Point(p[2].X, p[2].Y - 10);
            p[4] = new Point(p[3].X + 10, p[3].Y);
            p[5] = new Point(p[4].X, p[4].Y - 10);
            p[6] = new Point(p[5].X + 20, p[5].Y);
            p[7] = new Point(p[6].X, p[6].Y + 10);
            p[8] = new Point(p[7].X + 10, p[7].Y);
            p[9] = new Point(p[8].X, p[8].Y + 20);
            p[14] = new Point(p[9].X - 40, p[9].Y);
            p[15] = new Point(p[5].X + 10, p[5].Y - 10);
            p[16] = new Point(p[15].X, p[15].Y + 10);
            p[17] = new Point(p[8].X + 10, p[8].Y + 10);
            p[18] = new Point(p[17].X - 10, p[17].Y);
 
            for (int i = 1; i < 9; i++)
                gp.AddLine(p[i], p[i + 1]);
            gp.AddLine(p[9], p[14]);
            gp.AddLine(p[14], p[2]);
            for (int i = 15; i < 19; i += 2)
                gp.AddLine(p[i], p[i + 1]);
 
            // Draw the component text
            compText = "W = " + this.Value + " mils";
            pt = new Point(Loc.X + 5, Loc.Y + 5);
            gp.AddString(compText, family, fontStyle, emSize, pt, format);
 
            // Set rotation angle
            if (isRotated)
                angle = 90;
            else
                angle = 0;
 
            // Rotate the component by angle deg
            PointF rotatePoint = new PointF(Loc.X + 30, Loc.Y + 30); // Rotate about component center point
            Matrix myMatrix = new Matrix();
            myMatrix.RotateAt(angle, rotatePoint, MatrixOrder.Append);
            gr.Transform = myMatrix;
 
            // Update the bounding box location
            boundBox = new Rectangle(Loc.X, Loc.Y, Width, Height);
 
            // Draw the component path
            gr.DrawPath(drawPen, gp);
 
            // Draw the bounding box for debug
            //gr.DrawRectangle(redPen, boundBox);
 
            gp.Dispose();
        }
    }
}

Main Form Modifications

Add the attributes from the TestStretchLine Main Form. Keep the Wire NewWire = New Wire(); attribute.

Update the mouse event handlers keeping the line drawing options

  • Mouse down event handler
  • Mouse move event handler
  • Mouse up event handler

Add the following items:

  • Main form keypress event handler
  • Main form keydown event handler
  • confirmDelete() method
  • deleteSelectedComps() method

Add a new button in the Main Menu select panel:
  • Text: Select Mode
  • Name: btnSelect
Add a btnSelect Click event handler:

        private void btnSelect_Click(object sender, EventArgs e)
        {
            isSelectMode = !isSelectMode;
        }

Finally, update the hitTest() method to support the component bounding boxes.

Run the program and test component rotate, select, delete, and wire stretch. The complete source code for this post is available on GitHub.



No comments:

Post a Comment

34-Microwave Tools with Analysis (Series Final Post)

In this final blog post, I have integrated Y-Matrix analysis into the Microwave Tools project. This version has addition Lumped, Ideal, Micr...