commit 3ef94813ace90f9ed313680c1a45aa1362665a53 Author: AJ Date: Fri Sep 6 17:28:34 2019 -0400 First commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a5f80a --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ + +#Ignore thumbnails created by Windows +Thumbs.db +#Ignore files built by Visual Studio +*.obj +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.cache +*.ilk +*.log +[Bb]in +[Dd]ebug*/ +*.lib +*.sbr +obj/ +[Rr]elease*/ +_ReSharper*/ +[Tt]est[Rr]esult* +.vs/ +#Nuget packages folder +packages/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..523f392 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "netDxf"] + path = netDxf + url = https://github.com/haplokuon/netDxf.git diff --git a/EtchBendLines.sln b/EtchBendLines.sln new file mode 100644 index 0000000..44987de --- /dev/null +++ b/EtchBendLines.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29123.88 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EtchBendLines", "EtchBendLines\EtchBendLines.csproj", "{229C2FB9-6AD6-4A5D-B83A-D1146573D6F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "netDxf", "netDxf\netDxf\netDxf.csproj", "{785380E0-CEB9-4C34-82E5-60D0E33E848E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {229C2FB9-6AD6-4A5D-B83A-D1146573D6F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {229C2FB9-6AD6-4A5D-B83A-D1146573D6F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {229C2FB9-6AD6-4A5D-B83A-D1146573D6F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {229C2FB9-6AD6-4A5D-B83A-D1146573D6F9}.Release|Any CPU.Build.0 = Release|Any CPU + {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4EF8ADDD-D992-4DED-BB58-F4DC0F53A4A3} + EndGlobalSection +EndGlobal diff --git a/EtchBendLines/App.config b/EtchBendLines/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/EtchBendLines/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/EtchBendLines/Bend.cs b/EtchBendLines/Bend.cs new file mode 100644 index 0000000..0eb3a35 --- /dev/null +++ b/EtchBendLines/Bend.cs @@ -0,0 +1,150 @@ +using netDxf; +using netDxf.Entities; +using netDxf.Tables; +using System; +using System.Collections.Generic; + +namespace EtchBendLine +{ + public class Bend + { + const double RadPerDeg = Math.PI / 180.0; + + public Line Line { get; set; } + + public double YIntercept + { + get { return Line.YIntercept(); } + } + + public double Slope + { + get { return Line.Slope(); } + } + + public bool IsVertical + { + get { return Line.IsVertical(); } + } + + public bool IsHorizontal + { + get { return Line.IsHorizontal(); } + } + + public bool IsCollinearTo(Bend bend) + { + if (bend.IsVertical || this.IsVertical) + return (bend.IsVertical && this.IsVertical && bend.YIntercept == this.YIntercept); + + if (bend.YIntercept != this.YIntercept) + return false; + + return bend.Slope == this.Slope; + } + + public List GetEtchLines(double etchLength) + { + var lines = new List(); + + var etchLayer = new Layer("ETCH") + { + Color = AciColor.Green, + }; + + var startPoint = new Vector2(Line.StartPoint.X, Line.StartPoint.Y); + var endPoint = new Vector2(Line.EndPoint.X, Line.EndPoint.Y); + var bendLength = startPoint.DistanceTo(endPoint); + + if (bendLength < (etchLength * 3.0)) + { + var fullLengthLine = new Line(Line.StartPoint, Line.EndPoint) + { + Layer = etchLayer + }; + + lines.Add(fullLengthLine); + + return lines; + } + else + { + var angle = startPoint.AngleTo(endPoint); + + if (Line.IsVertical()) + { + var x = Line.StartPoint.X; + + var bottomY1 = Line.StartPoint.Y < Line.EndPoint.Y ? Line.StartPoint.Y : Line.EndPoint.Y; + var bottomY2 = bottomY1 + etchLength; + + var topY1 = Line.StartPoint.Y > Line.EndPoint.Y ? Line.StartPoint.Y : Line.EndPoint.Y; + var topY2 = topY1 - etchLength; + + var p1 = new Vector2(x, bottomY1); + var p2 = new Vector2(x, bottomY2); + + var p3 = new Vector2(x, topY1); + var p4 = new Vector2(x, topY2); + + var bottomPoint = Line.StartPoint.Y < Line.EndPoint.Y ? Line.StartPoint : Line.EndPoint; + var bottomOffsetPoint = new Vector2(bottomPoint.X, bottomPoint.Y + etchLength); + + var line1 = new Line(p1, p2) + { + Layer = etchLayer + }; + + var line2 = new Line(p3, p4) + { + Layer = etchLayer + }; + + lines.Add(line1); + lines.Add(line2); + } + else + { + var start = Line.StartPoint.ToVector2(); + var end = Line.EndPoint.ToVector2(); + + var x1 = Math.Cos(angle); + var y1 = Math.Sin(angle); + + var p1 = new Vector2(start.X, start.Y); + var p2 = new Vector2(start.X + x1, start.Y + y1); + + var p3 = new Vector2(end.X, end.Y); + var p4 = new Vector2(end.X - x1, end.Y - y1); + + var line1 = new Line(p1, p2) + { + Layer = etchLayer + }; + + var line2 = new Line(p3, p4) + { + Layer = etchLayer + }; + + lines.Add(line1); + lines.Add(line2); + } + } + + return lines; + } + + public BendDirection Direction { get; set; } + + public double Length + { + get + { + var x = Line.EndPoint.X - Line.StartPoint.X; + var y = Line.EndPoint.Y - Line.StartPoint.Y; + return Math.Sqrt(x * x + y * y); + } + } + } +} diff --git a/EtchBendLines/BendDirection.cs b/EtchBendLines/BendDirection.cs new file mode 100644 index 0000000..79f5701 --- /dev/null +++ b/EtchBendLines/BendDirection.cs @@ -0,0 +1,9 @@ +namespace EtchBendLine +{ + public enum BendDirection + { + Up, + Down, + Unknown + } +} diff --git a/EtchBendLines/EtchBendLines.csproj b/EtchBendLines/EtchBendLines.csproj new file mode 100644 index 0000000..ce6369c --- /dev/null +++ b/EtchBendLines/EtchBendLines.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + {229C2FB9-6AD6-4A5D-B83A-D1146573D6F9} + Exe + EtchBendLine + EtchBendLine + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + {785380e0-ceb9-4c34-82e5-60d0e33e848e} + netDxf + + + + \ No newline at end of file diff --git a/EtchBendLines/Extensions.cs b/EtchBendLines/Extensions.cs new file mode 100644 index 0000000..ffc2413 --- /dev/null +++ b/EtchBendLines/Extensions.cs @@ -0,0 +1,102 @@ +using netDxf; +using netDxf.Entities; +using System; + +namespace EtchBendLine +{ + public static class Extensions + { + const double TwoPI = Math.PI * 2.0; + + public static Vector2 ToVector2(this Vector3 pt) + { + return new Vector2(pt.X, pt.Y); + } + + public static bool IsVertical(this Line line) + { + return line.StartPoint.X == line.EndPoint.X; + } + + public static bool IsHorizontal(this Line line) + { + return line.StartPoint.Y == line.EndPoint.Y; + } + + public static double Slope(this Line line) + { + if (line.IsVertical()) + return double.NaN; + + var p1 = line.StartPoint; + var p2 = line.EndPoint; + + return Math.Round((p2.Y - p1.Y) / (p2.X - p1.X), 4); + } + + public static double YIntercept(this Line line) + { + var p1 = line.StartPoint; + var p2 = line.EndPoint; + var slope = line.Slope(); + + // y = mx + b + + return Math.Round(p1.Y - slope * p1.X, 4); + } + + public static Vector2 PointPerpendicularTo(this Line line, Vector2 pt) + { + var startPoint = line.StartPoint.ToVector2(); + var endPoint = line.EndPoint.ToVector2(); + + var d1 = pt - startPoint; + var d2 = endPoint - startPoint; + var dotProduct = d1.X * d2.X + d1.Y * d2.Y; + var lengthSquared = d2.X * d2.X + d2.Y * d2.Y; + var param = dotProduct / lengthSquared; + + if (param < 0) + return startPoint; + else if (param > 1) + return endPoint; + else + { + return new Vector2( + startPoint.X + param * d2.X, + startPoint.Y + param * d2.Y); + } + } + + public static Vector2 MidPoint(this Line line) + { + var x = (line.StartPoint.X + line.EndPoint.X) * 0.5; + var y = (line.StartPoint.Y + line.EndPoint.Y) * 0.5; + + return new Vector2(x, y); + } + + public static double DistanceTo(this Vector2 startPoint, Vector2 endPoint) + { + var x = endPoint.X - startPoint.X; + var y = endPoint.Y - startPoint.Y; + + return Math.Sqrt(x * x + y * y); + } + + public static double AngleTo(this Vector2 startPoint, Vector2 endPoint) + { + var x = endPoint.X - startPoint.X; + var y = endPoint.Y - startPoint.Y; + + return NormalizeRad(Math.Atan2(y, x)); + } + + + static double NormalizeRad(double angle) + { + double r = angle % TwoPI; + return r < 0 ? TwoPI + r : r; + } + } +} diff --git a/EtchBendLines/Program.cs b/EtchBendLines/Program.cs new file mode 100644 index 0000000..2f0fc89 --- /dev/null +++ b/EtchBendLines/Program.cs @@ -0,0 +1,266 @@ +using netDxf; +using netDxf.Entities; +using netDxf.Tables; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EtchBendLine +{ + class Program + { + const double ETCH_LENGTH = 1.0; + + static Layer BendLayer = new Layer("BEND") + { + Color = AciColor.Yellow + }; + + static void Main(string[] args) + { + var path = AppDomain.CurrentDomain.BaseDirectory; + var files = Directory.GetFiles(path, "*.dxf", SearchOption.AllDirectories); + + if (files == null || files.Length == 0) + { + Console.WriteLine($"No DXF files founds. Place DXF files in \"{AppDomain.CurrentDomain.BaseDirectory}\" and run this program again."); + PressAnyKeyToExit(); + return; + } + + foreach (var file in files) + { + AddEtchLines(file); + Console.WriteLine("----------------------------------------------------------------"); + + } + + PressAnyKeyToExit(); + } + + static void PressAnyKeyToExit() + { + Console.WriteLine("Press any key to exit."); + Console.ReadKey(); + } + + static void AddEtchLines(string filePath) + { + var name = Path.GetFileNameWithoutExtension(filePath); + Console.WriteLine($"Adding etch lines to file \"{name}\""); + + var dxf = LoadDoc(filePath); + var bendLines = GetBendLines(dxf); + var bendNotes = GetBendNotes(dxf); + + if (bendLines.Count == 0) + { + Console.WriteLine("No bend lines found."); + return; + } + else + { + Console.WriteLine($"Found {bendLines.Count} bend lines."); + } + + if (bendNotes.Count == 0) + { + Console.WriteLine("No bend notes found."); + return; + } + else + { + Console.WriteLine($"Found {bendNotes.Count} bend notes."); + } + + foreach (var bendLine in bendLines) + { + bendLine.Line.Layer = BendLayer; + bendLine.Line.Color = AciColor.ByLayer; + } + + foreach (var note in bendNotes) + { + note.Layer = BendLayer; + } + + AssignBendDirections(bendLines, bendNotes); + + var upBends = bendLines.Where(b => b.Direction == BendDirection.Up); + + Console.WriteLine($"{upBends.Count()} up bends, {bendLines.Count - upBends.Count()} down bends."); + + foreach (var bendline in upBends) + { + var etchLines = bendline.GetEtchLines(ETCH_LENGTH); + dxf.AddEntity(etchLines); + } + + dxf.Save(filePath); + } + + static void AssignBendDirections(IEnumerable bendlines, IEnumerable bendNotes) + { + foreach (var bendline in bendlines) + { + var bendNote = FindBendNote(bendline.Line, bendNotes); + + if (bendNote == null) + continue; + + bendNote.Layer = BendLayer; + + var note = bendNote.Value.ToUpper(); + + if (note.Contains("UP")) + bendline.Direction = BendDirection.Up; + + else if (note.Contains("DOWN") || note.Contains("DN")) + bendline.Direction = BendDirection.Down; + } + } + + //static MText FindBendNote(Line bendLine, IEnumerable bendNotes) + // { + // var startPoint = new Vector2(bendLine.StartPoint.X, bendLine.StartPoint.Y); + // var endPoint = new Vector2(bendLine.EndPoint.X, bendLine.EndPoint.Y); + // var angle = startPoint.AngleTo(endPoint); + + // if (angle >= 180.0) + // angle -= 180.0; + + // const double ANGLE_TOLERANCE = 0.001; + + // var bendNotesWithSameAngle = bendNotes.Where(n => Math.Abs(n.Rotation - angle) < ANGLE_TOLERANCE).ToList(); + + // var midPoint = bendLine.MidPoint(); + + // MText closestNote = bendNotes.First(); + // Vector2 closestPoint = closestNote.Position.ToVector2(); + + + + // foreach (var note in bendNotes) + // { + // var pt = note.Position.ToVector2(); + // var dist = midPoint.DistanceTo(pt); + + // if (dist < distance) + // { + // closestNote = note; + // distance = dist; + // closestPoint = pt; + // } + // } + + // var distToBendNote = closestNote.Position.ToVector2().DistanceTo(midPoint); + + // if (distToBendNote > 18) + // return null; + + // return closestNote; + // } + + static MText FindBendNote(Line bendLIne, IEnumerable bendNotes) + { + var list = bendNotes.ToList(); + var shortestDist = double.MaxValue; + var shortestDistIndex = -1; + + for (int i = 0; i < list.Count; i++) + { + var note = list[i]; + var notePos = note.Position.ToVector2(); + var perpendicularPoint = bendLIne.PointPerpendicularTo(notePos); + var dist = notePos.DistanceTo(perpendicularPoint); + + if (dist < shortestDist) + { + shortestDistIndex = i; + shortestDist = dist; + } + } + + if (shortestDistIndex == -1) + return null; + + var bendNote = list[shortestDistIndex]; + var maxAcceptableDist = bendNote.Height * 2.0; + + if (shortestDist > maxAcceptableDist) + return null; + + return bendNote; + } + + static Vector2? FindClosestPoint(Vector2 originPoint, List pts) + { + if (pts == null || pts.Any() == false) + return null; + + var closest = pts[0]; + var distance = originPoint.DistanceTo(closest); + + for (int i = 1; i < pts.Count; i++) + { + var pt = pts[i]; + var dist = originPoint.DistanceTo(pt); + + if (dist < distance) + { + distance = dist; + closest = pts[i]; + } + } + + return closest; + } + + static DxfDocument LoadDoc(string file) + { + return DxfDocument.Load(file); + } + + static List GetBendLines(DxfDocument dxf) + { + var bends = new List(); + + foreach (var line in dxf.Lines) + { + if (line.Linetype.Name != "CENTERX2" && line.Layer.Name != "BEND") + continue; + + var bend = new Bend + { + Line = line, + Direction = BendDirection.Unknown + }; + + + bends.Add(bend); + } + + return bends; + } + + static List GetBendNotes(DxfDocument dxf) + { + var bendNotes = new List(); + + foreach (var text in dxf.MTexts) + { + var textAsUpper = text.Value.ToUpper(); + + if (textAsUpper.Contains("UP") || textAsUpper.Contains("DOWN")) + { + bendNotes.Add(text); + } + } + + return bendNotes; + } + } +} diff --git a/EtchBendLines/Properties/AssemblyInfo.cs b/EtchBendLines/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d76633c --- /dev/null +++ b/EtchBendLines/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("EtchBendLine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EtchBendLine")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("229c2fb9-6ad6-4a5d-b83a-d1146573d6f9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/netDxf b/netDxf new file mode 160000 index 0000000..67789bf --- /dev/null +++ b/netDxf @@ -0,0 +1 @@ +Subproject commit 67789bfe700b9ef2d66457030b6500c33beeb249