733 lines
26 KiB
C#
733 lines
26 KiB
C#
using OpenNest.Bending;
|
|
using OpenNest.CNC;
|
|
using OpenNest.Controls;
|
|
using OpenNest.Converters;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.IO;
|
|
using OpenNest.IO.Bending;
|
|
using OpenNest.Properties;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace OpenNest.Forms
|
|
{
|
|
public partial class CadConverterForm : Form
|
|
{
|
|
private static int colorIndex;
|
|
private SimplifierViewerForm simplifierViewer;
|
|
private bool staleProgram = true;
|
|
|
|
public CadConverterForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
fileList.SelectedIndexChanged += OnFileSelected;
|
|
filterPanel.FilterChanged += OnFilterChanged;
|
|
filterPanel.BendLineSelected += OnBendLineSelected;
|
|
filterPanel.BendLineRemoved += OnBendLineRemoved;
|
|
filterPanel.AddBendLineClicked += OnAddBendLineClicked;
|
|
entityView1.LinePicked += OnLinePicked;
|
|
entityView1.PickCancelled += OnPickCancelled;
|
|
btnSplit.Click += OnSplitClicked;
|
|
numQuantity.ValueChanged += OnQuantityChanged;
|
|
txtCustomer.TextChanged += OnCustomerChanged;
|
|
cboBendDetector.SelectedIndexChanged += OnBendDetectorChanged;
|
|
|
|
// Populate bend detector dropdown
|
|
cboBendDetector.Items.Add("Auto");
|
|
foreach (var detector in BendDetectorRegistry.Detectors)
|
|
cboBendDetector.Items.Add(detector.Name);
|
|
cboBendDetector.SelectedIndex = 0;
|
|
|
|
viewTabs.SelectedIndexChanged += OnViewTabChanged;
|
|
|
|
// Drag & drop
|
|
AllowDrop = true;
|
|
DragEnter += OnDragEnter;
|
|
DragDrop += OnDragDrop;
|
|
}
|
|
|
|
private FileListItem CurrentItem => fileList.SelectedItem;
|
|
|
|
#region File Import
|
|
|
|
public void AddFile(string file) => AddFile(file, 0, null);
|
|
|
|
private void AddFile(string file, int detectorIndex, string detectorName)
|
|
{
|
|
try
|
|
{
|
|
var importer = new DxfImporter();
|
|
importer.SplinePrecision = Settings.Default.ImportSplinePrecision;
|
|
var result = importer.Import(file);
|
|
|
|
if (result.Entities.Count == 0)
|
|
return;
|
|
|
|
// Compute bounds
|
|
var bounds = result.Entities.GetBoundingBox();
|
|
|
|
// Detect bends (detectorIndex/Name captured on UI thread)
|
|
var bends = new List<Bend>();
|
|
if (result.Document != null)
|
|
{
|
|
bends = detectorIndex == 0
|
|
? BendDetectorRegistry.AutoDetect(result.Document)
|
|
: BendDetectorRegistry.GetByName(detectorName)
|
|
?.DetectBends(result.Document)
|
|
?? new List<Bend>();
|
|
}
|
|
|
|
Bend.UpdateEtchEntities(result.Entities, bends);
|
|
|
|
var item = new FileListItem
|
|
{
|
|
Name = Path.GetFileNameWithoutExtension(file),
|
|
Entities = result.Entities,
|
|
Path = file,
|
|
Quantity = 1,
|
|
Customer = string.Empty,
|
|
Bends = bends,
|
|
Bounds = bounds,
|
|
EntityCount = result.Entities.Count
|
|
};
|
|
|
|
if (InvokeRequired)
|
|
BeginInvoke((Action)(() => fileList.AddItem(item)));
|
|
else
|
|
fileList.AddItem(item);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Error importing \"{file}\": {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public void AddFiles(IEnumerable<string> files)
|
|
{
|
|
var fileArray = files.ToArray();
|
|
// Capture UI state on main thread before entering parallel loop
|
|
var detectorIndex = cboBendDetector.SelectedIndex;
|
|
var detectorName = cboBendDetector.SelectedItem?.ToString();
|
|
|
|
System.Threading.Tasks.Task.Run(() =>
|
|
{
|
|
Parallel.ForEach(fileArray, file => AddFile(file, detectorIndex, detectorName));
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Event Handlers
|
|
|
|
private void OnFileSelected(object sender, int index)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item == null)
|
|
{
|
|
ClearDetailBar();
|
|
return;
|
|
}
|
|
|
|
LoadItem(item);
|
|
staleProgram = true;
|
|
if (viewTabs.SelectedTab == tabProgram)
|
|
LoadProgramTab();
|
|
else
|
|
programEditor.Clear();
|
|
}
|
|
|
|
private void LoadItem(FileListItem item)
|
|
{
|
|
entityView1.ClearPenCache();
|
|
if (entityView1.IsPickingBendLine)
|
|
{
|
|
entityView1.IsPickingBendLine = false;
|
|
filterPanel.SetPickMode(false);
|
|
}
|
|
entityView1.OriginalEntities = chkShowOriginal.Checked ? item.OriginalEntities : null;
|
|
entityView1.Entities.Clear();
|
|
entityView1.Entities.AddRange(item.Entities);
|
|
entityView1.Bends = item.Bends ?? new List<Bend>();
|
|
|
|
item.Entities.ForEach(e => e.IsVisible = true);
|
|
if (item.Entities.Any(e => e.Layer != null))
|
|
item.Entities.ForEach(e => e.Layer.IsVisible = true);
|
|
ReHidePromotedEntities(item.Bends);
|
|
|
|
ApplyContourColors(item.Entities);
|
|
|
|
filterPanel.LoadItem(item.Entities, item.Bends);
|
|
|
|
numQuantity.Value = item.Quantity;
|
|
txtCustomer.Text = item.Customer ?? "";
|
|
|
|
var bounds = item.Bounds;
|
|
lblDimensions.Text = bounds != null
|
|
? $"{bounds.Width:0.#} x {bounds.Length:0.#}"
|
|
: "";
|
|
lblEntityCount.Text = $"{item.EntityCount} entities";
|
|
|
|
entityView1.ZoomToFit();
|
|
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)
|
|
{
|
|
ResetSimplifyButton();
|
|
|
|
// Only check original (unsimplified) entities
|
|
var entities = item.OriginalEntities ?? item.Entities;
|
|
if (entities == null || entities.Count < 10) return;
|
|
|
|
// Quick line count check — need at least MinLines consecutive lines
|
|
var lineCount = entities.Count(e => e is Geometry.Line);
|
|
if (lineCount < 3) return;
|
|
|
|
// Run a quick analysis on a background thread
|
|
var capturedEntities = new List<Entity>(entities);
|
|
Task.Run(() =>
|
|
{
|
|
var shapes = ShapeBuilder.GetShapes(capturedEntities);
|
|
var simplifier = new GeometrySimplifier();
|
|
var count = 0;
|
|
foreach (var shape in shapes)
|
|
count += simplifier.Analyze(shape).Count;
|
|
return count;
|
|
}).ContinueWith(t =>
|
|
{
|
|
if (t.IsCompletedSuccessfully && t.Result > 0)
|
|
HighlightSimplifyButton(t.Result);
|
|
}, TaskScheduler.FromCurrentSynchronizationContext());
|
|
}
|
|
|
|
private void HighlightSimplifyButton(int candidateCount)
|
|
{
|
|
btnSimplify.Text = $"Simplify ({candidateCount})";
|
|
btnSimplify.BackColor = Color.FromArgb(60, 120, 60);
|
|
btnSimplify.ForeColor = Color.White;
|
|
}
|
|
|
|
private void ResetSimplifyButton()
|
|
{
|
|
btnSimplify.Text = "Simplify...";
|
|
btnSimplify.BackColor = SystemColors.Control;
|
|
btnSimplify.ForeColor = SystemColors.ControlText;
|
|
}
|
|
|
|
private void ClearDetailBar()
|
|
{
|
|
numQuantity.Value = 1;
|
|
txtCustomer.Text = "";
|
|
lblDimensions.Text = "";
|
|
lblEntityCount.Text = "";
|
|
entityView1.Entities.Clear();
|
|
entityView1.Invalidate();
|
|
}
|
|
|
|
private void OnFilterChanged(object sender, EventArgs e)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item == null) return;
|
|
|
|
filterPanel.ApplyFilters(item.Entities);
|
|
ReHidePromotedEntities(item.Bends);
|
|
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)
|
|
{
|
|
entityView1.SelectedBendIndex = index;
|
|
entityView1.Invalidate();
|
|
}
|
|
|
|
private void OnBendLineRemoved(object sender, int index)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item == null || index < 0 || index >= item.Bends.Count) return;
|
|
|
|
var bend = item.Bends[index];
|
|
if (bend.SourceEntity != null)
|
|
bend.SourceEntity.IsVisible = true;
|
|
|
|
item.Bends.RemoveAt(index);
|
|
Bend.UpdateEtchEntities(item.Entities, item.Bends);
|
|
entityView1.Entities.Clear();
|
|
entityView1.Entities.AddRange(item.Entities);
|
|
entityView1.Bends = item.Bends;
|
|
entityView1.SelectedBendIndex = -1;
|
|
filterPanel.LoadItem(item.Entities, item.Bends);
|
|
entityView1.Invalidate();
|
|
}
|
|
|
|
private void OnQuantityChanged(object sender, EventArgs e)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item == null) return;
|
|
|
|
item.Quantity = (int)numQuantity.Value;
|
|
fileList.Invalidate();
|
|
}
|
|
|
|
private void OnCustomerChanged(object sender, EventArgs e)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item != null)
|
|
item.Customer = txtCustomer.Text;
|
|
}
|
|
|
|
private void OnBendDetectorChanged(object sender, EventArgs e)
|
|
{
|
|
// Re-run bend detection on current item if it has a document
|
|
// For now, bend detection only runs at import time
|
|
}
|
|
|
|
private void OnSplitClicked(object sender, EventArgs e)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item == null) return;
|
|
|
|
var entities = item.Entities.Where(en => en.Layer.IsVisible && en.IsVisible).ToList();
|
|
if (entities.Count == 0) return;
|
|
|
|
var normalized = ShapeProfile.NormalizeEntities(entities);
|
|
var pgm = ConvertGeometry.ToProgram(normalized);
|
|
var originOffset = Vector.Zero;
|
|
if (pgm.Codes.Count > 0 && pgm[0].Type == CodeType.RapidMove)
|
|
{
|
|
var rapid = (RapidMove)pgm[0];
|
|
originOffset = rapid.EndPoint;
|
|
pgm.Offset(-originOffset);
|
|
pgm.Codes.RemoveAt(0);
|
|
}
|
|
|
|
var drawing = new Drawing(item.Name, pgm);
|
|
drawing.Bends = item.Bends.Select(b => new Bend
|
|
{
|
|
StartPoint = new Vector(b.StartPoint.X - originOffset.X, b.StartPoint.Y - originOffset.Y),
|
|
EndPoint = new Vector(b.EndPoint.X - originOffset.X, b.EndPoint.Y - originOffset.Y),
|
|
Direction = b.Direction,
|
|
Angle = b.Angle,
|
|
Radius = b.Radius,
|
|
NoteText = b.NoteText,
|
|
}).ToList();
|
|
|
|
using var form = new SplitDrawingForm(drawing);
|
|
if (form.ShowDialog(this) != DialogResult.OK || form.ResultDrawings?.Count <= 1)
|
|
return;
|
|
|
|
// Write split DXF files and re-import
|
|
var sourceDir = Path.GetDirectoryName(item.Path);
|
|
var baseName = Path.GetFileNameWithoutExtension(item.Path);
|
|
var writableDir = Directory.Exists(sourceDir) && IsDirectoryWritable(sourceDir)
|
|
? sourceDir
|
|
: Path.GetTempPath();
|
|
|
|
var index = fileList.SelectedIndex;
|
|
var newItems = new List<string>();
|
|
|
|
var splitWriter = new SplitDxfWriter();
|
|
var splitItems = new List<FileListItem>();
|
|
|
|
for (var i = 0; i < form.ResultDrawings.Count; i++)
|
|
{
|
|
var splitDrawing = form.ResultDrawings[i];
|
|
|
|
var splitName = $"{baseName}-{i + 1}.dxf";
|
|
var splitPath = GetUniquePath(Path.Combine(writableDir, splitName));
|
|
|
|
splitWriter.Write(splitPath, splitDrawing);
|
|
newItems.Add(splitPath);
|
|
|
|
// Re-import geometry but keep bends from the split drawing
|
|
var importer = new DxfImporter();
|
|
importer.SplinePrecision = Settings.Default.ImportSplinePrecision;
|
|
var result = importer.Import(splitPath);
|
|
|
|
var splitItem = new FileListItem
|
|
{
|
|
Name = Path.GetFileNameWithoutExtension(splitPath),
|
|
Entities = result.Entities,
|
|
Path = splitPath,
|
|
Quantity = item.Quantity,
|
|
Customer = item.Customer,
|
|
Bends = splitDrawing.Bends ?? new List<Bend>(),
|
|
Bounds = result.Entities.GetBoundingBox(),
|
|
EntityCount = result.Entities.Count
|
|
};
|
|
splitItems.Add(splitItem);
|
|
}
|
|
|
|
// Remove original and add split items directly (preserving bend info)
|
|
fileList.RemoveAt(index);
|
|
foreach (var splitItem in splitItems)
|
|
fileList.AddItem(splitItem);
|
|
|
|
if (writableDir != sourceDir)
|
|
MessageBox.Show($"Split files written to: {writableDir}", "Split Output",
|
|
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
private void OnAddBendLineClicked(object sender, EventArgs e)
|
|
{
|
|
var active = !entityView1.IsPickingBendLine;
|
|
entityView1.IsPickingBendLine = active;
|
|
filterPanel.SetPickMode(active);
|
|
}
|
|
|
|
private void OnLinePicked(object sender, Line line)
|
|
{
|
|
using var dialog = new BendLineDialog();
|
|
if (dialog.ShowDialog(this) != DialogResult.OK)
|
|
return;
|
|
|
|
var item = CurrentItem;
|
|
if (item == null) return;
|
|
|
|
var bend = new Bend
|
|
{
|
|
StartPoint = line.StartPoint,
|
|
EndPoint = line.EndPoint,
|
|
Direction = dialog.Direction,
|
|
Angle = dialog.BendAngle,
|
|
Radius = dialog.BendRadius,
|
|
SourceEntity = line
|
|
};
|
|
|
|
line.IsVisible = false;
|
|
item.Bends.Add(bend);
|
|
Bend.UpdateEtchEntities(item.Entities, item.Bends);
|
|
entityView1.Entities.Clear();
|
|
entityView1.Entities.AddRange(item.Entities);
|
|
entityView1.Bends = item.Bends;
|
|
filterPanel.LoadItem(item.Entities, item.Bends);
|
|
entityView1.Invalidate();
|
|
}
|
|
|
|
private void OnPickCancelled(object sender, EventArgs e)
|
|
{
|
|
entityView1.IsPickingBendLine = false;
|
|
filterPanel.SetPickMode(false);
|
|
}
|
|
|
|
private void OnDragEnter(object sender, DragEventArgs e)
|
|
{
|
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
|
e.Effect = DragDropEffects.Copy;
|
|
}
|
|
|
|
private void OnDragDrop(object sender, DragEventArgs e)
|
|
{
|
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
|
{
|
|
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
|
var dxfFiles = files.Where(f =>
|
|
f.EndsWith(".dxf", StringComparison.OrdinalIgnoreCase)).ToArray();
|
|
if (dxfFiles.Length > 0)
|
|
AddFiles(dxfFiles);
|
|
}
|
|
}
|
|
|
|
private void OnSimplifyClick(object sender, EventArgs e)
|
|
{
|
|
if (entityView1.Entities == null || entityView1.Entities.Count == 0)
|
|
return;
|
|
|
|
// Always simplify from original geometry to prevent tolerance creep
|
|
var item = CurrentItem;
|
|
if (item != null && item.OriginalEntities == null)
|
|
item.OriginalEntities = new List<Entity>(item.Entities);
|
|
|
|
var sourceEntities = item?.OriginalEntities ?? entityView1.Entities;
|
|
var shapes = ShapeBuilder.GetShapes(sourceEntities);
|
|
if (shapes.Count == 0)
|
|
return;
|
|
|
|
if (simplifierViewer == null || simplifierViewer.IsDisposed)
|
|
{
|
|
simplifierViewer = new SimplifierViewerForm();
|
|
simplifierViewer.Owner = this;
|
|
simplifierViewer.Applied += OnSimplifierApplied;
|
|
|
|
// Position next to this form
|
|
var screen = Screen.FromControl(this);
|
|
simplifierViewer.Location = new Point(
|
|
System.Math.Min(Right, screen.WorkingArea.Right - simplifierViewer.Width),
|
|
Top);
|
|
}
|
|
|
|
simplifierViewer.LoadShapes(shapes, entityView1);
|
|
}
|
|
|
|
private void OnSimplifierApplied(List<Entity> entities)
|
|
{
|
|
entityView1.Entities.Clear();
|
|
entityView1.Entities.AddRange(entities);
|
|
entityView1.ZoomToFit();
|
|
entityView1.Invalidate();
|
|
|
|
var item = CurrentItem;
|
|
if (item != null)
|
|
{
|
|
item.Entities = entities;
|
|
item.EntityCount = entities.Count;
|
|
item.Bounds = entities.GetBoundingBox();
|
|
}
|
|
|
|
lblEntityCount.Text = $"{entities.Count} entities";
|
|
ResetSimplifyButton();
|
|
}
|
|
|
|
private void OnShowOriginalChanged(object sender, EventArgs e)
|
|
{
|
|
var item = CurrentItem;
|
|
entityView1.OriginalEntities = chkShowOriginal.Checked ? item?.OriginalEntities : null;
|
|
entityView1.Invalidate();
|
|
}
|
|
|
|
private void OnLabelsChanged(object sender, EventArgs e)
|
|
{
|
|
entityView1.ShowEntityLabels = chkLabels.Checked;
|
|
entityView1.Invalidate();
|
|
}
|
|
|
|
private void OnExportDxfClick(object sender, EventArgs e)
|
|
{
|
|
var item = CurrentItem;
|
|
if (item == null) return;
|
|
|
|
using var dlg = new SaveFileDialog
|
|
{
|
|
Filter = "DXF 2018 (*.dxf)|*.dxf|" +
|
|
"DXF 2013 (*.dxf)|*.dxf|" +
|
|
"DXF 2010 (*.dxf)|*.dxf|" +
|
|
"DXF 2007 (*.dxf)|*.dxf|" +
|
|
"DXF 2004 (*.dxf)|*.dxf|" +
|
|
"DXF 2000 (*.dxf)|*.dxf|" +
|
|
"DXF R14 (*.dxf)|*.dxf",
|
|
FileName = Path.ChangeExtension(item.Name, ".dxf"),
|
|
};
|
|
|
|
if (dlg.ShowDialog() != DialogResult.OK) return;
|
|
|
|
var version = dlg.FilterIndex switch
|
|
{
|
|
2 => ACadSharp.ACadVersion.AC1027,
|
|
3 => ACadSharp.ACadVersion.AC1024,
|
|
4 => ACadSharp.ACadVersion.AC1021,
|
|
5 => ACadSharp.ACadVersion.AC1018,
|
|
6 => ACadSharp.ACadVersion.AC1015,
|
|
7 => ACadSharp.ACadVersion.AC1014,
|
|
_ => ACadSharp.ACadVersion.AC1032,
|
|
};
|
|
|
|
var doc = new ACadSharp.CadDocument(version);
|
|
foreach (var entity in item.Entities)
|
|
{
|
|
switch (entity)
|
|
{
|
|
case Geometry.Line line:
|
|
doc.Entities.Add(new ACadSharp.Entities.Line
|
|
{
|
|
StartPoint = new CSMath.XYZ(line.StartPoint.X, line.StartPoint.Y, 0),
|
|
EndPoint = new CSMath.XYZ(line.EndPoint.X, line.EndPoint.Y, 0),
|
|
});
|
|
break;
|
|
|
|
case Geometry.Arc arc:
|
|
var startAngle = arc.StartAngle;
|
|
var endAngle = arc.EndAngle;
|
|
if (arc.IsReversed)
|
|
OpenNest.Math.Generic.Swap(ref startAngle, ref endAngle);
|
|
doc.Entities.Add(new ACadSharp.Entities.Arc
|
|
{
|
|
Center = new CSMath.XYZ(arc.Center.X, arc.Center.Y, 0),
|
|
Radius = arc.Radius,
|
|
StartAngle = startAngle,
|
|
EndAngle = endAngle,
|
|
});
|
|
break;
|
|
|
|
case Geometry.Circle circle:
|
|
doc.Entities.Add(new ACadSharp.Entities.Circle
|
|
{
|
|
Center = new CSMath.XYZ(circle.Center.X, circle.Center.Y, 0),
|
|
Radius = circle.Radius,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
using var writer = new ACadSharp.IO.DxfWriter(dlg.FileName, doc, false);
|
|
writer.Write();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Output
|
|
|
|
public List<Drawing> GetDrawings()
|
|
{
|
|
var drawings = new List<Drawing>();
|
|
|
|
foreach (var item in fileList.Items)
|
|
{
|
|
var entities = item.Entities.Where(e => e.Layer.IsVisible && e.IsVisible).ToList();
|
|
|
|
if (entities.Count == 0)
|
|
continue;
|
|
|
|
var drawing = new Drawing(item.Name);
|
|
drawing.Color = GetNextColor();
|
|
drawing.Customer = item.Customer;
|
|
drawing.Source.Path = item.Path;
|
|
drawing.Quantity.Required = item.Quantity;
|
|
|
|
// Copy bends
|
|
if (item.Bends != null)
|
|
drawing.Bends.AddRange(item.Bends);
|
|
|
|
var normalized = ShapeProfile.NormalizeEntities(entities);
|
|
var pgm = ConvertGeometry.ToProgram(normalized);
|
|
var firstCode = pgm[0];
|
|
|
|
if (firstCode.Type == CodeType.RapidMove)
|
|
{
|
|
var rapid = (RapidMove)firstCode;
|
|
drawing.Source.Offset = rapid.EndPoint;
|
|
pgm.Offset(-rapid.EndPoint);
|
|
pgm.Codes.RemoveAt(0);
|
|
}
|
|
|
|
if (item == CurrentItem && programEditor.IsDirty && programEditor.Program != null)
|
|
drawing.Program = programEditor.Program;
|
|
else
|
|
drawing.Program = pgm;
|
|
drawings.Add(drawing);
|
|
|
|
Thread.Sleep(20);
|
|
}
|
|
|
|
return drawings;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helpers
|
|
|
|
private static void ReHidePromotedEntities(List<Bend> bends)
|
|
{
|
|
if (bends == null) return;
|
|
foreach (var bend in bends)
|
|
{
|
|
if (bend.SourceEntity != null)
|
|
bend.SourceEntity.IsVisible = false;
|
|
}
|
|
}
|
|
|
|
|
|
private static Color GetNextColor()
|
|
{
|
|
var color = ColorScheme.PartColors[colorIndex % ColorScheme.PartColors.Length];
|
|
colorIndex++;
|
|
return color;
|
|
}
|
|
|
|
private static bool IsDirectoryWritable(string path)
|
|
{
|
|
try
|
|
{
|
|
var testFile = Path.Combine(path, $".writetest_{Guid.NewGuid()}");
|
|
File.WriteAllText(testFile, "");
|
|
File.Delete(testFile);
|
|
return true;
|
|
}
|
|
catch { return false; }
|
|
}
|
|
|
|
private static string GetUniquePath(string path)
|
|
{
|
|
if (!File.Exists(path)) return path;
|
|
|
|
var dir = Path.GetDirectoryName(path);
|
|
var name = Path.GetFileNameWithoutExtension(path);
|
|
var ext = Path.GetExtension(path);
|
|
var counter = 2;
|
|
|
|
while (File.Exists(path))
|
|
{
|
|
path = Path.Combine(dir, $"{name}_{counter}{ext}");
|
|
counter++;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|