Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5bd4c89999 | |||
| dd93c230dd | |||
| d6ffd8efc9 | |||
| 68c3a904e8 | |||
| d57e2ca54b | |||
| 904eeb38c2 | |||
| e1bb723169 | |||
| aa156fff57 | |||
| d3a439181c | |||
| bb70ae26d3 | |||
| 35dc954017 | |||
| 0cae9e88e7 | |||
| 5d824a1aff | |||
| 8a293bcc9d | |||
| 24b89689c5 | |||
| 3da5d1c70c | |||
| d3ec4eb3e2 | |||
| cb446e1057 |
@@ -0,0 +1,137 @@
|
|||||||
|
using OpenNest.Geometry;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenNest.Converters
|
||||||
|
{
|
||||||
|
public enum ContourClassification
|
||||||
|
{
|
||||||
|
Perimeter,
|
||||||
|
Hole,
|
||||||
|
Etch,
|
||||||
|
Open
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ContourInfo
|
||||||
|
{
|
||||||
|
public Shape Shape { get; }
|
||||||
|
public ContourClassification Type { get; private set; }
|
||||||
|
public string Label { get; private set; }
|
||||||
|
|
||||||
|
private ContourInfo(Shape shape, ContourClassification type, string label)
|
||||||
|
{
|
||||||
|
Shape = shape;
|
||||||
|
Type = type;
|
||||||
|
Label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DirectionLabel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Type == ContourClassification.Open || Type == ContourClassification.Etch)
|
||||||
|
return "Open";
|
||||||
|
var poly = Shape.ToPolygon();
|
||||||
|
if (poly == null || poly.Vertices.Count < 3)
|
||||||
|
return "?";
|
||||||
|
return poly.RotationDirection() == RotationType.CW ? "CW" : "CCW";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DimensionLabel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Shape.Entities.Count == 1 && Shape.Entities[0] is Circle c)
|
||||||
|
return $"Circle R{c.Radius:0.#}";
|
||||||
|
Shape.UpdateBounds();
|
||||||
|
var box = Shape.BoundingBox;
|
||||||
|
return $"{box.Width:0.#} x {box.Length:0.#}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reverse()
|
||||||
|
{
|
||||||
|
Shape.Reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLabel(string label)
|
||||||
|
{
|
||||||
|
Label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ContourInfo> Classify(List<Shape> shapes)
|
||||||
|
{
|
||||||
|
if (shapes.Count == 0)
|
||||||
|
return new List<ContourInfo>();
|
||||||
|
|
||||||
|
// Ensure bounding boxes are up to date before comparing
|
||||||
|
foreach (var s in shapes)
|
||||||
|
s.UpdateBounds();
|
||||||
|
|
||||||
|
// Find perimeter — largest bounding box area
|
||||||
|
var perimeterIndex = 0;
|
||||||
|
var maxArea = shapes[0].BoundingBox.Area();
|
||||||
|
for (var i = 1; i < shapes.Count; i++)
|
||||||
|
{
|
||||||
|
var area = shapes[i].BoundingBox.Area();
|
||||||
|
if (area > maxArea)
|
||||||
|
{
|
||||||
|
maxArea = area;
|
||||||
|
perimeterIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new List<ContourInfo>();
|
||||||
|
var holeCount = 0;
|
||||||
|
var etchCount = 0;
|
||||||
|
var openCount = 0;
|
||||||
|
|
||||||
|
// Non-perimeter shapes first (matches CNC cut order: holes before perimeter)
|
||||||
|
for (var i = 0; i < shapes.Count; i++)
|
||||||
|
{
|
||||||
|
if (i == perimeterIndex) continue;
|
||||||
|
var shape = shapes[i];
|
||||||
|
var type = ClassifyShape(shape);
|
||||||
|
|
||||||
|
string label;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ContourClassification.Hole:
|
||||||
|
holeCount++;
|
||||||
|
label = $"Hole {holeCount}";
|
||||||
|
break;
|
||||||
|
case ContourClassification.Etch:
|
||||||
|
etchCount++;
|
||||||
|
label = etchCount == 1 ? "Etch" : $"Etch {etchCount}";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
openCount++;
|
||||||
|
label = openCount == 1 ? "Open" : $"Open {openCount}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(new ContourInfo(shape, type, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perimeter last
|
||||||
|
result.Add(new ContourInfo(shapes[perimeterIndex], ContourClassification.Perimeter, "Perimeter"));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ContourClassification ClassifyShape(Shape shape)
|
||||||
|
{
|
||||||
|
// Check etch layer — all entities must be on ETCH layer
|
||||||
|
if (shape.Entities.Count > 0 &&
|
||||||
|
shape.Entities.All(e => string.Equals(e.Layer?.Name, "ETCH", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
return ContourClassification.Etch;
|
||||||
|
|
||||||
|
if (shape.IsClosed())
|
||||||
|
return ContourClassification.Hole;
|
||||||
|
|
||||||
|
return ContourClassification.Open;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,157 @@
|
|||||||
|
using OpenNest.Converters;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.Tests;
|
||||||
|
|
||||||
|
public class ContourClassificationTests
|
||||||
|
{
|
||||||
|
private static Shape MakeRectShape(double x, double y, double w, double h)
|
||||||
|
{
|
||||||
|
var shape = new Shape();
|
||||||
|
shape.Entities.Add(new Line(new Vector(x, y), new Vector(x + w, y)));
|
||||||
|
shape.Entities.Add(new Line(new Vector(x + w, y), new Vector(x + w, y + h)));
|
||||||
|
shape.Entities.Add(new Line(new Vector(x + w, y + h), new Vector(x, y + h)));
|
||||||
|
shape.Entities.Add(new Line(new Vector(x, y + h), new Vector(x, y)));
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Shape MakeCircleShape(double cx, double cy, double r)
|
||||||
|
{
|
||||||
|
var shape = new Shape();
|
||||||
|
shape.Entities.Add(new Circle(new Vector(cx, cy), r));
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Shape MakeEtchShape()
|
||||||
|
{
|
||||||
|
var etchLayer = new Layer("ETCH");
|
||||||
|
var shape = new Shape();
|
||||||
|
shape.Entities.Add(new Line(new Vector(10, 10), new Vector(50, 10)) { Layer = etchLayer });
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_identifies_largest_shape_as_perimeter()
|
||||||
|
{
|
||||||
|
var shapes = new List<Shape>
|
||||||
|
{
|
||||||
|
MakeCircleShape(25, 25, 5),
|
||||||
|
MakeRectShape(0, 0, 100, 50),
|
||||||
|
MakeCircleShape(75, 25, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
Assert.Equal(3, contours.Count);
|
||||||
|
Assert.Single(contours, c => c.Type == ContourClassification.Perimeter);
|
||||||
|
var perimeter = contours.First(c => c.Type == ContourClassification.Perimeter);
|
||||||
|
Assert.Same(shapes[1], perimeter.Shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_identifies_closed_non_perimeter_as_holes()
|
||||||
|
{
|
||||||
|
var shapes = new List<Shape>
|
||||||
|
{
|
||||||
|
MakeCircleShape(25, 25, 5),
|
||||||
|
MakeRectShape(0, 0, 100, 50),
|
||||||
|
MakeCircleShape(75, 25, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
var holes = contours.Where(c => c.Type == ContourClassification.Hole).ToList();
|
||||||
|
Assert.Equal(2, holes.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_identifies_etch_layer_shapes()
|
||||||
|
{
|
||||||
|
var shapes = new List<Shape>
|
||||||
|
{
|
||||||
|
MakeRectShape(0, 0, 100, 50),
|
||||||
|
MakeEtchShape(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
Assert.Single(contours, c => c.Type == ContourClassification.Etch);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_identifies_open_shapes()
|
||||||
|
{
|
||||||
|
var openShape = new Shape();
|
||||||
|
openShape.Entities.Add(new Line(new Vector(0, 0), new Vector(10, 0)));
|
||||||
|
openShape.Entities.Add(new Line(new Vector(10, 0), new Vector(10, 5)));
|
||||||
|
// Not closed — doesn't return to (0,0)
|
||||||
|
|
||||||
|
var shapes = new List<Shape>
|
||||||
|
{
|
||||||
|
MakeRectShape(0, 0, 100, 50),
|
||||||
|
openShape,
|
||||||
|
};
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
Assert.Single(contours, c => c.Type == ContourClassification.Open);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_orders_holes_first_perimeter_last()
|
||||||
|
{
|
||||||
|
var shapes = new List<Shape>
|
||||||
|
{
|
||||||
|
MakeRectShape(0, 0, 100, 50),
|
||||||
|
MakeCircleShape(25, 25, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
Assert.Equal(ContourClassification.Hole, contours[0].Type);
|
||||||
|
Assert.Equal(ContourClassification.Perimeter, contours[^1].Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_labels_holes_sequentially()
|
||||||
|
{
|
||||||
|
var shapes = new List<Shape>
|
||||||
|
{
|
||||||
|
MakeRectShape(0, 0, 100, 50),
|
||||||
|
MakeCircleShape(25, 25, 5),
|
||||||
|
MakeCircleShape(75, 25, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
var holes = contours.Where(c => c.Type == ContourClassification.Hole).ToList();
|
||||||
|
Assert.Equal("Hole 1", holes[0].Label);
|
||||||
|
Assert.Equal("Hole 2", holes[1].Label);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Classify_single_shape_is_perimeter()
|
||||||
|
{
|
||||||
|
var shapes = new List<Shape> { MakeRectShape(0, 0, 50, 30) };
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
Assert.Single(contours);
|
||||||
|
Assert.Equal(ContourClassification.Perimeter, contours[0].Type);
|
||||||
|
Assert.Equal("Perimeter", contours[0].Label);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Reverse_changes_direction_label()
|
||||||
|
{
|
||||||
|
var shape = MakeRectShape(0, 0, 100, 50);
|
||||||
|
var contours = ContourInfo.Classify(new List<Shape> { shape });
|
||||||
|
var contour = contours[0];
|
||||||
|
|
||||||
|
var originalDirection = contour.DirectionLabel;
|
||||||
|
contour.Reverse();
|
||||||
|
var newDirection = contour.DirectionLabel;
|
||||||
|
|
||||||
|
Assert.NotEqual(originalDirection, newDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.Math;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenNest.Controls
|
||||||
|
{
|
||||||
|
internal static class CutDirectionArrows
|
||||||
|
{
|
||||||
|
public static void DrawProgram(Graphics g, DrawControl view, Program pgm, ref Vector pos,
|
||||||
|
Pen pen, double spacing, float arrowSize)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < pgm.Length; ++i)
|
||||||
|
{
|
||||||
|
var code = pgm[i];
|
||||||
|
|
||||||
|
if (code.Type == CodeType.SubProgramCall)
|
||||||
|
{
|
||||||
|
var subpgm = (SubProgramCall)code;
|
||||||
|
if (subpgm.Program != null)
|
||||||
|
DrawProgram(g, view, subpgm.Program, ref pos, pen, spacing, arrowSize);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code is not Motion motion) continue;
|
||||||
|
|
||||||
|
var endpt = pgm.Mode == Mode.Incremental
|
||||||
|
? motion.EndPoint + pos
|
||||||
|
: motion.EndPoint;
|
||||||
|
|
||||||
|
if (code.Type == CodeType.LinearMove)
|
||||||
|
{
|
||||||
|
var line = (LinearMove)code;
|
||||||
|
if (!line.Suppressed)
|
||||||
|
DrawLineArrows(g, view, pos, endpt, pen, spacing, arrowSize);
|
||||||
|
}
|
||||||
|
else if (code.Type == CodeType.ArcMove)
|
||||||
|
{
|
||||||
|
var arc = (ArcMove)code;
|
||||||
|
if (!arc.Suppressed)
|
||||||
|
{
|
||||||
|
var center = pgm.Mode == Mode.Incremental
|
||||||
|
? arc.CenterPoint + pos
|
||||||
|
: arc.CenterPoint;
|
||||||
|
DrawArcArrows(g, view, pos, endpt, center, arc.Rotation, pen, spacing, arrowSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = endpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawLineArrows(Graphics g, DrawControl view, Vector start, Vector end,
|
||||||
|
Pen pen, double spacing, float arrowSize)
|
||||||
|
{
|
||||||
|
var dx = end.X - start.X;
|
||||||
|
var dy = end.Y - start.Y;
|
||||||
|
var length = System.Math.Sqrt(dx * dx + dy * dy);
|
||||||
|
if (length < spacing * 0.5) return;
|
||||||
|
|
||||||
|
var dirX = dx / length;
|
||||||
|
var dirY = dy / length;
|
||||||
|
|
||||||
|
var count = System.Math.Max(1, (int)(length / spacing));
|
||||||
|
var step = length / (count + 1);
|
||||||
|
|
||||||
|
for (var i = 1; i <= count; i++)
|
||||||
|
{
|
||||||
|
var t = step * i;
|
||||||
|
var pt = new Vector(start.X + dirX * t, start.Y + dirY * t);
|
||||||
|
var screenPt = view.PointWorldToGraph(pt);
|
||||||
|
var angle = System.Math.Atan2(-dirY, dirX);
|
||||||
|
DrawArrowHead(g, pen, screenPt, angle, arrowSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawArcArrows(Graphics g, DrawControl view, Vector start, Vector end, Vector center,
|
||||||
|
RotationType rotation, Pen pen, double spacing, float arrowSize)
|
||||||
|
{
|
||||||
|
var radius = center.DistanceTo(start);
|
||||||
|
if (radius < Tolerance.Epsilon) return;
|
||||||
|
|
||||||
|
var startAngle = System.Math.Atan2(start.Y - center.Y, start.X - center.X);
|
||||||
|
var endAngle = System.Math.Atan2(end.Y - center.Y, end.X - center.X);
|
||||||
|
|
||||||
|
double sweep;
|
||||||
|
if (rotation == RotationType.CCW)
|
||||||
|
{
|
||||||
|
sweep = endAngle - startAngle;
|
||||||
|
if (sweep <= 0) sweep += 2 * System.Math.PI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sweep = startAngle - endAngle;
|
||||||
|
if (sweep <= 0) sweep += 2 * System.Math.PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arcLength = radius * System.Math.Abs(sweep);
|
||||||
|
if (arcLength < spacing * 0.5) return;
|
||||||
|
|
||||||
|
var count = System.Math.Max(1, (int)(arcLength / spacing));
|
||||||
|
var stepAngle = sweep / (count + 1);
|
||||||
|
|
||||||
|
for (var i = 1; i <= count; i++)
|
||||||
|
{
|
||||||
|
double angle;
|
||||||
|
if (rotation == RotationType.CCW)
|
||||||
|
angle = startAngle + stepAngle * i;
|
||||||
|
else
|
||||||
|
angle = startAngle - stepAngle * i;
|
||||||
|
|
||||||
|
var pt = new Vector(
|
||||||
|
center.X + radius * System.Math.Cos(angle),
|
||||||
|
center.Y + radius * System.Math.Sin(angle));
|
||||||
|
var screenPt = view.PointWorldToGraph(pt);
|
||||||
|
|
||||||
|
double tangent;
|
||||||
|
if (rotation == RotationType.CCW)
|
||||||
|
tangent = angle + System.Math.PI / 2;
|
||||||
|
else
|
||||||
|
tangent = angle - System.Math.PI / 2;
|
||||||
|
|
||||||
|
var screenAngle = System.Math.Atan2(-System.Math.Sin(tangent), System.Math.Cos(tangent));
|
||||||
|
DrawArrowHead(g, pen, screenPt, screenAngle, arrowSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawArrowHead(Graphics g, Pen pen, PointF tip, double angle, float size)
|
||||||
|
{
|
||||||
|
var leftAngle = angle + System.Math.PI + 0.5;
|
||||||
|
var rightAngle = angle + System.Math.PI - 0.5;
|
||||||
|
|
||||||
|
var left = new PointF(
|
||||||
|
tip.X + size * (float)System.Math.Cos(leftAngle),
|
||||||
|
tip.Y + size * (float)System.Math.Sin(leftAngle));
|
||||||
|
var right = new PointF(
|
||||||
|
tip.X + size * (float)System.Math.Cos(rightAngle),
|
||||||
|
tip.Y + size * (float)System.Math.Sin(rightAngle));
|
||||||
|
|
||||||
|
g.DrawLine(pen, left, tip);
|
||||||
|
g.DrawLine(pen, right, tip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -152,8 +152,12 @@ namespace OpenNest.Controls
|
|||||||
foreach (var entity in ((Shape)offsetShape.OffsetEntity(0.25, OffsetSide.Left)).Entities)
|
foreach (var entity in ((Shape)offsetShape.OffsetEntity(0.25, OffsetSide.Left)).Entities)
|
||||||
DrawEntity(e.Graphics, entity, Pens.RoyalBlue);
|
DrawEntity(e.Graphics, entity, Pens.RoyalBlue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PaintOverlay?.Invoke(e.Graphics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Action<Graphics> PaintOverlay { get; set; }
|
||||||
|
|
||||||
protected override void OnMouseWheel(MouseEventArgs e)
|
protected override void OnMouseWheel(MouseEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnMouseWheel(e);
|
base.OnMouseWheel(e);
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ namespace OpenNest.Controls
|
|||||||
|
|
||||||
private void DrawAllCutDirectionArrows(Graphics g)
|
private void DrawAllCutDirectionArrows(Graphics g)
|
||||||
{
|
{
|
||||||
using var pen = new Pen(Color.FromArgb(220, Color.Black), 1.5f);
|
using var pen = new Pen(Color.FromArgb(60, 60, 60), 1.5f);
|
||||||
|
|
||||||
var arrowSpacingWorld = view.LengthGuiToWorld(60f);
|
var arrowSpacingWorld = view.LengthGuiToWorld(60f);
|
||||||
var arrowSize = 6f;
|
var arrowSize = 6f;
|
||||||
@@ -525,145 +525,10 @@ namespace OpenNest.Controls
|
|||||||
var part = view.Plate.Parts[i];
|
var part = view.Plate.Parts[i];
|
||||||
var pgm = part.Program;
|
var pgm = part.Program;
|
||||||
var pos = part.Location;
|
var pos = part.Location;
|
||||||
DrawProgramCutDirectionArrows(g, pgm, ref pos, pen, arrowSpacingWorld, arrowSize);
|
CutDirectionArrows.DrawProgram(g, view, pgm, ref pos, pen, arrowSpacingWorld, arrowSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawProgramCutDirectionArrows(Graphics g, Program pgm, ref Vector pos,
|
|
||||||
Pen pen, double spacing, float arrowSize)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < pgm.Length; ++i)
|
|
||||||
{
|
|
||||||
var code = pgm[i];
|
|
||||||
|
|
||||||
if (code.Type == CodeType.SubProgramCall)
|
|
||||||
{
|
|
||||||
var subpgm = (SubProgramCall)code;
|
|
||||||
if (subpgm.Program != null)
|
|
||||||
DrawProgramCutDirectionArrows(g, subpgm.Program, ref pos, pen, spacing, arrowSize);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code is not Motion motion) continue;
|
|
||||||
|
|
||||||
var endpt = pgm.Mode == Mode.Incremental
|
|
||||||
? motion.EndPoint + pos
|
|
||||||
: motion.EndPoint;
|
|
||||||
|
|
||||||
if (code.Type == CodeType.LinearMove)
|
|
||||||
{
|
|
||||||
var line = (LinearMove)code;
|
|
||||||
if (!line.Suppressed)
|
|
||||||
DrawLineDirectionArrows(g, pos, endpt, pen, spacing, arrowSize);
|
|
||||||
}
|
|
||||||
else if (code.Type == CodeType.ArcMove)
|
|
||||||
{
|
|
||||||
var arc = (ArcMove)code;
|
|
||||||
if (!arc.Suppressed)
|
|
||||||
{
|
|
||||||
var center = pgm.Mode == Mode.Incremental
|
|
||||||
? arc.CenterPoint + pos
|
|
||||||
: arc.CenterPoint;
|
|
||||||
DrawArcDirectionArrows(g, pos, endpt, center, arc.Rotation, pen, spacing, arrowSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = endpt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawLineDirectionArrows(Graphics g, Vector start, Vector end,
|
|
||||||
Pen pen, double spacing, float arrowSize)
|
|
||||||
{
|
|
||||||
var dx = end.X - start.X;
|
|
||||||
var dy = end.Y - start.Y;
|
|
||||||
var length = System.Math.Sqrt(dx * dx + dy * dy);
|
|
||||||
if (length < spacing * 0.5) return;
|
|
||||||
|
|
||||||
var dirX = dx / length;
|
|
||||||
var dirY = dy / length;
|
|
||||||
|
|
||||||
var count = System.Math.Max(1, (int)(length / spacing));
|
|
||||||
var step = length / (count + 1);
|
|
||||||
|
|
||||||
for (var i = 1; i <= count; i++)
|
|
||||||
{
|
|
||||||
var t = step * i;
|
|
||||||
var pt = new Vector(start.X + dirX * t, start.Y + dirY * t);
|
|
||||||
var screenPt = view.PointWorldToGraph(pt);
|
|
||||||
var angle = System.Math.Atan2(-dirY, dirX);
|
|
||||||
DrawArrowHead(g, pen, screenPt, angle, arrowSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawArcDirectionArrows(Graphics g, Vector start, Vector end, Vector center,
|
|
||||||
RotationType rotation, Pen pen, double spacing, float arrowSize)
|
|
||||||
{
|
|
||||||
var radius = center.DistanceTo(start);
|
|
||||||
if (radius < Tolerance.Epsilon) return;
|
|
||||||
|
|
||||||
var startAngle = System.Math.Atan2(start.Y - center.Y, start.X - center.X);
|
|
||||||
var endAngle = System.Math.Atan2(end.Y - center.Y, end.X - center.X);
|
|
||||||
|
|
||||||
double sweep;
|
|
||||||
if (rotation == RotationType.CCW)
|
|
||||||
{
|
|
||||||
sweep = endAngle - startAngle;
|
|
||||||
if (sweep <= 0) sweep += 2 * System.Math.PI;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sweep = startAngle - endAngle;
|
|
||||||
if (sweep <= 0) sweep += 2 * System.Math.PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
var arcLength = radius * System.Math.Abs(sweep);
|
|
||||||
if (arcLength < spacing * 0.5) return;
|
|
||||||
|
|
||||||
var count = System.Math.Max(1, (int)(arcLength / spacing));
|
|
||||||
var stepAngle = sweep / (count + 1);
|
|
||||||
|
|
||||||
for (var i = 1; i <= count; i++)
|
|
||||||
{
|
|
||||||
double angle;
|
|
||||||
if (rotation == RotationType.CCW)
|
|
||||||
angle = startAngle + stepAngle * i;
|
|
||||||
else
|
|
||||||
angle = startAngle - stepAngle * i;
|
|
||||||
|
|
||||||
var pt = new Vector(
|
|
||||||
center.X + radius * System.Math.Cos(angle),
|
|
||||||
center.Y + radius * System.Math.Sin(angle));
|
|
||||||
var screenPt = view.PointWorldToGraph(pt);
|
|
||||||
|
|
||||||
double tangent;
|
|
||||||
if (rotation == RotationType.CCW)
|
|
||||||
tangent = angle + System.Math.PI / 2;
|
|
||||||
else
|
|
||||||
tangent = angle - System.Math.PI / 2;
|
|
||||||
|
|
||||||
var screenAngle = System.Math.Atan2(-System.Math.Sin(tangent), System.Math.Cos(tangent));
|
|
||||||
DrawArrowHead(g, pen, screenPt, screenAngle, arrowSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DrawArrowHead(Graphics g, Pen pen, PointF tip, double angle, float size)
|
|
||||||
{
|
|
||||||
var sin = (float)System.Math.Sin(angle);
|
|
||||||
var cos = (float)System.Math.Cos(angle);
|
|
||||||
|
|
||||||
var backX = -size * cos;
|
|
||||||
var backY = -size * sin;
|
|
||||||
var wingX = size * 0.5f * sin;
|
|
||||||
var wingY = -size * 0.5f * cos;
|
|
||||||
|
|
||||||
var wing1 = new PointF(tip.X + backX + wingX, tip.Y + backY + wingY);
|
|
||||||
var wing2 = new PointF(tip.X + backX - wingX, tip.Y + backY - wingY);
|
|
||||||
|
|
||||||
g.DrawLine(pen, wing1, tip);
|
|
||||||
g.DrawLine(pen, wing2, tip);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawLine(Graphics g, Vector pt1, Vector pt2, Pen pen)
|
private void DrawLine(Graphics g, Vector pt1, Vector pt2, Pen pen)
|
||||||
{
|
{
|
||||||
var point1 = view.PointWorldToGraph(pt1);
|
var point1 = view.PointWorldToGraph(pt1);
|
||||||
|
|||||||
+274
@@ -0,0 +1,274 @@
|
|||||||
|
namespace OpenNest.Controls
|
||||||
|
{
|
||||||
|
partial class ProgramEditorControl
|
||||||
|
{
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
components.Dispose();
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
components = new System.ComponentModel.Container();
|
||||||
|
mainSplit = new System.Windows.Forms.SplitContainer();
|
||||||
|
contourPanel = new System.Windows.Forms.Panel();
|
||||||
|
contourList = new System.Windows.Forms.ListBox();
|
||||||
|
contourMenu = new System.Windows.Forms.ContextMenuStrip(components);
|
||||||
|
menuReverse = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
menuMoveUp = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
menuMoveDown = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
menuSequence = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
reverseButton = new System.Windows.Forms.Button();
|
||||||
|
rightSplit = new System.Windows.Forms.SplitContainer();
|
||||||
|
preview = new EntityView();
|
||||||
|
editorPanel = new System.Windows.Forms.Panel();
|
||||||
|
gcodeEditor = new System.Windows.Forms.TextBox();
|
||||||
|
editorToolbar = new System.Windows.Forms.Panel();
|
||||||
|
applyButton = new System.Windows.Forms.Button();
|
||||||
|
lblGcode = new System.Windows.Forms.Label();
|
||||||
|
((System.ComponentModel.ISupportInitialize)mainSplit).BeginInit();
|
||||||
|
mainSplit.Panel1.SuspendLayout();
|
||||||
|
mainSplit.Panel2.SuspendLayout();
|
||||||
|
mainSplit.SuspendLayout();
|
||||||
|
contourPanel.SuspendLayout();
|
||||||
|
contourMenu.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)rightSplit).BeginInit();
|
||||||
|
rightSplit.Panel1.SuspendLayout();
|
||||||
|
rightSplit.Panel2.SuspendLayout();
|
||||||
|
rightSplit.SuspendLayout();
|
||||||
|
editorPanel.SuspendLayout();
|
||||||
|
editorToolbar.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// mainSplit
|
||||||
|
//
|
||||||
|
mainSplit.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
mainSplit.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||||
|
mainSplit.Location = new System.Drawing.Point(0, 0);
|
||||||
|
mainSplit.Name = "mainSplit";
|
||||||
|
//
|
||||||
|
// mainSplit.Panel1
|
||||||
|
//
|
||||||
|
mainSplit.Panel1.Controls.Add(contourPanel);
|
||||||
|
mainSplit.Panel1MinSize = 150;
|
||||||
|
//
|
||||||
|
// mainSplit.Panel2
|
||||||
|
//
|
||||||
|
mainSplit.Panel2.Controls.Add(rightSplit);
|
||||||
|
mainSplit.Size = new System.Drawing.Size(800, 500);
|
||||||
|
mainSplit.SplitterDistance = 180;
|
||||||
|
mainSplit.SplitterWidth = 5;
|
||||||
|
mainSplit.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// contourPanel
|
||||||
|
//
|
||||||
|
contourPanel.Controls.Add(contourList);
|
||||||
|
contourPanel.Controls.Add(reverseButton);
|
||||||
|
contourPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
contourPanel.Location = new System.Drawing.Point(0, 0);
|
||||||
|
contourPanel.Name = "contourPanel";
|
||||||
|
contourPanel.Size = new System.Drawing.Size(180, 500);
|
||||||
|
contourPanel.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// contourList
|
||||||
|
//
|
||||||
|
contourList.BackColor = System.Drawing.Color.White;
|
||||||
|
contourList.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||||
|
contourList.ContextMenuStrip = contourMenu;
|
||||||
|
contourList.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
contourList.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
|
||||||
|
contourList.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||||
|
contourList.IntegralHeight = false;
|
||||||
|
contourList.Location = new System.Drawing.Point(0, 0);
|
||||||
|
contourList.Name = "contourList";
|
||||||
|
contourList.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
|
||||||
|
contourList.Size = new System.Drawing.Size(180, 462);
|
||||||
|
contourList.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// contourMenu
|
||||||
|
//
|
||||||
|
contourMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { menuReverse, menuMoveUp, menuMoveDown, new System.Windows.Forms.ToolStripSeparator(), menuSequence });
|
||||||
|
contourMenu.Name = "contourMenu";
|
||||||
|
contourMenu.Size = new System.Drawing.Size(180, 120);
|
||||||
|
//
|
||||||
|
// menuReverse
|
||||||
|
//
|
||||||
|
menuReverse.Name = "menuReverse";
|
||||||
|
menuReverse.Size = new System.Drawing.Size(179, 22);
|
||||||
|
menuReverse.Text = "Reverse Direction";
|
||||||
|
//
|
||||||
|
// menuMoveUp
|
||||||
|
//
|
||||||
|
menuMoveUp.Name = "menuMoveUp";
|
||||||
|
menuMoveUp.Size = new System.Drawing.Size(179, 22);
|
||||||
|
menuMoveUp.Text = "Move Up";
|
||||||
|
//
|
||||||
|
// menuMoveDown
|
||||||
|
//
|
||||||
|
menuMoveDown.Name = "menuMoveDown";
|
||||||
|
menuMoveDown.Size = new System.Drawing.Size(179, 22);
|
||||||
|
menuMoveDown.Text = "Move Down";
|
||||||
|
//
|
||||||
|
// menuSequence
|
||||||
|
//
|
||||||
|
menuSequence.Name = "menuSequence";
|
||||||
|
menuSequence.Size = new System.Drawing.Size(179, 22);
|
||||||
|
menuSequence.Text = "Auto Sequence";
|
||||||
|
//
|
||||||
|
// reverseButton
|
||||||
|
//
|
||||||
|
reverseButton.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
reverseButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
reverseButton.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||||
|
reverseButton.Location = new System.Drawing.Point(0, 462);
|
||||||
|
reverseButton.Name = "reverseButton";
|
||||||
|
reverseButton.Size = new System.Drawing.Size(180, 38);
|
||||||
|
reverseButton.TabIndex = 1;
|
||||||
|
reverseButton.Text = "⇅ Reverse Direction";
|
||||||
|
//
|
||||||
|
// rightSplit
|
||||||
|
//
|
||||||
|
rightSplit.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
rightSplit.Location = new System.Drawing.Point(0, 0);
|
||||||
|
rightSplit.Name = "rightSplit";
|
||||||
|
//
|
||||||
|
// rightSplit.Panel1
|
||||||
|
//
|
||||||
|
rightSplit.Panel1.Controls.Add(preview);
|
||||||
|
//
|
||||||
|
// rightSplit.Panel2
|
||||||
|
//
|
||||||
|
rightSplit.Panel2.Controls.Add(editorPanel);
|
||||||
|
rightSplit.Size = new System.Drawing.Size(615, 500);
|
||||||
|
rightSplit.SplitterDistance = 350;
|
||||||
|
rightSplit.SplitterWidth = 5;
|
||||||
|
rightSplit.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// preview
|
||||||
|
//
|
||||||
|
preview.BackColor = System.Drawing.Color.FromArgb(33, 40, 48);
|
||||||
|
preview.Cursor = System.Windows.Forms.Cursors.Cross;
|
||||||
|
preview.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
preview.IsPickingBendLine = false;
|
||||||
|
preview.Location = new System.Drawing.Point(0, 0);
|
||||||
|
preview.Name = "preview";
|
||||||
|
preview.OriginalEntities = null;
|
||||||
|
preview.PaintOverlay = null;
|
||||||
|
preview.ShowEntityLabels = false;
|
||||||
|
preview.SimplifierHighlight = null;
|
||||||
|
preview.SimplifierPreview = null;
|
||||||
|
preview.SimplifierToleranceLeft = null;
|
||||||
|
preview.SimplifierToleranceRight = null;
|
||||||
|
preview.Size = new System.Drawing.Size(350, 500);
|
||||||
|
preview.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// editorPanel
|
||||||
|
//
|
||||||
|
editorPanel.Controls.Add(gcodeEditor);
|
||||||
|
editorPanel.Controls.Add(editorToolbar);
|
||||||
|
editorPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
editorPanel.Location = new System.Drawing.Point(0, 0);
|
||||||
|
editorPanel.Name = "editorPanel";
|
||||||
|
editorPanel.Size = new System.Drawing.Size(260, 500);
|
||||||
|
editorPanel.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// gcodeEditor
|
||||||
|
//
|
||||||
|
gcodeEditor.BackColor = System.Drawing.Color.FromArgb(30, 30, 45);
|
||||||
|
gcodeEditor.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||||
|
gcodeEditor.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
gcodeEditor.Font = new System.Drawing.Font("Consolas", 10F);
|
||||||
|
gcodeEditor.ForeColor = System.Drawing.Color.FromArgb(180, 200, 180);
|
||||||
|
gcodeEditor.Location = new System.Drawing.Point(0, 30);
|
||||||
|
gcodeEditor.Multiline = true;
|
||||||
|
gcodeEditor.Name = "gcodeEditor";
|
||||||
|
gcodeEditor.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
|
gcodeEditor.Size = new System.Drawing.Size(260, 470);
|
||||||
|
gcodeEditor.TabIndex = 1;
|
||||||
|
gcodeEditor.WordWrap = false;
|
||||||
|
//
|
||||||
|
// editorToolbar
|
||||||
|
//
|
||||||
|
editorToolbar.BackColor = System.Drawing.Color.FromArgb(245, 245, 245);
|
||||||
|
editorToolbar.Controls.Add(applyButton);
|
||||||
|
editorToolbar.Controls.Add(lblGcode);
|
||||||
|
editorToolbar.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
|
editorToolbar.Location = new System.Drawing.Point(0, 0);
|
||||||
|
editorToolbar.Name = "editorToolbar";
|
||||||
|
editorToolbar.Padding = new System.Windows.Forms.Padding(6, 4, 6, 4);
|
||||||
|
editorToolbar.Size = new System.Drawing.Size(260, 30);
|
||||||
|
editorToolbar.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// applyButton
|
||||||
|
//
|
||||||
|
applyButton.Dock = System.Windows.Forms.DockStyle.Right;
|
||||||
|
applyButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
applyButton.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||||
|
applyButton.Location = new System.Drawing.Point(184, 4);
|
||||||
|
applyButton.Name = "applyButton";
|
||||||
|
applyButton.Size = new System.Drawing.Size(70, 22);
|
||||||
|
applyButton.TabIndex = 1;
|
||||||
|
applyButton.Text = "Apply";
|
||||||
|
//
|
||||||
|
// lblGcode
|
||||||
|
//
|
||||||
|
lblGcode.AutoSize = true;
|
||||||
|
lblGcode.Dock = System.Windows.Forms.DockStyle.Left;
|
||||||
|
lblGcode.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||||
|
lblGcode.ForeColor = System.Drawing.Color.Gray;
|
||||||
|
lblGcode.Location = new System.Drawing.Point(6, 4);
|
||||||
|
lblGcode.Name = "lblGcode";
|
||||||
|
lblGcode.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
|
lblGcode.Size = new System.Drawing.Size(48, 18);
|
||||||
|
lblGcode.TabIndex = 0;
|
||||||
|
lblGcode.Text = "G-Code";
|
||||||
|
//
|
||||||
|
// ProgramEditorControl
|
||||||
|
//
|
||||||
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||||
|
Controls.Add(mainSplit);
|
||||||
|
Name = "ProgramEditorControl";
|
||||||
|
Size = new System.Drawing.Size(800, 500);
|
||||||
|
mainSplit.Panel1.ResumeLayout(false);
|
||||||
|
mainSplit.Panel2.ResumeLayout(false);
|
||||||
|
((System.ComponentModel.ISupportInitialize)mainSplit).EndInit();
|
||||||
|
mainSplit.ResumeLayout(false);
|
||||||
|
contourPanel.ResumeLayout(false);
|
||||||
|
contourMenu.ResumeLayout(false);
|
||||||
|
rightSplit.Panel1.ResumeLayout(false);
|
||||||
|
rightSplit.Panel2.ResumeLayout(false);
|
||||||
|
((System.ComponentModel.ISupportInitialize)rightSplit).EndInit();
|
||||||
|
rightSplit.ResumeLayout(false);
|
||||||
|
editorPanel.ResumeLayout(false);
|
||||||
|
editorPanel.PerformLayout();
|
||||||
|
editorToolbar.ResumeLayout(false);
|
||||||
|
editorToolbar.PerformLayout();
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.SplitContainer mainSplit;
|
||||||
|
private System.Windows.Forms.Panel contourPanel;
|
||||||
|
private System.Windows.Forms.ListBox contourList;
|
||||||
|
private System.Windows.Forms.Button reverseButton;
|
||||||
|
private System.Windows.Forms.SplitContainer rightSplit;
|
||||||
|
private Controls.EntityView preview;
|
||||||
|
private System.Windows.Forms.Panel editorPanel;
|
||||||
|
private System.Windows.Forms.Panel editorToolbar;
|
||||||
|
private System.Windows.Forms.Label lblGcode;
|
||||||
|
private System.Windows.Forms.Button applyButton;
|
||||||
|
private System.Windows.Forms.TextBox gcodeEditor;
|
||||||
|
private System.Windows.Forms.ContextMenuStrip contourMenu;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem menuReverse;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem menuMoveUp;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem menuMoveDown;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem menuSequence;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,470 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.Converters;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace OpenNest.Controls
|
||||||
|
{
|
||||||
|
public partial class ProgramEditorControl : UserControl
|
||||||
|
{
|
||||||
|
private List<ContourInfo> contours = new();
|
||||||
|
private bool isDirty;
|
||||||
|
private bool isLoaded;
|
||||||
|
|
||||||
|
public ProgramEditorControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
contourList.DrawItem += OnDrawContourItem;
|
||||||
|
contourList.MeasureItem += OnMeasureContourItem;
|
||||||
|
contourList.SelectedIndexChanged += OnContourSelectionChanged;
|
||||||
|
reverseButton.Click += OnReverseClicked;
|
||||||
|
menuReverse.Click += OnReverseClicked;
|
||||||
|
menuMoveUp.Click += OnMoveUpClicked;
|
||||||
|
menuMoveDown.Click += OnMoveDownClicked;
|
||||||
|
menuSequence.Click += OnSequenceClicked;
|
||||||
|
contourMenu.Opening += OnContourMenuOpening;
|
||||||
|
applyButton.Click += OnApplyClicked;
|
||||||
|
preview.PaintOverlay = OnPreviewPaintOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Program Program { get; private set; }
|
||||||
|
public bool IsDirty => isDirty;
|
||||||
|
public bool IsLoaded => isLoaded;
|
||||||
|
|
||||||
|
public event EventHandler ProgramChanged;
|
||||||
|
|
||||||
|
public void LoadEntities(List<Entity> entities)
|
||||||
|
{
|
||||||
|
var shapes = ShapeBuilder.GetShapes(entities);
|
||||||
|
if (shapes.Count == 0)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
contours = ContourInfo.Classify(shapes);
|
||||||
|
|
||||||
|
// Assign contour-type colors once so the CAD view also picks them up
|
||||||
|
foreach (var contour in contours)
|
||||||
|
{
|
||||||
|
var color = GetContourColor(contour.Type, false);
|
||||||
|
foreach (var entity in contour.Shape.Entities)
|
||||||
|
entity.Color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program = BuildProgram(contours);
|
||||||
|
isDirty = false;
|
||||||
|
isLoaded = true;
|
||||||
|
|
||||||
|
PopulateContourList();
|
||||||
|
UpdateGcodeText();
|
||||||
|
RefreshPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
contours.Clear();
|
||||||
|
contourList.Items.Clear();
|
||||||
|
preview.Entities.Clear();
|
||||||
|
preview.Invalidate();
|
||||||
|
gcodeEditor.Clear();
|
||||||
|
Program = null;
|
||||||
|
isDirty = false;
|
||||||
|
isLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Program BuildProgram(List<ContourInfo> contours)
|
||||||
|
{
|
||||||
|
var pgm = new Program();
|
||||||
|
foreach (var contour in contours)
|
||||||
|
{
|
||||||
|
var sub = ConvertGeometry.ToProgram(contour.Shape);
|
||||||
|
pgm.Merge(sub);
|
||||||
|
}
|
||||||
|
pgm.Mode = Mode.Incremental;
|
||||||
|
return pgm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateContourList()
|
||||||
|
{
|
||||||
|
contourList.Items.Clear();
|
||||||
|
foreach (var contour in contours)
|
||||||
|
contourList.Items.Add(contour);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateGcodeText()
|
||||||
|
{
|
||||||
|
gcodeEditor.Text = Program != null ? FormatProgram(Program) : string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatProgram(Program pgm)
|
||||||
|
{
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
sb.AppendLine(pgm.Mode == Mode.Absolute ? "G90" : "G91");
|
||||||
|
|
||||||
|
var lastWasRapid = false;
|
||||||
|
foreach (var code in pgm.Codes)
|
||||||
|
{
|
||||||
|
if (code is RapidMove rapid)
|
||||||
|
{
|
||||||
|
if (!lastWasRapid && sb.Length > 0)
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine($"G00 X{FormatCoord(rapid.EndPoint.X)} Y{FormatCoord(rapid.EndPoint.Y)}");
|
||||||
|
lastWasRapid = true;
|
||||||
|
}
|
||||||
|
else if (code is ArcMove arc)
|
||||||
|
{
|
||||||
|
var g = arc.Rotation == RotationType.CW ? "G02" : "G03";
|
||||||
|
sb.AppendLine($"{g} X{FormatCoord(arc.EndPoint.X)} Y{FormatCoord(arc.EndPoint.Y)} I{FormatCoord(arc.CenterPoint.X)} J{FormatCoord(arc.CenterPoint.Y)}");
|
||||||
|
lastWasRapid = false;
|
||||||
|
}
|
||||||
|
else if (code is LinearMove linear)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"G01 X{FormatCoord(linear.EndPoint.X)} Y{FormatCoord(linear.EndPoint.Y)}");
|
||||||
|
lastWasRapid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatCoord(double value)
|
||||||
|
{
|
||||||
|
return System.Math.Round(value, 4).ToString("0.####", System.Globalization.CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshPreview()
|
||||||
|
{
|
||||||
|
preview.ClearPenCache();
|
||||||
|
preview.Entities.Clear();
|
||||||
|
|
||||||
|
// Restore base colors first (undo any selection highlight)
|
||||||
|
foreach (var contour in contours)
|
||||||
|
{
|
||||||
|
var baseColor = GetContourColor(contour.Type, false);
|
||||||
|
foreach (var entity in contour.Shape.Entities)
|
||||||
|
entity.Color = baseColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < contours.Count; i++)
|
||||||
|
{
|
||||||
|
var contour = contours[i];
|
||||||
|
var selected = contourList.SelectedIndices.Contains(i);
|
||||||
|
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
var selColor = GetContourColor(contour.Type, true);
|
||||||
|
foreach (var entity in contour.Shape.Entities)
|
||||||
|
entity.Color = selColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
preview.Entities.AddRange(contour.Shape.Entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
preview.ZoomToFit();
|
||||||
|
preview.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color GetContourColor(ContourClassification type, bool selected)
|
||||||
|
{
|
||||||
|
if (selected)
|
||||||
|
return Color.White;
|
||||||
|
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
ContourClassification.Perimeter => Color.FromArgb(80, 180, 120),
|
||||||
|
ContourClassification.Hole => Color.FromArgb(100, 140, 255),
|
||||||
|
ContourClassification.Etch => Color.FromArgb(255, 170, 50),
|
||||||
|
ContourClassification.Open => Color.FromArgb(200, 200, 100),
|
||||||
|
_ => Color.Gray,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMeasureContourItem(object sender, MeasureItemEventArgs e)
|
||||||
|
{
|
||||||
|
e.ItemHeight = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDrawContourItem(object sender, DrawItemEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Index < 0 || e.Index >= contours.Count) return;
|
||||||
|
|
||||||
|
var contour = contours[e.Index];
|
||||||
|
var selected = (e.State & DrawItemState.Selected) != 0;
|
||||||
|
var bounds = e.Bounds;
|
||||||
|
|
||||||
|
// Background
|
||||||
|
using var bgBrush = new SolidBrush(selected
|
||||||
|
? Color.FromArgb(230, 238, 255)
|
||||||
|
: Color.White);
|
||||||
|
e.Graphics.FillRectangle(bgBrush, bounds);
|
||||||
|
|
||||||
|
// Accent bar
|
||||||
|
var accentColor = GetContourColor(contour.Type, false);
|
||||||
|
using var accentBrush = new SolidBrush(accentColor);
|
||||||
|
e.Graphics.FillRectangle(accentBrush, bounds.X, bounds.Y + 4, 3, bounds.Height - 8);
|
||||||
|
|
||||||
|
// Direction icon
|
||||||
|
var icon = contour.Type switch
|
||||||
|
{
|
||||||
|
ContourClassification.Perimeter or ContourClassification.Hole =>
|
||||||
|
contour.DirectionLabel == "CW" ? "\u21BB" : "\u21BA",
|
||||||
|
ContourClassification.Etch => "\u2014",
|
||||||
|
_ => "\u2014",
|
||||||
|
};
|
||||||
|
using var iconFont = new Font("Segoe UI", 14f);
|
||||||
|
using var iconBrush = new SolidBrush(accentColor);
|
||||||
|
e.Graphics.DrawString(icon, iconFont, iconBrush, bounds.X + 8, bounds.Y + 6);
|
||||||
|
|
||||||
|
// Label
|
||||||
|
using var labelFont = new Font("Segoe UI", 9f, FontStyle.Bold);
|
||||||
|
using var labelBrush = new SolidBrush(Color.FromArgb(40, 40, 40));
|
||||||
|
e.Graphics.DrawString(contour.Label, labelFont, labelBrush, bounds.X + 32, bounds.Y + 4);
|
||||||
|
|
||||||
|
// Info line
|
||||||
|
var info = $"{contour.DirectionLabel} \u00B7 {contour.DimensionLabel}";
|
||||||
|
using var infoFont = new Font("Segoe UI", 8f);
|
||||||
|
using var infoBrush = new SolidBrush(Color.Gray);
|
||||||
|
e.Graphics.DrawString(info, infoFont, infoBrush, bounds.X + 32, bounds.Y + 22);
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
using var sepPen = new Pen(Color.FromArgb(230, 230, 230));
|
||||||
|
e.Graphics.DrawLine(sepPen, bounds.X + 8, bounds.Bottom - 1, bounds.Right - 8, bounds.Bottom - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnContourSelectionChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RefreshPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnReverseClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (contourList.SelectedIndices.Count == 0) return;
|
||||||
|
|
||||||
|
foreach (int index in contourList.SelectedIndices)
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < contours.Count)
|
||||||
|
contours[index].Reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
Program = BuildProgram(contours);
|
||||||
|
isDirty = true;
|
||||||
|
|
||||||
|
contourList.Invalidate();
|
||||||
|
UpdateGcodeText();
|
||||||
|
RefreshPreview();
|
||||||
|
ProgramChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnContourMenuOpening(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
|
{
|
||||||
|
var index = contourList.SelectedIndex;
|
||||||
|
var perimeterIndex = contours.FindIndex(c => c.Type == ContourClassification.Perimeter);
|
||||||
|
var isPerimeter = index >= 0 && index == perimeterIndex;
|
||||||
|
|
||||||
|
// Can't move perimeter, can't move past perimeter
|
||||||
|
menuMoveUp.Enabled = index > 0 && !isPerimeter;
|
||||||
|
menuMoveDown.Enabled = index >= 0 && index < perimeterIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMoveUpClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var index = contourList.SelectedIndex;
|
||||||
|
if (index <= 0) return;
|
||||||
|
if (contours[index].Type == ContourClassification.Perimeter) return;
|
||||||
|
|
||||||
|
(contours[index], contours[index - 1]) = (contours[index - 1], contours[index]);
|
||||||
|
RebuildAfterReorder(index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMoveDownClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var index = contourList.SelectedIndex;
|
||||||
|
if (index < 0 || index >= contours.Count - 1) return;
|
||||||
|
if (contours[index].Type == ContourClassification.Perimeter) return;
|
||||||
|
if (contours[index + 1].Type == ContourClassification.Perimeter) return;
|
||||||
|
|
||||||
|
(contours[index], contours[index + 1]) = (contours[index + 1], contours[index]);
|
||||||
|
RebuildAfterReorder(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSequenceClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// Nearest-neighbor sort for non-perimeter contours
|
||||||
|
var perimeterIndex = contours.FindIndex(c => c.Type == ContourClassification.Perimeter);
|
||||||
|
if (perimeterIndex < 0) return;
|
||||||
|
|
||||||
|
var nonPerimeter = contours.Where(c => c.Type != ContourClassification.Perimeter).ToList();
|
||||||
|
if (nonPerimeter.Count <= 1) return;
|
||||||
|
|
||||||
|
var sorted = new List<ContourInfo>();
|
||||||
|
var remaining = new List<ContourInfo>(nonPerimeter);
|
||||||
|
var pos = new Vector();
|
||||||
|
|
||||||
|
while (remaining.Count > 0)
|
||||||
|
{
|
||||||
|
var nearest = 0;
|
||||||
|
var nearestDist = double.MaxValue;
|
||||||
|
|
||||||
|
for (var i = 0; i < remaining.Count; i++)
|
||||||
|
{
|
||||||
|
var startPt = GetContourStartPoint(remaining[i]);
|
||||||
|
var dist = pos.DistanceTo(startPt);
|
||||||
|
if (dist < nearestDist)
|
||||||
|
{
|
||||||
|
nearestDist = dist;
|
||||||
|
nearest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var next = remaining[nearest];
|
||||||
|
sorted.Add(next);
|
||||||
|
pos = GetContourEndPoint(next);
|
||||||
|
remaining.RemoveAt(nearest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put perimeter back at the end
|
||||||
|
sorted.Add(contours[perimeterIndex]);
|
||||||
|
contours = sorted;
|
||||||
|
RebuildAfterReorder(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector GetContourStartPoint(ContourInfo contour)
|
||||||
|
{
|
||||||
|
var entity = contour.Shape.Entities[0];
|
||||||
|
return entity switch
|
||||||
|
{
|
||||||
|
Line line => line.StartPoint,
|
||||||
|
Arc arc => arc.StartPoint(),
|
||||||
|
Circle circle => new Vector(circle.Center.X + circle.Radius, circle.Center.Y),
|
||||||
|
_ => new Vector(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector GetContourEndPoint(ContourInfo contour)
|
||||||
|
{
|
||||||
|
var entity = contour.Shape.Entities[^1];
|
||||||
|
return entity switch
|
||||||
|
{
|
||||||
|
Line line => line.EndPoint,
|
||||||
|
Arc arc => arc.EndPoint(),
|
||||||
|
Circle circle => new Vector(circle.Center.X + circle.Radius, circle.Center.Y),
|
||||||
|
_ => new Vector(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RebuildAfterReorder(int selectIndex)
|
||||||
|
{
|
||||||
|
RelabelContours();
|
||||||
|
Program = BuildProgram(contours);
|
||||||
|
isDirty = true;
|
||||||
|
|
||||||
|
PopulateContourList();
|
||||||
|
if (selectIndex >= 0 && selectIndex < contourList.Items.Count)
|
||||||
|
contourList.SelectedIndex = selectIndex;
|
||||||
|
UpdateGcodeText();
|
||||||
|
RefreshPreview();
|
||||||
|
ProgramChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RelabelContours()
|
||||||
|
{
|
||||||
|
var holeCount = 0;
|
||||||
|
var etchCount = 0;
|
||||||
|
var openCount = 0;
|
||||||
|
|
||||||
|
foreach (var contour in contours)
|
||||||
|
{
|
||||||
|
switch (contour.Type)
|
||||||
|
{
|
||||||
|
case ContourClassification.Hole:
|
||||||
|
holeCount++;
|
||||||
|
contour.SetLabel($"Hole {holeCount}");
|
||||||
|
break;
|
||||||
|
case ContourClassification.Etch:
|
||||||
|
etchCount++;
|
||||||
|
contour.SetLabel(etchCount == 1 ? "Etch" : $"Etch {etchCount}");
|
||||||
|
break;
|
||||||
|
case ContourClassification.Open:
|
||||||
|
openCount++;
|
||||||
|
contour.SetLabel(openCount == 1 ? "Open" : $"Open {openCount}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPreviewPaintOverlay(Graphics g)
|
||||||
|
{
|
||||||
|
if (contours.Count == 0) return;
|
||||||
|
|
||||||
|
var spacing = preview.LengthGuiToWorld(60f);
|
||||||
|
var arrowSize = 8f;
|
||||||
|
|
||||||
|
using var pen = new Pen(Color.LightGray, 1.5f);
|
||||||
|
|
||||||
|
for (var i = 0; i < contours.Count; i++)
|
||||||
|
{
|
||||||
|
if (!contourList.SelectedIndices.Contains(i)) continue;
|
||||||
|
|
||||||
|
var contour = contours[i];
|
||||||
|
var pgm = ConvertGeometry.ToProgram(contour.Shape);
|
||||||
|
if (pgm == null) continue;
|
||||||
|
|
||||||
|
var pos = new Vector();
|
||||||
|
CutDirectionArrows.DrawProgram(g, preview, pgm, ref pos, pen, spacing, arrowSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplyClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var text = gcodeEditor.Text;
|
||||||
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
|
{
|
||||||
|
MessageBox.Show("G-code is empty.", "Apply", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var stream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(text));
|
||||||
|
var reader = new ProgramReader(stream);
|
||||||
|
var parsed = reader.Read();
|
||||||
|
|
||||||
|
if (parsed == null || parsed.Length == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show("No valid G-code found.", "Apply", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebuild shapes from the parsed program
|
||||||
|
var entities = ConvertProgram.ToGeometry(parsed);
|
||||||
|
var shapes = ShapeBuilder.GetShapes(entities);
|
||||||
|
|
||||||
|
if (shapes.Count == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show("No contours found in parsed G-code.", "Apply", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
contours = ContourInfo.Classify(shapes);
|
||||||
|
Program = parsed;
|
||||||
|
isDirty = true;
|
||||||
|
|
||||||
|
PopulateContourList();
|
||||||
|
RefreshPreview();
|
||||||
|
ProgramChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error parsing G-code: {ex.Message}", "Apply",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="contourMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+92
-36
@@ -16,11 +16,15 @@ namespace OpenNest.Forms
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
mainSplit = new System.Windows.Forms.SplitContainer();
|
mainSplit = new System.Windows.Forms.SplitContainer();
|
||||||
sidebarSplit = new System.Windows.Forms.SplitContainer();
|
|
||||||
fileList = new OpenNest.Controls.FileListControl();
|
fileList = new OpenNest.Controls.FileListControl();
|
||||||
|
cadViewSplit = new System.Windows.Forms.SplitContainer();
|
||||||
filterPanel = new OpenNest.Controls.FilterPanel();
|
filterPanel = new OpenNest.Controls.FilterPanel();
|
||||||
entityView1 = new OpenNest.Controls.EntityView();
|
entityView1 = new OpenNest.Controls.EntityView();
|
||||||
detailBar = new System.Windows.Forms.FlowLayoutPanel();
|
detailBar = new System.Windows.Forms.FlowLayoutPanel();
|
||||||
|
viewTabs = new System.Windows.Forms.TabControl();
|
||||||
|
tabCadView = new System.Windows.Forms.TabPage();
|
||||||
|
tabProgram = new System.Windows.Forms.TabPage();
|
||||||
|
programEditor = new OpenNest.Controls.ProgramEditorControl();
|
||||||
lblQty = new System.Windows.Forms.Label();
|
lblQty = new System.Windows.Forms.Label();
|
||||||
numQuantity = new System.Windows.Forms.NumericUpDown();
|
numQuantity = new System.Windows.Forms.NumericUpDown();
|
||||||
lblCust = new System.Windows.Forms.Label();
|
lblCust = new System.Windows.Forms.Label();
|
||||||
@@ -41,11 +45,14 @@ namespace OpenNest.Forms
|
|||||||
mainSplit.Panel1.SuspendLayout();
|
mainSplit.Panel1.SuspendLayout();
|
||||||
mainSplit.Panel2.SuspendLayout();
|
mainSplit.Panel2.SuspendLayout();
|
||||||
mainSplit.SuspendLayout();
|
mainSplit.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)sidebarSplit).BeginInit();
|
((System.ComponentModel.ISupportInitialize)cadViewSplit).BeginInit();
|
||||||
sidebarSplit.Panel1.SuspendLayout();
|
cadViewSplit.Panel1.SuspendLayout();
|
||||||
sidebarSplit.Panel2.SuspendLayout();
|
cadViewSplit.Panel2.SuspendLayout();
|
||||||
sidebarSplit.SuspendLayout();
|
cadViewSplit.SuspendLayout();
|
||||||
detailBar.SuspendLayout();
|
detailBar.SuspendLayout();
|
||||||
|
viewTabs.SuspendLayout();
|
||||||
|
tabCadView.SuspendLayout();
|
||||||
|
tabProgram.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)numQuantity).BeginInit();
|
((System.ComponentModel.ISupportInitialize)numQuantity).BeginInit();
|
||||||
bottomPanel1.SuspendLayout();
|
bottomPanel1.SuspendLayout();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
@@ -59,37 +66,17 @@ namespace OpenNest.Forms
|
|||||||
//
|
//
|
||||||
// mainSplit.Panel1
|
// mainSplit.Panel1
|
||||||
//
|
//
|
||||||
mainSplit.Panel1.Controls.Add(sidebarSplit);
|
mainSplit.Panel1.Controls.Add(fileList);
|
||||||
mainSplit.Panel1MinSize = 200;
|
mainSplit.Panel1MinSize = 200;
|
||||||
//
|
//
|
||||||
// mainSplit.Panel2
|
// mainSplit.Panel2
|
||||||
//
|
//
|
||||||
mainSplit.Panel2.Controls.Add(entityView1);
|
mainSplit.Panel2.Controls.Add(viewTabs);
|
||||||
mainSplit.Panel2.Controls.Add(detailBar);
|
|
||||||
mainSplit.Size = new System.Drawing.Size(1024, 670);
|
mainSplit.Size = new System.Drawing.Size(1024, 670);
|
||||||
mainSplit.SplitterDistance = 260;
|
mainSplit.SplitterDistance = 260;
|
||||||
mainSplit.SplitterWidth = 5;
|
mainSplit.SplitterWidth = 5;
|
||||||
mainSplit.TabIndex = 2;
|
mainSplit.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// sidebarSplit
|
|
||||||
//
|
|
||||||
sidebarSplit.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
||||||
sidebarSplit.Location = new System.Drawing.Point(0, 0);
|
|
||||||
sidebarSplit.Name = "sidebarSplit";
|
|
||||||
sidebarSplit.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
|
||||||
//
|
|
||||||
// sidebarSplit.Panel1
|
|
||||||
//
|
|
||||||
sidebarSplit.Panel1.Controls.Add(fileList);
|
|
||||||
//
|
|
||||||
// sidebarSplit.Panel2
|
|
||||||
//
|
|
||||||
sidebarSplit.Panel2.Controls.Add(filterPanel);
|
|
||||||
sidebarSplit.Size = new System.Drawing.Size(260, 670);
|
|
||||||
sidebarSplit.SplitterDistance = 300;
|
|
||||||
sidebarSplit.SplitterWidth = 5;
|
|
||||||
sidebarSplit.TabIndex = 0;
|
|
||||||
//
|
|
||||||
// fileList
|
// fileList
|
||||||
//
|
//
|
||||||
fileList.AllowDrop = true;
|
fileList.AllowDrop = true;
|
||||||
@@ -98,9 +85,30 @@ namespace OpenNest.Forms
|
|||||||
fileList.Font = new System.Drawing.Font("Segoe UI", 9F);
|
fileList.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||||
fileList.Location = new System.Drawing.Point(0, 0);
|
fileList.Location = new System.Drawing.Point(0, 0);
|
||||||
fileList.Name = "fileList";
|
fileList.Name = "fileList";
|
||||||
fileList.Size = new System.Drawing.Size(260, 300);
|
fileList.Size = new System.Drawing.Size(260, 670);
|
||||||
fileList.TabIndex = 0;
|
fileList.TabIndex = 0;
|
||||||
//
|
//
|
||||||
|
// cadViewSplit
|
||||||
|
//
|
||||||
|
cadViewSplit.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
cadViewSplit.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||||
|
cadViewSplit.Location = new System.Drawing.Point(0, 0);
|
||||||
|
cadViewSplit.Name = "cadViewSplit";
|
||||||
|
//
|
||||||
|
// cadViewSplit.Panel1 — filter panel
|
||||||
|
//
|
||||||
|
cadViewSplit.Panel1.Controls.Add(filterPanel);
|
||||||
|
cadViewSplit.Panel1MinSize = 150;
|
||||||
|
//
|
||||||
|
// cadViewSplit.Panel2 — entity view + detail bar
|
||||||
|
//
|
||||||
|
cadViewSplit.Panel2.Controls.Add(entityView1);
|
||||||
|
cadViewSplit.Panel2.Controls.Add(detailBar);
|
||||||
|
cadViewSplit.Size = new System.Drawing.Size(751, 642);
|
||||||
|
cadViewSplit.SplitterDistance = 200;
|
||||||
|
cadViewSplit.SplitterWidth = 5;
|
||||||
|
cadViewSplit.TabIndex = 0;
|
||||||
|
//
|
||||||
// filterPanel
|
// filterPanel
|
||||||
//
|
//
|
||||||
filterPanel.AutoScroll = true;
|
filterPanel.AutoScroll = true;
|
||||||
@@ -108,7 +116,7 @@ namespace OpenNest.Forms
|
|||||||
filterPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
filterPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
filterPanel.Location = new System.Drawing.Point(0, 0);
|
filterPanel.Location = new System.Drawing.Point(0, 0);
|
||||||
filterPanel.Name = "filterPanel";
|
filterPanel.Name = "filterPanel";
|
||||||
filterPanel.Size = new System.Drawing.Size(260, 365);
|
filterPanel.Size = new System.Drawing.Size(200, 642);
|
||||||
filterPanel.TabIndex = 0;
|
filterPanel.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// entityView1
|
// entityView1
|
||||||
@@ -125,7 +133,7 @@ namespace OpenNest.Forms
|
|||||||
entityView1.SimplifierPreview = null;
|
entityView1.SimplifierPreview = null;
|
||||||
entityView1.SimplifierToleranceLeft = null;
|
entityView1.SimplifierToleranceLeft = null;
|
||||||
entityView1.SimplifierToleranceRight = null;
|
entityView1.SimplifierToleranceRight = null;
|
||||||
entityView1.Size = new System.Drawing.Size(759, 634);
|
entityView1.Size = new System.Drawing.Size(546, 606);
|
||||||
entityView1.TabIndex = 0;
|
entityView1.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// detailBar
|
// detailBar
|
||||||
@@ -148,7 +156,7 @@ namespace OpenNest.Forms
|
|||||||
detailBar.Location = new System.Drawing.Point(0, 634);
|
detailBar.Location = new System.Drawing.Point(0, 634);
|
||||||
detailBar.Name = "detailBar";
|
detailBar.Name = "detailBar";
|
||||||
detailBar.Padding = new System.Windows.Forms.Padding(4, 6, 4, 4);
|
detailBar.Padding = new System.Windows.Forms.Padding(4, 6, 4, 4);
|
||||||
detailBar.Size = new System.Drawing.Size(759, 36);
|
detailBar.Size = new System.Drawing.Size(546, 36);
|
||||||
detailBar.TabIndex = 1;
|
detailBar.TabIndex = 1;
|
||||||
detailBar.WrapContents = false;
|
detailBar.WrapContents = false;
|
||||||
//
|
//
|
||||||
@@ -334,6 +342,47 @@ namespace OpenNest.Forms
|
|||||||
acceptButton.TabIndex = 1;
|
acceptButton.TabIndex = 1;
|
||||||
acceptButton.Text = "Accept";
|
acceptButton.Text = "Accept";
|
||||||
//
|
//
|
||||||
|
// viewTabs
|
||||||
|
//
|
||||||
|
viewTabs.Controls.Add(tabCadView);
|
||||||
|
viewTabs.Controls.Add(tabProgram);
|
||||||
|
viewTabs.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
viewTabs.Location = new System.Drawing.Point(0, 0);
|
||||||
|
viewTabs.Name = "viewTabs";
|
||||||
|
viewTabs.SelectedIndex = 0;
|
||||||
|
viewTabs.Size = new System.Drawing.Size(759, 670);
|
||||||
|
viewTabs.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// tabCadView
|
||||||
|
//
|
||||||
|
tabCadView.Controls.Add(cadViewSplit);
|
||||||
|
tabCadView.Location = new System.Drawing.Point(4, 24);
|
||||||
|
tabCadView.Name = "tabCadView";
|
||||||
|
tabCadView.Padding = new System.Windows.Forms.Padding(0);
|
||||||
|
tabCadView.Size = new System.Drawing.Size(751, 642);
|
||||||
|
tabCadView.TabIndex = 0;
|
||||||
|
tabCadView.Text = "CAD View";
|
||||||
|
tabCadView.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tabProgram
|
||||||
|
//
|
||||||
|
tabProgram.Controls.Add(programEditor);
|
||||||
|
tabProgram.Location = new System.Drawing.Point(4, 24);
|
||||||
|
tabProgram.Name = "tabProgram";
|
||||||
|
tabProgram.Padding = new System.Windows.Forms.Padding(0);
|
||||||
|
tabProgram.Size = new System.Drawing.Size(751, 642);
|
||||||
|
tabProgram.TabIndex = 1;
|
||||||
|
tabProgram.Text = "Program";
|
||||||
|
tabProgram.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// programEditor
|
||||||
|
//
|
||||||
|
programEditor.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
programEditor.Location = new System.Drawing.Point(0, 0);
|
||||||
|
programEditor.Name = "programEditor";
|
||||||
|
programEditor.Size = new System.Drawing.Size(751, 642);
|
||||||
|
programEditor.TabIndex = 0;
|
||||||
|
//
|
||||||
// CadConverterForm
|
// CadConverterForm
|
||||||
//
|
//
|
||||||
AllowDrop = true;
|
AllowDrop = true;
|
||||||
@@ -353,13 +402,16 @@ namespace OpenNest.Forms
|
|||||||
mainSplit.Panel2.ResumeLayout(false);
|
mainSplit.Panel2.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)mainSplit).EndInit();
|
((System.ComponentModel.ISupportInitialize)mainSplit).EndInit();
|
||||||
mainSplit.ResumeLayout(false);
|
mainSplit.ResumeLayout(false);
|
||||||
sidebarSplit.Panel1.ResumeLayout(false);
|
cadViewSplit.Panel1.ResumeLayout(false);
|
||||||
sidebarSplit.Panel2.ResumeLayout(false);
|
cadViewSplit.Panel2.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)sidebarSplit).EndInit();
|
((System.ComponentModel.ISupportInitialize)cadViewSplit).EndInit();
|
||||||
sidebarSplit.ResumeLayout(false);
|
cadViewSplit.ResumeLayout(false);
|
||||||
detailBar.ResumeLayout(false);
|
detailBar.ResumeLayout(false);
|
||||||
detailBar.PerformLayout();
|
detailBar.PerformLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)numQuantity).EndInit();
|
((System.ComponentModel.ISupportInitialize)numQuantity).EndInit();
|
||||||
|
viewTabs.ResumeLayout(false);
|
||||||
|
tabCadView.ResumeLayout(false);
|
||||||
|
tabProgram.ResumeLayout(false);
|
||||||
bottomPanel1.ResumeLayout(false);
|
bottomPanel1.ResumeLayout(false);
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
@@ -367,7 +419,7 @@ namespace OpenNest.Forms
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.SplitContainer mainSplit;
|
private System.Windows.Forms.SplitContainer mainSplit;
|
||||||
private System.Windows.Forms.SplitContainer sidebarSplit;
|
private System.Windows.Forms.SplitContainer cadViewSplit;
|
||||||
private Controls.FileListControl fileList;
|
private Controls.FileListControl fileList;
|
||||||
private Controls.FilterPanel filterPanel;
|
private Controls.FilterPanel filterPanel;
|
||||||
private Controls.EntityView entityView1;
|
private Controls.EntityView entityView1;
|
||||||
@@ -388,5 +440,9 @@ namespace OpenNest.Forms
|
|||||||
private Controls.BottomPanel bottomPanel1;
|
private Controls.BottomPanel bottomPanel1;
|
||||||
private System.Windows.Forms.Button acceptButton;
|
private System.Windows.Forms.Button acceptButton;
|
||||||
private System.Windows.Forms.Button cancelButton;
|
private System.Windows.Forms.Button cancelButton;
|
||||||
|
private System.Windows.Forms.TabControl viewTabs;
|
||||||
|
private System.Windows.Forms.TabPage tabCadView;
|
||||||
|
private System.Windows.Forms.TabPage tabProgram;
|
||||||
|
private Controls.ProgramEditorControl programEditor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace OpenNest.Forms
|
|||||||
{
|
{
|
||||||
private static int colorIndex;
|
private static int colorIndex;
|
||||||
private SimplifierViewerForm simplifierViewer;
|
private SimplifierViewerForm simplifierViewer;
|
||||||
|
private bool staleProgram = true;
|
||||||
|
|
||||||
public CadConverterForm()
|
public CadConverterForm()
|
||||||
{
|
{
|
||||||
@@ -44,6 +45,8 @@ namespace OpenNest.Forms
|
|||||||
cboBendDetector.Items.Add(detector.Name);
|
cboBendDetector.Items.Add(detector.Name);
|
||||||
cboBendDetector.SelectedIndex = 0;
|
cboBendDetector.SelectedIndex = 0;
|
||||||
|
|
||||||
|
viewTabs.SelectedIndexChanged += OnViewTabChanged;
|
||||||
|
|
||||||
// Drag & drop
|
// Drag & drop
|
||||||
AllowDrop = true;
|
AllowDrop = true;
|
||||||
DragEnter += OnDragEnter;
|
DragEnter += OnDragEnter;
|
||||||
@@ -133,6 +136,11 @@ namespace OpenNest.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadItem(item);
|
LoadItem(item);
|
||||||
|
staleProgram = true;
|
||||||
|
if (viewTabs.SelectedTab == tabProgram)
|
||||||
|
LoadProgramTab();
|
||||||
|
else
|
||||||
|
programEditor.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadItem(FileListItem item)
|
private void LoadItem(FileListItem item)
|
||||||
@@ -153,6 +161,8 @@ namespace OpenNest.Forms
|
|||||||
item.Entities.ForEach(e => e.Layer.IsVisible = true);
|
item.Entities.ForEach(e => e.Layer.IsVisible = true);
|
||||||
ReHidePromotedEntities(item.Bends);
|
ReHidePromotedEntities(item.Bends);
|
||||||
|
|
||||||
|
ApplyContourColors(item.Entities);
|
||||||
|
|
||||||
filterPanel.LoadItem(item.Entities, item.Bends);
|
filterPanel.LoadItem(item.Entities, item.Bends);
|
||||||
|
|
||||||
numQuantity.Value = item.Quantity;
|
numQuantity.Value = item.Quantity;
|
||||||
@@ -168,6 +178,30 @@ namespace OpenNest.Forms
|
|||||||
CheckSimplifiable(item);
|
CheckSimplifiable(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ApplyContourColors(List<Entity> entities)
|
||||||
|
{
|
||||||
|
var visible = entities.Where(e => e.IsVisible && e.Layer != null && e.Layer.IsVisible).ToList();
|
||||||
|
if (visible.Count == 0) return;
|
||||||
|
|
||||||
|
var shapes = ShapeBuilder.GetShapes(visible);
|
||||||
|
if (shapes.Count == 0) return;
|
||||||
|
|
||||||
|
var contours = ContourInfo.Classify(shapes);
|
||||||
|
foreach (var contour in contours)
|
||||||
|
{
|
||||||
|
var color = contour.Type switch
|
||||||
|
{
|
||||||
|
ContourClassification.Perimeter => System.Drawing.Color.FromArgb(80, 180, 120),
|
||||||
|
ContourClassification.Hole => System.Drawing.Color.FromArgb(100, 140, 255),
|
||||||
|
ContourClassification.Etch => System.Drawing.Color.FromArgb(255, 170, 50),
|
||||||
|
ContourClassification.Open => System.Drawing.Color.FromArgb(200, 200, 100),
|
||||||
|
_ => System.Drawing.Color.Gray,
|
||||||
|
};
|
||||||
|
foreach (var entity in contour.Shape.Entities)
|
||||||
|
entity.Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void CheckSimplifiable(FileListItem item)
|
private void CheckSimplifiable(FileListItem item)
|
||||||
{
|
{
|
||||||
ResetSimplifyButton();
|
ResetSimplifyButton();
|
||||||
@@ -229,6 +263,40 @@ namespace OpenNest.Forms
|
|||||||
filterPanel.ApplyFilters(item.Entities);
|
filterPanel.ApplyFilters(item.Entities);
|
||||||
ReHidePromotedEntities(item.Bends);
|
ReHidePromotedEntities(item.Bends);
|
||||||
entityView1.Invalidate();
|
entityView1.Invalidate();
|
||||||
|
staleProgram = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnViewTabChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (viewTabs.SelectedTab == tabProgram && staleProgram)
|
||||||
|
LoadProgramTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadProgramTab()
|
||||||
|
{
|
||||||
|
var item = CurrentItem;
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
programEditor.Clear();
|
||||||
|
staleProgram = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entities = item.Entities.Where(en => en.Layer.IsVisible && en.IsVisible).ToList();
|
||||||
|
if (entities.Count == 0)
|
||||||
|
{
|
||||||
|
programEditor.Clear();
|
||||||
|
staleProgram = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var normalized = ShapeProfile.NormalizeEntities(entities);
|
||||||
|
programEditor.LoadEntities(normalized);
|
||||||
|
staleProgram = false;
|
||||||
|
|
||||||
|
// Refresh CAD view to show contour-type colors
|
||||||
|
entityView1.ClearPenCache();
|
||||||
|
entityView1.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBendLineSelected(object sender, int index)
|
private void OnBendLineSelected(object sender, int index)
|
||||||
@@ -595,7 +663,10 @@ namespace OpenNest.Forms
|
|||||||
pgm.Codes.RemoveAt(0);
|
pgm.Codes.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawing.Program = pgm;
|
if (item == CurrentItem && programEditor.IsDirty && programEditor.Program != null)
|
||||||
|
drawing.Program = programEditor.Program;
|
||||||
|
else
|
||||||
|
drawing.Program = pgm;
|
||||||
drawings.Add(drawing);
|
drawings.Add(drawing);
|
||||||
|
|
||||||
Thread.Sleep(20);
|
Thread.Sleep(20);
|
||||||
|
|||||||
Generated
+1
-37
@@ -38,9 +38,6 @@
|
|||||||
this.qtyColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
this.qtyColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
||||||
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
|
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
|
||||||
this.btnAssignLeadIns = new System.Windows.Forms.ToolStripButton();
|
|
||||||
this.btnPlaceLeadIn = new System.Windows.Forms.ToolStripButton();
|
|
||||||
this.btnRemoveLeadIns = new System.Windows.Forms.ToolStripButton();
|
|
||||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||||
this.drawingListBox1 = new OpenNest.Controls.DrawingListBox();
|
this.drawingListBox1 = new OpenNest.Controls.DrawingListBox();
|
||||||
this.toolStrip2 = new System.Windows.Forms.ToolStrip();
|
this.toolStrip2 = new System.Windows.Forms.ToolStrip();
|
||||||
@@ -136,10 +133,7 @@
|
|||||||
this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
|
this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
|
||||||
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||||
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
this.toolStripButton1,
|
this.toolStripButton1});
|
||||||
this.btnAssignLeadIns,
|
|
||||||
this.btnPlaceLeadIn,
|
|
||||||
this.btnRemoveLeadIns});
|
|
||||||
this.toolStrip1.Location = new System.Drawing.Point(3, 3);
|
this.toolStrip1.Location = new System.Drawing.Point(3, 3);
|
||||||
this.toolStrip1.Name = "toolStrip1";
|
this.toolStrip1.Name = "toolStrip1";
|
||||||
this.toolStrip1.Size = new System.Drawing.Size(227, 31);
|
this.toolStrip1.Size = new System.Drawing.Size(227, 31);
|
||||||
@@ -158,33 +152,6 @@
|
|||||||
this.toolStripButton1.Text = "Calculate Cut Time";
|
this.toolStripButton1.Text = "Calculate Cut Time";
|
||||||
this.toolStripButton1.Click += new System.EventHandler(this.CalculateSelectedPlateCutTime_Click);
|
this.toolStripButton1.Click += new System.EventHandler(this.CalculateSelectedPlateCutTime_Click);
|
||||||
//
|
//
|
||||||
// btnAssignLeadIns
|
|
||||||
//
|
|
||||||
this.btnAssignLeadIns.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
|
||||||
this.btnAssignLeadIns.ImageTransparentColor = System.Drawing.Color.Magenta;
|
|
||||||
this.btnAssignLeadIns.Name = "btnAssignLeadIns";
|
|
||||||
this.btnAssignLeadIns.Size = new System.Drawing.Size(96, 28);
|
|
||||||
this.btnAssignLeadIns.Text = "Assign Lead-ins";
|
|
||||||
this.btnAssignLeadIns.Click += new System.EventHandler(this.AssignLeadIns_Click);
|
|
||||||
//
|
|
||||||
// btnPlaceLeadIn
|
|
||||||
//
|
|
||||||
this.btnPlaceLeadIn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
|
||||||
this.btnPlaceLeadIn.ImageTransparentColor = System.Drawing.Color.Magenta;
|
|
||||||
this.btnPlaceLeadIn.Name = "btnPlaceLeadIn";
|
|
||||||
this.btnPlaceLeadIn.Size = new System.Drawing.Size(90, 28);
|
|
||||||
this.btnPlaceLeadIn.Text = "Place Lead-in";
|
|
||||||
this.btnPlaceLeadIn.Click += new System.EventHandler(this.PlaceLeadIn_Click);
|
|
||||||
//
|
|
||||||
// btnRemoveLeadIns
|
|
||||||
//
|
|
||||||
this.btnRemoveLeadIns.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
|
||||||
this.btnRemoveLeadIns.ImageTransparentColor = System.Drawing.Color.Magenta;
|
|
||||||
this.btnRemoveLeadIns.Name = "btnRemoveLeadIns";
|
|
||||||
this.btnRemoveLeadIns.Size = new System.Drawing.Size(104, 28);
|
|
||||||
this.btnRemoveLeadIns.Text = "Remove Lead-ins";
|
|
||||||
this.btnRemoveLeadIns.Click += new System.EventHandler(this.RemoveLeadIns_Click);
|
|
||||||
//
|
|
||||||
// tabPage2
|
// tabPage2
|
||||||
//
|
//
|
||||||
this.tabPage2.Controls.Add(this.drawingListBox1);
|
this.tabPage2.Controls.Add(this.drawingListBox1);
|
||||||
@@ -299,8 +266,5 @@
|
|||||||
private System.Windows.Forms.ToolStripButton toolStripButton2;
|
private System.Windows.Forms.ToolStripButton toolStripButton2;
|
||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||||
private System.Windows.Forms.ToolStripButton toolStripButton3;
|
private System.Windows.Forms.ToolStripButton toolStripButton3;
|
||||||
private System.Windows.Forms.ToolStripButton btnAssignLeadIns;
|
|
||||||
private System.Windows.Forms.ToolStripButton btnPlaceLeadIn;
|
|
||||||
private System.Windows.Forms.ToolStripButton btnRemoveLeadIns;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -718,7 +718,7 @@ namespace OpenNest.Forms
|
|||||||
CalculateCurrentPlateCutTime();
|
CalculateCurrentPlateCutTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AssignLeadIns_Click(object sender, EventArgs e)
|
public void AssignLeadIns_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (PlateView?.Plate == null)
|
if (PlateView?.Plate == null)
|
||||||
return;
|
return;
|
||||||
@@ -747,7 +747,7 @@ namespace OpenNest.Forms
|
|||||||
PlateView.Invalidate();
|
PlateView.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveLeadIns_Click(object sender, EventArgs e)
|
public void RemoveLeadIns_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (PlateView?.Plate == null)
|
if (PlateView?.Plate == null)
|
||||||
return;
|
return;
|
||||||
@@ -779,7 +779,56 @@ namespace OpenNest.Forms
|
|||||||
PlateView.Invalidate();
|
PlateView.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlaceLeadIn_Click(object sender, EventArgs e)
|
public void AssignLeadInsAllPlates()
|
||||||
|
{
|
||||||
|
if (Nest == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using var form = new CuttingParametersForm();
|
||||||
|
if (form.ShowDialog(this) != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parameters = form.BuildParameters();
|
||||||
|
var assigner = new LeadInAssigner
|
||||||
|
{
|
||||||
|
Sequencer = new LeftSideSequencer()
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var plate in Nest.Plates)
|
||||||
|
{
|
||||||
|
plate.CuttingParameters = parameters;
|
||||||
|
assigner.Assign(plate);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveLeadInsAllPlates()
|
||||||
|
{
|
||||||
|
if (Nest == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var plate in Nest.Plates)
|
||||||
|
{
|
||||||
|
foreach (var part in plate.Parts)
|
||||||
|
{
|
||||||
|
if (part.HasManualLeadIns)
|
||||||
|
part.RemoveLeadIns();
|
||||||
|
}
|
||||||
|
|
||||||
|
plate.CuttingParameters = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var lp in PlateView.Parts)
|
||||||
|
{
|
||||||
|
lp.IsDirty = true;
|
||||||
|
lp.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlaceLeadIn_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (PlateView?.Plate == null)
|
if (PlateView?.Plate == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
Generated
+61
-2
@@ -98,6 +98,9 @@
|
|||||||
mnuNestPost = new System.Windows.Forms.ToolStripMenuItem();
|
mnuNestPost = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
toolStripMenuItem19 = new System.Windows.Forms.ToolStripSeparator();
|
toolStripMenuItem19 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
calculateCutTimeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
calculateCutTimeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
toolStripMenuItem22 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
|
mnuNestAssignLeadIns = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
mnuNestRemoveLeadIns = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuPlate = new System.Windows.Forms.ToolStripMenuItem();
|
mnuPlate = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuPlateEdit = new System.Windows.Forms.ToolStripMenuItem();
|
mnuPlateEdit = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuPlateSetAsDefault = new System.Windows.Forms.ToolStripMenuItem();
|
mnuPlateSetAsDefault = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
@@ -120,6 +123,10 @@
|
|||||||
calculateCutTimeToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
calculateCutTimeToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
centerPartsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
centerPartsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuPlateCutOff = new System.Windows.Forms.ToolStripMenuItem();
|
mnuPlateCutOff = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
toolStripMenuItem21 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
|
mnuPlateAssignLeadIns = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
mnuPlatePlaceLeadIn = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
mnuPlateRemoveLeadIns = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuWindow = new System.Windows.Forms.ToolStripMenuItem();
|
mnuWindow = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuWindowCascade = new System.Windows.Forms.ToolStripMenuItem();
|
mnuWindowCascade = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
mnuWindowTileVertical = new System.Windows.Forms.ToolStripMenuItem();
|
mnuWindowTileVertical = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
@@ -552,7 +559,7 @@
|
|||||||
//
|
//
|
||||||
// mnuNest
|
// mnuNest
|
||||||
//
|
//
|
||||||
mnuNest.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuNestEdit, mnuNestImportDrawing, toolStripMenuItem7, mnuNestFirstPlate, mnuNestLastPlate, toolStripMenuItem6, mnuNestNextPlate, mnuNestPreviousPlate, toolStripMenuItem12, runAutoNestToolStripMenuItem, autoSequenceAllPlatesToolStripMenuItem, mnuNestRemoveEmptyPlates, mnuNestPost, toolStripMenuItem19, calculateCutTimeToolStripMenuItem });
|
mnuNest.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuNestEdit, mnuNestImportDrawing, toolStripMenuItem7, mnuNestFirstPlate, mnuNestLastPlate, toolStripMenuItem6, mnuNestNextPlate, mnuNestPreviousPlate, toolStripMenuItem12, runAutoNestToolStripMenuItem, autoSequenceAllPlatesToolStripMenuItem, mnuNestRemoveEmptyPlates, mnuNestPost, toolStripMenuItem19, calculateCutTimeToolStripMenuItem, toolStripMenuItem22, mnuNestAssignLeadIns, mnuNestRemoveLeadIns });
|
||||||
mnuNest.Name = "mnuNest";
|
mnuNest.Name = "mnuNest";
|
||||||
mnuNest.Size = new System.Drawing.Size(43, 20);
|
mnuNest.Size = new System.Drawing.Size(43, 20);
|
||||||
mnuNest.Text = "&Nest";
|
mnuNest.Text = "&Nest";
|
||||||
@@ -660,9 +667,28 @@
|
|||||||
calculateCutTimeToolStripMenuItem.Text = "Calculate Cut Time";
|
calculateCutTimeToolStripMenuItem.Text = "Calculate Cut Time";
|
||||||
calculateCutTimeToolStripMenuItem.Click += CalculateNestCutTime_Click;
|
calculateCutTimeToolStripMenuItem.Click += CalculateNestCutTime_Click;
|
||||||
//
|
//
|
||||||
|
// toolStripMenuItem22
|
||||||
|
//
|
||||||
|
toolStripMenuItem22.Name = "toolStripMenuItem22";
|
||||||
|
toolStripMenuItem22.Size = new System.Drawing.Size(202, 6);
|
||||||
|
//
|
||||||
|
// mnuNestAssignLeadIns
|
||||||
|
//
|
||||||
|
mnuNestAssignLeadIns.Name = "mnuNestAssignLeadIns";
|
||||||
|
mnuNestAssignLeadIns.Size = new System.Drawing.Size(205, 22);
|
||||||
|
mnuNestAssignLeadIns.Text = "Assign Lead-ins (All Plates)";
|
||||||
|
mnuNestAssignLeadIns.Click += NestAssignLeadIns_Click;
|
||||||
|
//
|
||||||
|
// mnuNestRemoveLeadIns
|
||||||
|
//
|
||||||
|
mnuNestRemoveLeadIns.Name = "mnuNestRemoveLeadIns";
|
||||||
|
mnuNestRemoveLeadIns.Size = new System.Drawing.Size(205, 22);
|
||||||
|
mnuNestRemoveLeadIns.Text = "Remove Lead-ins (All Plates)";
|
||||||
|
mnuNestRemoveLeadIns.Click += NestRemoveLeadIns_Click;
|
||||||
|
//
|
||||||
// mnuPlate
|
// mnuPlate
|
||||||
//
|
//
|
||||||
mnuPlate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuPlateEdit, mnuPlateSetAsDefault, toolStripMenuItem18, mnuPlateAdd, mnuPlateRemove, toolStripMenuItem16, mnuPlateCutOff, mnuPlateRotate, mnuResizeToFitParts, toolStripMenuItem13, mnuPlateViewInCad, toolStripMenuItem20, mnuSequenceParts, calculateCutTimeToolStripMenuItem1, centerPartsToolStripMenuItem });
|
mnuPlate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuPlateEdit, mnuPlateSetAsDefault, toolStripMenuItem18, mnuPlateAdd, mnuPlateRemove, toolStripMenuItem16, mnuPlateCutOff, mnuPlateRotate, mnuResizeToFitParts, toolStripMenuItem13, mnuPlateViewInCad, toolStripMenuItem20, mnuSequenceParts, calculateCutTimeToolStripMenuItem1, centerPartsToolStripMenuItem, toolStripMenuItem21, mnuPlateAssignLeadIns, mnuPlatePlaceLeadIn, mnuPlateRemoveLeadIns });
|
||||||
mnuPlate.Name = "mnuPlate";
|
mnuPlate.Name = "mnuPlate";
|
||||||
mnuPlate.Size = new System.Drawing.Size(45, 20);
|
mnuPlate.Size = new System.Drawing.Size(45, 20);
|
||||||
mnuPlate.Text = "&Plate";
|
mnuPlate.Text = "&Plate";
|
||||||
@@ -809,6 +835,32 @@
|
|||||||
centerPartsToolStripMenuItem.Text = "Center Parts";
|
centerPartsToolStripMenuItem.Text = "Center Parts";
|
||||||
centerPartsToolStripMenuItem.Click += centerPartsToolStripMenuItem_Click;
|
centerPartsToolStripMenuItem.Click += centerPartsToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
|
// toolStripMenuItem21
|
||||||
|
//
|
||||||
|
toolStripMenuItem21.Name = "toolStripMenuItem21";
|
||||||
|
toolStripMenuItem21.Size = new System.Drawing.Size(174, 6);
|
||||||
|
//
|
||||||
|
// mnuPlateAssignLeadIns
|
||||||
|
//
|
||||||
|
mnuPlateAssignLeadIns.Name = "mnuPlateAssignLeadIns";
|
||||||
|
mnuPlateAssignLeadIns.Size = new System.Drawing.Size(177, 22);
|
||||||
|
mnuPlateAssignLeadIns.Text = "Assign Lead-ins";
|
||||||
|
mnuPlateAssignLeadIns.Click += PlateAssignLeadIns_Click;
|
||||||
|
//
|
||||||
|
// mnuPlatePlaceLeadIn
|
||||||
|
//
|
||||||
|
mnuPlatePlaceLeadIn.Name = "mnuPlatePlaceLeadIn";
|
||||||
|
mnuPlatePlaceLeadIn.Size = new System.Drawing.Size(177, 22);
|
||||||
|
mnuPlatePlaceLeadIn.Text = "Place Lead-in";
|
||||||
|
mnuPlatePlaceLeadIn.Click += PlatePlaceLeadIn_Click;
|
||||||
|
//
|
||||||
|
// mnuPlateRemoveLeadIns
|
||||||
|
//
|
||||||
|
mnuPlateRemoveLeadIns.Name = "mnuPlateRemoveLeadIns";
|
||||||
|
mnuPlateRemoveLeadIns.Size = new System.Drawing.Size(177, 22);
|
||||||
|
mnuPlateRemoveLeadIns.Text = "Remove Lead-ins";
|
||||||
|
mnuPlateRemoveLeadIns.Click += PlateRemoveLeadIns_Click;
|
||||||
|
//
|
||||||
// mnuWindow
|
// mnuWindow
|
||||||
//
|
//
|
||||||
mnuWindow.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuWindowCascade, mnuWindowTileVertical, mnuWindowTileHorizontal, toolStripMenuItem10, closeToolStripMenuItem, mnuCloseAll });
|
mnuWindow.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuWindowCascade, mnuWindowTileVertical, mnuWindowTileHorizontal, toolStripMenuItem10, closeToolStripMenuItem, mnuCloseAll });
|
||||||
@@ -1257,5 +1309,12 @@
|
|||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
|
||||||
private System.Windows.Forms.ToolStripButton btnCutOff;
|
private System.Windows.Forms.ToolStripButton btnCutOff;
|
||||||
private System.Windows.Forms.ToolStripMenuItem mnuPlateCutOff;
|
private System.Windows.Forms.ToolStripMenuItem mnuPlateCutOff;
|
||||||
|
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem21;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem mnuPlateAssignLeadIns;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem mnuPlatePlaceLeadIn;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem mnuPlateRemoveLeadIns;
|
||||||
|
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem22;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem mnuNestAssignLeadIns;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem mnuNestRemoveLeadIns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1066,6 +1066,18 @@ namespace OpenNest.Forms
|
|||||||
activeForm.CalculateNestCutTime();
|
activeForm.CalculateNestCutTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void NestAssignLeadIns_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (activeForm == null) return;
|
||||||
|
activeForm.AssignLeadInsAllPlates();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NestRemoveLeadIns_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (activeForm == null) return;
|
||||||
|
activeForm.RemoveLeadInsAllPlates();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Nest Menu Events
|
#endregion Nest Menu Events
|
||||||
|
|
||||||
#region Plate Menu Events
|
#region Plate Menu Events
|
||||||
@@ -1158,6 +1170,24 @@ namespace OpenNest.Forms
|
|||||||
activeForm.PlateView.SetAction(typeof(ActionCutOff));
|
activeForm.PlateView.SetAction(typeof(ActionCutOff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PlateAssignLeadIns_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (activeForm == null) return;
|
||||||
|
activeForm.AssignLeadIns_Click(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlatePlaceLeadIn_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (activeForm == null) return;
|
||||||
|
activeForm.PlaceLeadIn_Click(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlateRemoveLeadIns_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (activeForm == null) return;
|
||||||
|
activeForm.RemoveLeadIns_Click(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Plate Menu Events
|
#endregion Plate Menu Events
|
||||||
|
|
||||||
#region Window Menu Events
|
#region Window Menu Events
|
||||||
|
|||||||
Reference in New Issue
Block a user