From fc59b9cb7b3032cdee5cd8e5961d867291028a29 Mon Sep 17 00:00:00 2001 From: Boris Date: Fri, 2 Aug 2024 14:45:59 +0200 Subject: [PATCH] Adjust namespaces, added path builder --- GdsGenerator/Program.cs | 41 +++- GdsSharp.Lib.Test/VectorExtensionsTests.cs | 84 +++++++ .../Abstractions/GdsStreamOperator.cs | 2 +- GdsSharp.Lib/Binary/GdsBinaryReader.cs | 2 +- GdsSharp.Lib/Binary/GdsBinaryWriter.cs | 2 +- GdsSharp.Lib/Builders/BezierBuilder.cs | 14 +- GdsSharp.Lib/Builders/PathBuilder.cs | 220 ++++++++++++++++++ GdsSharp.Lib/Extensions.cs | 26 ++- GdsSharp.Lib/GdsParser.cs | 4 +- GdsSharp.Lib/GdsSharp.Lib.csproj | 4 + GdsSharp.Lib/GdsTokenWriter.cs | 4 +- GdsSharp.Lib/GdsTokenizer.cs | 4 +- GdsSharp.Lib/GdsWriter.cs | 2 + .../NonTerminals/Abstractions/IGdsElement.cs | 2 +- .../Abstractions/IGdsLayeredElement.cs | 2 +- .../Elements/GdsArrayReferenceElement.cs | 2 +- .../Elements/GdsBoundaryElement.cs | 2 +- .../NonTerminals/Elements/GdsBoxElement.cs | 2 +- .../NonTerminals/Elements/GdsElement.cs | 2 +- .../NonTerminals/Elements/GdsNodeElement.cs | 2 +- .../NonTerminals/Elements/GdsPathElement.cs | 2 +- .../Elements/GdsStructureReferenceElement.cs | 2 +- .../NonTerminals/Elements/GdsTextElement.cs | 2 +- .../Abstractions/IGdsReadableRecord.cs | 2 + .../Terminals/Abstractions/IGdsSimpleRead.cs | 1 + .../Terminals/Abstractions/IGdsSimpleWrite.cs | 1 + .../Abstractions/IGdsWriteableRecord.cs | 2 + .../Terminals/Records/GdsRecordElFlags.cs | 1 + .../Terminals/Records/GdsRecordFonts.cs | 1 + .../Terminals/Records/GdsRecordNoData.cs | 3 +- .../Records/GdsRecordPresentation.cs | 3 +- .../Terminals/Records/GdsRecordRefLibs.cs | 3 +- .../Terminals/Records/GdsRecordSTrans.cs | 3 +- GdsSharp.Lib/Terminals/Records/GdsRecordXy.cs | 3 +- README.md | 48 +++- build/Build.cs | 8 +- 36 files changed, 477 insertions(+), 31 deletions(-) create mode 100644 GdsSharp.Lib.Test/VectorExtensionsTests.cs create mode 100644 GdsSharp.Lib/Builders/PathBuilder.cs diff --git a/GdsGenerator/Program.cs b/GdsGenerator/Program.cs index e0b2a46..7ac6c65 100644 --- a/GdsGenerator/Program.cs +++ b/GdsGenerator/Program.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.Builders; +using System.Numerics; +using GdsSharp.Lib.Builders; using GdsSharp.Lib.NonTerminals; using GdsSharp.Lib.NonTerminals.Elements; @@ -53,7 +54,43 @@ new GdsPoint(-1250, 0) ] } - } + }, + + // Use the path builder to create a path + new PathBuilder( + 100f, + new Vector2(-3100, -3300), + Vector2.UnitX) + // Straight ahead for 2000 units + .Straight(2000) + + // Bend 45 degrees to the left with a radius of 500 units + .BendDeg(-45, 500) + + // Generate shape like <=> + .Straight(100, widthEnd: 250) + .Straight(100) + .Straight(100, widthEnd: 100) + + // Some more bends + .BendDeg(-45, 500) + .Straight(100) + .Straight(200, 250) + .BendDeg(180, 300) + .BendDeg(-180, 300) + + // Example of using a function to change the width + .BendDeg(-180, 900, f => MathF.Cos(f * 50) * 100 + 150) + + // PathBuilder also supports Bézier curves + .Bezier(b => b + .AddPoint(0, 0) + .AddPoint(0, 1000) + .AddPoint(2000, 1000) + .AddPoint(1000, 0), + t => 250 - (250 - 50) * t) + .Straight(800) + .Build() ] }); diff --git a/GdsSharp.Lib.Test/VectorExtensionsTests.cs b/GdsSharp.Lib.Test/VectorExtensionsTests.cs new file mode 100644 index 0000000..baf97ba --- /dev/null +++ b/GdsSharp.Lib.Test/VectorExtensionsTests.cs @@ -0,0 +1,84 @@ +using System.Numerics; + +namespace GdsSharp.Lib.Test; + +[TestFixture] +public class VectorExtensionsTests +{ + private const float TwoPi = 2 * MathF.PI; + + [Test] + public void Rotate_Rotate90Degrees_CorrectResult() + { + var vec = new Vector2(1, 0); + const float radians = MathF.PI / 2; + + var result = vec.Rotate(radians); + + Assert.Multiple(() => + { + Assert.That(result.X, Is.EqualTo(0).Within(1e-6)); // allowing a small tolerance for floating point errors + Assert.That(result.Y, Is.EqualTo(1).Within(1e-6)); + }); + } + + [Test] + public void Rotate_Rotate180Degrees_CorrectResult() + { + var vec = new Vector2(1, 0); + const float radians = MathF.PI; + + var result = vec.Rotate(radians); + + Assert.Multiple(() => + { + Assert.That(result.X, Is.EqualTo(-1).Within(1e-6)); + Assert.That(result.Y, Is.EqualTo(0).Within(1e-6)); + }); + } + + [Test] + public void Rotate_Rotate360Degrees_CorrectResult() + { + var vec = new Vector2(1, 0); + const float radians = 2 * MathF.PI; + + var result = vec.Rotate(radians); + + Assert.Multiple(() => + { + Assert.That(result.X, Is.EqualTo(1).Within(1e-6)); + Assert.That(result.Y, Is.EqualTo(0).Within(1e-6)); + }); + } + + [Test] + public void Angle_VectorAt45Degrees_CorrectResult() + { + var vec = new Vector2(1, 1); + + var result = vec.Angle(); + + Assert.That(result, Is.EqualTo(MathF.PI / 4).Within(1e-6)); + } + + [Test] + public void Angle_VectorAt90Degrees_CorrectResult() + { + var vec = new Vector2(0, 1); + + var result = vec.Angle(); + + Assert.That(result, Is.EqualTo(MathF.PI / 2).Within(1e-6)); + } + + [Test] + public void Angle_VectorAtNegative45Degrees_CorrectResult() + { + var vec = new Vector2(1, -1); + + var result = vec.Angle(); + + Assert.That(result, Is.EqualTo(-MathF.PI / 4).Within(1e-6)); + } +} \ No newline at end of file diff --git a/GdsSharp.Lib/Abstractions/GdsStreamOperator.cs b/GdsSharp.Lib/Abstractions/GdsStreamOperator.cs index 6e92671..f1a15b5 100644 --- a/GdsSharp.Lib/Abstractions/GdsStreamOperator.cs +++ b/GdsSharp.Lib/Abstractions/GdsStreamOperator.cs @@ -3,7 +3,7 @@ using GdsSharp.Lib.Terminals.Abstractions; using GdsSharp.Lib.Terminals.Records; -namespace GdsSharp.Lib; +namespace GdsSharp.Lib.Abstractions; public class GdsStreamOperator { diff --git a/GdsSharp.Lib/Binary/GdsBinaryReader.cs b/GdsSharp.Lib/Binary/GdsBinaryReader.cs index 2b203f1..7ece0b5 100644 --- a/GdsSharp.Lib/Binary/GdsBinaryReader.cs +++ b/GdsSharp.Lib/Binary/GdsBinaryReader.cs @@ -2,7 +2,7 @@ using System.Text; using GdsSharp.Lib.Terminals; -namespace GdsSharp.Lib; +namespace GdsSharp.Lib.Binary; public class GdsBinaryReader : BinaryReader { diff --git a/GdsSharp.Lib/Binary/GdsBinaryWriter.cs b/GdsSharp.Lib/Binary/GdsBinaryWriter.cs index e585f9c..5475368 100644 --- a/GdsSharp.Lib/Binary/GdsBinaryWriter.cs +++ b/GdsSharp.Lib/Binary/GdsBinaryWriter.cs @@ -2,7 +2,7 @@ using System.Text; using GdsSharp.Lib.Terminals; -namespace GdsSharp.Lib; +namespace GdsSharp.Lib.Binary; public class GdsBinaryWriter : BinaryWriter { diff --git a/GdsSharp.Lib/Builders/BezierBuilder.cs b/GdsSharp.Lib/Builders/BezierBuilder.cs index 7ee95aa..ff17132 100644 --- a/GdsSharp.Lib/Builders/BezierBuilder.cs +++ b/GdsSharp.Lib/Builders/BezierBuilder.cs @@ -147,7 +147,12 @@ public GdsElement BuildPolygon(int width, int numVertices = 64) } } - private Vector2 Evaluate(float t) + /// + /// Evaluates the Bézier curve at a given t. + /// + /// [0,1] + /// Position on the curve at . + public Vector2 Evaluate(float t) { var n = _controlPoints.Count - 1; var x = 0.0f; @@ -162,7 +167,12 @@ private Vector2 Evaluate(float t) return new Vector2(x, y); } - private Vector2 EvaluateTangent(float t) + /// + /// Evaluates the tangent of the Bézier curve at a given t. + /// + /// [0,1] + /// Tangent vector of the curve at . + public Vector2 EvaluateTangent(float t) { var n = _controlPoints.Count - 1; var nMinusOne = n - 1; diff --git a/GdsSharp.Lib/Builders/PathBuilder.cs b/GdsSharp.Lib/Builders/PathBuilder.cs new file mode 100644 index 0000000..82f43b8 --- /dev/null +++ b/GdsSharp.Lib/Builders/PathBuilder.cs @@ -0,0 +1,220 @@ +using System.Numerics; +using GdsSharp.Lib.NonTerminals; +using GdsSharp.Lib.NonTerminals.Elements; +using SoftCircuits.Collections; + +namespace GdsSharp.Lib.Builders; + +public class PathBuilder +{ + private readonly Vector2 _initialHeading; + private readonly Vector2 _initialPosition; + private readonly float _initialWidth; + private readonly List _pathSegments = new(); + + public PathBuilder(float initialWidth, Vector2? initialPosition = null, Vector2? initialHeading = null) + { + _initialWidth = initialWidth; + _initialPosition = initialPosition ?? Vector2.Zero; + _initialHeading = initialHeading ?? Vector2.UnitY; + } + + /// + /// Adds a path segment to the path. + /// + /// Function that returns the coordinates of the path. + /// Function that returns derivative vectors of the path. + /// + /// Function that returns the width of the path. Can be null or return null, in this case the last + /// available width will be used. + /// + /// Number of vertices used for the path. The final mesh will have two times this amount. + public PathBuilder AddPathSegment(Func path, Func derivative, Func? width = null, int vertices = 10) + { + _pathSegments.Add(new PathSegment(path, derivative, width, vertices)); + return this; + } + + /// + /// Adds a straight segment to the path. + /// If is provided it takes precedence over and . + /// If only is provided the width will be interpolated between the previous width and + /// . + /// + /// Length of the segment. + /// (optional) Width at the start of the segment. + /// (optional) Width at the end of the segment. + /// (optional) Function that provides a width for t on the interval [0,1]. + /// (optional) Number of vertices used for the path. Increase this if using . + public PathBuilder Straight(int length, float? widthStart = null, float? widthEnd = null, Func? width = null, int vertices = 2) + { + width ??= t => t < 0.5f ? widthStart : widthEnd; + + return AddPathSegment( + t => new Vector2(0, t * length), + _ => new Vector2(0, 1), + width, + vertices); + } + + /// + /// Adds a bend to the path. + /// + /// Angle of the bend in radians. + /// Radius of the bend. + /// (optional) Function that provides a width for t on the interval [0,1]. + /// (optional) Number of vertices used for the path. + public PathBuilder BendRad(float angle, int radius, Func? width = null, int vertices = 128) + { + var sign = Math.Sign(angle); + angle = MathF.Abs(angle); + var phase = sign == -1 ? MathF.PI : 0; + + return AddPathSegment( + t => new Vector2( + radius * (1 - MathF.Cos(t * angle)) * sign, + radius * MathF.Sin(t * angle) + ), + t => new Vector2( + angle * radius * MathF.Sin(t * angle + phase), + angle * radius * MathF.Cos(t * angle) + ), + t => width?.Invoke(t), + vertices); + } + + /// + /// Adds a bend to the path. + /// + /// Angle of the bend in degrees. + /// Radius of the bend. + /// (optional) Function that provides a width for t on the interval [0,1]. + /// (optional) Number of vertices used for the path. + public PathBuilder BendDeg(float angle, int radius, Func? width = null, int vertices = 128) + { + angle = MathF.PI * angle / 180; + return BendRad(angle, radius, width, vertices); + } + + /// + /// Adds a Bézier curve to the path. + /// + /// Bézier builder where you can add control points. + /// (optional) Function that provides a width for t on the interval [0,1]. + /// (optional) Number of vertices used for the path. + public PathBuilder Bezier(Action build, Func? width = null, int vertices = 128) + { + var builder = new BezierBuilder(); + build(builder); + + return AddPathSegment( + t => builder.Evaluate(t), + t => builder.EvaluateTangent(t), // It works like this without rotation for some reason + t => width?.Invoke(t), + vertices); + } + + /// + /// Builds the path into a GdsElement. + /// + /// GdsBoundaryElement. + public GdsElement Build() + { + return new GdsElement + { + Element = new GdsBoundaryElement + { + Points = GetPolygonPoints().ToList() + } + }; + } + + /// + /// Builds a polygon from the path. + /// + /// + private IEnumerable GetPolygonPoints() + { + var segments = GetPathPoints(); + + List meshUp = new(); + List meshDown = new(); + + foreach (var (_, points) in segments) + foreach (var (point, normal, width) in points) + { + meshUp.Add(new GdsPoint(point + normal * width / 2)); + meshDown.Insert(0, new GdsPoint(point - normal * width / 2)); + } + + return meshUp.Concat(meshDown); + } + + /// + /// Generates a list of points for each segment in the path. + /// + /// List of points per segment. + private OrderedDictionary> GetPathPoints() + { + var points = new OrderedDictionary>(); + var position = _initialPosition; + var heading = _initialHeading; + var currentWidth = _initialWidth; + + foreach (var segment in _pathSegments) + { + var segmentPoints = new List(); + + Vector2? lastPosition = null; + Vector2? lastHeading = null; + + for (var i = 0; i <= segment.Vertices; i++) + { + var t = i / (float)segment.Vertices; + + // Get data from this point + var point = segment.Path(t); + var derivative = Vector2.Normalize(segment.Derivative(t)); + var width = segment.Width?.Invoke(t); + + // Correct the point and derivative for the heading + var rotationAngle = Vector2.UnitY.Angle() - heading.Angle(); + point = point.Rotate(-rotationAngle); + derivative = derivative.Rotate(-rotationAngle); + + lastHeading = derivative; + lastPosition = point; + currentWidth = width ?? currentWidth; + + var normal = new Vector2(-derivative.Y, derivative.X); + segmentPoints.Add(new PathPoint(point + position, normal, currentWidth)); + } + + if (lastPosition.HasValue) + position += lastPosition.Value; + if (lastHeading.HasValue) + heading = lastHeading.Value; + + points.Add(segment, segmentPoints); + } + + return points; + } + + /// + /// Represents a path segment. + /// + /// Function that defines the path of the segment. + /// Function that defines the derivative of the segment. + /// Function that defines the width of the segment. + /// Number of vertices of the segment. + private record struct PathSegment(Func Path, Func Derivative, Func? Width, int Vertices); + + /// + /// Represents a single point in the path. + /// + /// The coordinates of the point. + /// The normal of the point. + /// The width at the point. + private record struct PathPoint(Vector2 Point, Vector2 Normal, float Width); +} \ No newline at end of file diff --git a/GdsSharp.Lib/Extensions.cs b/GdsSharp.Lib/Extensions.cs index aa3b722..96e7bed 100644 --- a/GdsSharp.Lib/Extensions.cs +++ b/GdsSharp.Lib/Extensions.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.NonTerminals; +using System.Numerics; +using GdsSharp.Lib.NonTerminals; namespace GdsSharp.Lib; @@ -13,4 +14,27 @@ public static List AsGdsPoints(this List<(int x, int y)> coordinates) { return coordinates.ConvertAll(c => (c.X, c.Y)); } + + /// + /// Rotates a vector by the given angle in radians. + /// + /// Vector to rotate. + /// Angle to rotate by. + /// Rotated vector. + public static Vector2 Rotate(this Vector2 vec, float radians) + { + var ca = MathF.Cos(radians); + var sa = MathF.Sin(radians); + return new Vector2(ca * vec.X - sa * vec.Y, sa * vec.X + ca * vec.Y); + } + + /// + /// Gets the angle of a vector in radians. + /// + /// Vector. + /// Angle of the vector in radians. + public static float Angle(this Vector2 vec) + { + return MathF.Atan2(vec.Y, vec.X); + } } \ No newline at end of file diff --git a/GdsSharp.Lib/GdsParser.cs b/GdsSharp.Lib/GdsParser.cs index db1820c..bd280f4 100644 --- a/GdsSharp.Lib/GdsParser.cs +++ b/GdsSharp.Lib/GdsParser.cs @@ -1,5 +1,5 @@ -using GdsSharp.Lib.Abstractions; -using GdsSharp.Lib.NonTerminals; +using GdsSharp.Lib.NonTerminals; +using GdsSharp.Lib.NonTerminals.Abstractions; using GdsSharp.Lib.NonTerminals.Elements; using GdsSharp.Lib.NonTerminals.Enum; using GdsSharp.Lib.Terminals.Abstractions; diff --git a/GdsSharp.Lib/GdsSharp.Lib.csproj b/GdsSharp.Lib/GdsSharp.Lib.csproj index 4ec294c..b0ca84d 100644 --- a/GdsSharp.Lib/GdsSharp.Lib.csproj +++ b/GdsSharp.Lib/GdsSharp.Lib.csproj @@ -29,4 +29,8 @@ + + + + diff --git a/GdsSharp.Lib/GdsTokenWriter.cs b/GdsSharp.Lib/GdsTokenWriter.cs index ae03fcd..9d83c54 100644 --- a/GdsSharp.Lib/GdsTokenWriter.cs +++ b/GdsSharp.Lib/GdsTokenWriter.cs @@ -1,5 +1,5 @@ -using GdsSharp.Lib.Abstractions; -using GdsSharp.Lib.NonTerminals; +using GdsSharp.Lib.NonTerminals; +using GdsSharp.Lib.NonTerminals.Abstractions; using GdsSharp.Lib.NonTerminals.Elements; using GdsSharp.Lib.NonTerminals.Enum; using GdsSharp.Lib.Terminals.Abstractions; diff --git a/GdsSharp.Lib/GdsTokenizer.cs b/GdsSharp.Lib/GdsTokenizer.cs index 976c8b3..568f968 100644 --- a/GdsSharp.Lib/GdsTokenizer.cs +++ b/GdsSharp.Lib/GdsTokenizer.cs @@ -1,4 +1,6 @@ -using GdsSharp.Lib.Terminals; +using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.Binary; +using GdsSharp.Lib.Terminals; using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib; diff --git a/GdsSharp.Lib/GdsWriter.cs b/GdsSharp.Lib/GdsWriter.cs index 378acfc..830e68f 100644 --- a/GdsSharp.Lib/GdsWriter.cs +++ b/GdsSharp.Lib/GdsWriter.cs @@ -1,3 +1,5 @@ +using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.Binary; using GdsSharp.Lib.Terminals; using GdsSharp.Lib.Terminals.Abstractions; diff --git a/GdsSharp.Lib/NonTerminals/Abstractions/IGdsElement.cs b/GdsSharp.Lib/NonTerminals/Abstractions/IGdsElement.cs index 0888081..10e5f28 100644 --- a/GdsSharp.Lib/NonTerminals/Abstractions/IGdsElement.cs +++ b/GdsSharp.Lib/NonTerminals/Abstractions/IGdsElement.cs @@ -1,4 +1,4 @@ -namespace GdsSharp.Lib.Abstractions; +namespace GdsSharp.Lib.NonTerminals.Abstractions; public interface IGdsElement { diff --git a/GdsSharp.Lib/NonTerminals/Abstractions/IGdsLayeredElement.cs b/GdsSharp.Lib/NonTerminals/Abstractions/IGdsLayeredElement.cs index a2508f8..4acabc7 100644 --- a/GdsSharp.Lib/NonTerminals/Abstractions/IGdsLayeredElement.cs +++ b/GdsSharp.Lib/NonTerminals/Abstractions/IGdsLayeredElement.cs @@ -1,4 +1,4 @@ -namespace GdsSharp.Lib.Abstractions; +namespace GdsSharp.Lib.NonTerminals.Abstractions; public interface IGdsLayeredElement : IGdsElement { diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsArrayReferenceElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsArrayReferenceElement.cs index 2c4f376..fb0baf2 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsArrayReferenceElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsArrayReferenceElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsBoundaryElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsBoundaryElement.cs index 352f82e..fc38f88 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsBoundaryElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsBoundaryElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsBoxElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsBoxElement.cs index f92fcaf..ce8e6d6 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsBoxElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsBoxElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsElement.cs index 95817ab..65af966 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsNodeElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsNodeElement.cs index 76c5484..ae645d2 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsNodeElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsNodeElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsPathElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsPathElement.cs index bee0196..158a479 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsPathElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsPathElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; using GdsSharp.Lib.NonTerminals.Enum; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsStructureReferenceElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsStructureReferenceElement.cs index 3102e81..8bd2bf0 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsStructureReferenceElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsStructureReferenceElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/NonTerminals/Elements/GdsTextElement.cs b/GdsSharp.Lib/NonTerminals/Elements/GdsTextElement.cs index 82512fc..23325cf 100644 --- a/GdsSharp.Lib/NonTerminals/Elements/GdsTextElement.cs +++ b/GdsSharp.Lib/NonTerminals/Elements/GdsTextElement.cs @@ -1,4 +1,4 @@ -using GdsSharp.Lib.Abstractions; +using GdsSharp.Lib.NonTerminals.Abstractions; using GdsSharp.Lib.NonTerminals.Enum; namespace GdsSharp.Lib.NonTerminals.Elements; diff --git a/GdsSharp.Lib/Terminals/Abstractions/IGdsReadableRecord.cs b/GdsSharp.Lib/Terminals/Abstractions/IGdsReadableRecord.cs index e820ee6..aa836c2 100644 --- a/GdsSharp.Lib/Terminals/Abstractions/IGdsReadableRecord.cs +++ b/GdsSharp.Lib/Terminals/Abstractions/IGdsReadableRecord.cs @@ -1,3 +1,5 @@ +using GdsSharp.Lib.Binary; + namespace GdsSharp.Lib.Terminals.Abstractions; public interface IGdsReadableRecord : IGdsRecord diff --git a/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleRead.cs b/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleRead.cs index c665783..6dc935e 100644 --- a/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleRead.cs +++ b/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleRead.cs @@ -1,4 +1,5 @@ using System.Reflection; +using GdsSharp.Lib.Binary; namespace GdsSharp.Lib.Terminals.Abstractions; diff --git a/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleWrite.cs b/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleWrite.cs index eb7daf9..3d63141 100644 --- a/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleWrite.cs +++ b/GdsSharp.Lib/Terminals/Abstractions/IGdsSimpleWrite.cs @@ -1,4 +1,5 @@ using System.Reflection; +using GdsSharp.Lib.Binary; namespace GdsSharp.Lib.Terminals.Abstractions; diff --git a/GdsSharp.Lib/Terminals/Abstractions/IGdsWriteableRecord.cs b/GdsSharp.Lib/Terminals/Abstractions/IGdsWriteableRecord.cs index 7b54ada..04187f4 100644 --- a/GdsSharp.Lib/Terminals/Abstractions/IGdsWriteableRecord.cs +++ b/GdsSharp.Lib/Terminals/Abstractions/IGdsWriteableRecord.cs @@ -1,3 +1,5 @@ +using GdsSharp.Lib.Binary; + namespace GdsSharp.Lib.Terminals.Abstractions; public interface IGdsWriteableRecord : IGdsRecord diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordElFlags.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordElFlags.cs index 88d40f6..11fa714 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordElFlags.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordElFlags.cs @@ -1,3 +1,4 @@ +using GdsSharp.Lib.Binary; using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordFonts.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordFonts.cs index d0b4e75..af47399 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordFonts.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordFonts.cs @@ -1,3 +1,4 @@ +using GdsSharp.Lib.Binary; using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordNoData.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordNoData.cs index 986bf87..e4030ed 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordNoData.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordNoData.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.Terminals.Abstractions; +using GdsSharp.Lib.Binary; +using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordPresentation.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordPresentation.cs index 23c393f..545df40 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordPresentation.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordPresentation.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.Terminals.Abstractions; +using GdsSharp.Lib.Binary; +using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordRefLibs.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordRefLibs.cs index 43f6865..d89a9b9 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordRefLibs.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordRefLibs.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.Terminals.Abstractions; +using GdsSharp.Lib.Binary; +using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordSTrans.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordSTrans.cs index 1062f36..6a4dafa 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordSTrans.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordSTrans.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.Terminals.Abstractions; +using GdsSharp.Lib.Binary; +using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/GdsSharp.Lib/Terminals/Records/GdsRecordXy.cs b/GdsSharp.Lib/Terminals/Records/GdsRecordXy.cs index 18958b8..304b73e 100644 --- a/GdsSharp.Lib/Terminals/Records/GdsRecordXy.cs +++ b/GdsSharp.Lib/Terminals/Records/GdsRecordXy.cs @@ -1,4 +1,5 @@ -using GdsSharp.Lib.Terminals.Abstractions; +using GdsSharp.Lib.Binary; +using GdsSharp.Lib.Terminals.Abstractions; namespace GdsSharp.Lib.Terminals.Records; diff --git a/README.md b/README.md index 742e459..bee9432 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [![NuGet](https://img.shields.io/nuget/v/GdsSharp.svg)](https://www.nuget.org/packages/GdsSharp/)\ A library for reading, editing, and writing [Calma GDSII](https://en.wikipedia.org/wiki/GDSII) files. -Some helpers are also provided for drawing curves like circles and Bézier curves. +Some helpers are also provided for drawing shapes like circles and Bézier curves. +Additionally, a path builder is included to create parameterized paths with multiple segments. ## Usage @@ -26,7 +27,7 @@ file.WriteTo(fileStream); An example of how to create a GDS file from scratch and creating some shapes using the helpers can be found in the [example project](https://github.com/BorisGerretzen/GdsSharp/blob/master/GdsGenerator/Program.cs). This is the created GDS file: -![image](https://github.com/user-attachments/assets/0e0e524f-129d-433f-b560-626846b6e991) +![image](https://github.com/user-attachments/assets/6629195b-64e3-4778-87e7-d8cae87826d7) ## Helpers @@ -70,6 +71,49 @@ var elemLine = new BezierBuilder() .BuildLine(width: 200, numVertices: 128); ``` +### Path builder + +GdsSharp also includes a path builder that can be used to create paths with multiple segments. +The output of this code can be seen on the bottom part of the picture above. + +```csharp +// Use the path builder to create a path +new PathBuilder( + initialWidth: 100f, + initialPosition: new Vector2(-3100, -3300), + initialHeading: Vector2.UnitX) + // Straight ahead for 2000 units + .Straight(2000) + + // Bend 45 degrees to the left with a radius of 500 units + .BendDeg(-45, 500) + + // Generate shape like <=> + .Straight(100, widthEnd: 250) + .Straight(100) + .Straight(100, widthEnd: 100) + + // Some more bends + .BendDeg(-45, 500) + .Straight(100) + .Straight(200, widthStart: 250) + .BendDeg(180, 300) + .BendDeg(-180, 300) + + // Example of using a function to change the width + .BendDeg(-180, 900, f => MathF.Cos(f * 50) * 100 + 150) + + // PathBuilder also supports Bézier curves + .Bezier(b => b + .AddPoint(0, 0) + .AddPoint(0,1000) + .AddPoint(2000, 1000) + .AddPoint(1000, 0), + width: t => 250 - (250-50) * t) + .Straight(800) + .Build(); +``` + ## Missing features I have not implemented all features of the GDSii spec, some terminals diff --git a/build/Build.cs b/build/Build.cs index 12eb3e5..dd49c08 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -134,7 +134,13 @@ from framework in project.GetTargetFrameworks() .SetTargetPath(v) ) ); - Git($"push --set-upstream origin {PackageVersion ?? GitVersion.NuGetVersionV2}"); + + var version = PackageVersion ?? GitVersion.NuGetVersionV2; + + Git("config --global user.email \"<>\""); + Git("config --global user.name \"GitHub Actions\""); + Git($"tag -a {version} -m \"Created release '{version}'\""); + Git($"push --tags"); }); public static int Main() => Execute(x => x.Test);