mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-19 23:16:26 +02:00
* (Add) Tools: Warn where layer preview is critical for use the tool, must disable layer rotation first (#100) * (Add) CWS: Bottom lift speed property * (Add) CWS: Support Wanhao Workshop CWX and Wanhao Creation Workshop file types (#98) * (Add) CWS: Split format into virtual extensions (.cws, .rgb.cws, .xml.cws) to support diferent file formats and diferent printers under same main .cws extensions. That will affect file converts only to let UVtools know what type of encoding to use. Load and save a xxx.cws file will always auto decode/encode the file for the correct target format no matter the extension. * (Improvement) CWS: It no longer search for a specific filename in the zip file, instead it look for extension to get the files to ensure it always found them no matter the file name system * (Fix) CWS: When "Save as" the file were generating sub files with .cws extension, eg: filename0001.cws.png * (Change) Allow read empty layers without error from Anycubic files (PWS, PW0, PWxx) due a bug on slicer software under macOS
267 lines
8.1 KiB
C#
267 lines
8.1 KiB
C#
/*
|
|
* GNU AFFERO GENERAL PUBLIC LICENSE
|
|
* Version 3, 19 November 2007
|
|
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
* Everyone is permitted to copy and distribute verbatim copies
|
|
* of this license document, but changing it is not allowed.
|
|
*/
|
|
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using UVtools.Core.Objects;
|
|
|
|
namespace UVtools.Core.Operations
|
|
{
|
|
[Serializable]
|
|
public class OperationPattern : Operation
|
|
{
|
|
private Enumerations.Anchor _anchor = Enumerations.Anchor.None;
|
|
private ushort _colSpacing;
|
|
private ushort _rowSpacing;
|
|
private ushort _maxColSpacing;
|
|
private ushort _maxRowSpacing;
|
|
private ushort _cols = 1;
|
|
private ushort _rows = 1;
|
|
private ushort _maxCols;
|
|
private ushort _maxRows;
|
|
private bool _isWithinBoundary = true;
|
|
|
|
#region Overrides
|
|
|
|
public override string Title => "Pattern";
|
|
public override string Description =>
|
|
"Duplicates the model in a rectangular pattern around the build plate.\n" +
|
|
"Note: Before perform this operation, un-rotate the layer preview to see the real orientation.";
|
|
public override string ConfirmationText =>
|
|
$"pattern the object across {Cols} columns and {Rows} rows?";
|
|
|
|
public override string ProgressTitle =>
|
|
$"Patterning the object across {Cols} columns and {Rows} rows";
|
|
|
|
public override string ProgressAction => "Patterned layers";
|
|
|
|
public override bool CanHaveProfiles => false;
|
|
|
|
public override StringTag Validate(params object[] parameters)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
if (Cols <= 1 && Rows <= 1)
|
|
{
|
|
sb.AppendLine("Either columns or rows must be greater than 1.");
|
|
}
|
|
|
|
if (!ValidateBounds())
|
|
{
|
|
sb.AppendLine("Your parameters will put the object outside of the build plate, please adjust the margins.");
|
|
}
|
|
|
|
return new StringTag(sb.ToString());
|
|
}
|
|
|
|
#endregion
|
|
|
|
public Enumerations.Anchor Anchor
|
|
{
|
|
get => _anchor;
|
|
set => RaiseAndSetIfChanged(ref _anchor, value);
|
|
}
|
|
|
|
public uint ImageWidth { get; }
|
|
public uint ImageHeight { get; }
|
|
|
|
public ushort Cols
|
|
{
|
|
get => _cols;
|
|
set
|
|
{
|
|
if (!RaiseAndSetIfChanged(ref _cols, value)) return;
|
|
RaisePropertyChanged(nameof(InfoCols));
|
|
RaisePropertyChanged(nameof(InfoWidthStr));
|
|
RaisePropertyChanged(nameof(InfoModelWithinBoundaryStr));
|
|
ValidateBounds();
|
|
}
|
|
}
|
|
|
|
public ushort Rows
|
|
{
|
|
get => _rows;
|
|
set
|
|
{
|
|
if (!RaiseAndSetIfChanged(ref _rows, value)) return;
|
|
RaisePropertyChanged(nameof(InfoRows));
|
|
RaisePropertyChanged(nameof(InfoHeightStr));
|
|
RaisePropertyChanged(nameof(InfoModelWithinBoundaryStr));
|
|
ValidateBounds();
|
|
}
|
|
}
|
|
|
|
public ushort MaxCols
|
|
{
|
|
get => _maxCols;
|
|
set
|
|
{
|
|
if(!RaiseAndSetIfChanged(ref _maxCols, value)) return;
|
|
RaisePropertyChanged(nameof(InfoCols));
|
|
ValidateBounds();
|
|
}
|
|
}
|
|
|
|
public ushort MaxRows
|
|
{
|
|
get => _maxRows;
|
|
set
|
|
{
|
|
if (!RaiseAndSetIfChanged(ref _maxRows, value)) return;
|
|
RaisePropertyChanged(nameof(InfoRows));
|
|
ValidateBounds();
|
|
}
|
|
}
|
|
|
|
public ushort ColSpacing
|
|
{
|
|
get => _colSpacing;
|
|
set
|
|
{
|
|
if(!RaiseAndSetIfChanged(ref _colSpacing, value)) return;
|
|
RaisePropertyChanged(nameof(InfoWidthStr));
|
|
RaisePropertyChanged(nameof(InfoModelWithinBoundaryStr));
|
|
ValidateBounds();
|
|
}
|
|
}
|
|
|
|
public ushort RowSpacing
|
|
{
|
|
get => _rowSpacing;
|
|
set
|
|
{
|
|
if (!RaiseAndSetIfChanged(ref _rowSpacing, value)) return;
|
|
RaisePropertyChanged(nameof(InfoHeightStr));
|
|
RaisePropertyChanged(nameof(InfoModelWithinBoundaryStr));
|
|
ValidateBounds();
|
|
}
|
|
}
|
|
|
|
public ushort MaxColSpacing
|
|
{
|
|
get => _maxColSpacing;
|
|
set => RaiseAndSetIfChanged(ref _maxColSpacing, value);
|
|
}
|
|
|
|
public ushort MaxRowSpacing
|
|
{
|
|
get => _maxRowSpacing;
|
|
set => RaiseAndSetIfChanged(ref _maxRowSpacing, value);
|
|
}
|
|
|
|
public string InfoCols => $"Columns: {Cols} / {MaxCols}";
|
|
public string InfoRows => $"Rows: {Rows} / {MaxRows}";
|
|
|
|
public string InfoWidthStr =>
|
|
$"Width: {GetPatternVolume.Width} (Min: {ROI.Width}, Max: {ImageWidth})";
|
|
|
|
public string InfoHeightStr =>
|
|
$"Width: {GetPatternVolume.Height} (Min: {ROI.Height}, Max: {ImageHeight})";
|
|
|
|
public bool IsWithinBoundary
|
|
{
|
|
get => _isWithinBoundary;
|
|
set
|
|
{
|
|
if (!RaiseAndSetIfChanged(ref _isWithinBoundary, value)) return;
|
|
RaisePropertyChanged(nameof(InfoModelWithinBoundaryStr));
|
|
}
|
|
}
|
|
|
|
public string InfoModelWithinBoundaryStr => "Model within boundary: " + (_isWithinBoundary ? "Yes" : "No");
|
|
|
|
public Size GetPatternVolume => new Size(Cols * ROI.Width + (Cols - 1) * ColSpacing, Rows * ROI.Height + (Rows - 1) * RowSpacing);
|
|
|
|
public OperationPattern()
|
|
{
|
|
}
|
|
|
|
public OperationPattern(Rectangle srcRoi, Size resolution)
|
|
{
|
|
ImageWidth = (uint) resolution.Width;
|
|
ImageHeight = (uint) resolution.Height;
|
|
|
|
SetRoi(srcRoi);
|
|
Fill();
|
|
}
|
|
|
|
public void SetAnchor(byte value)
|
|
{
|
|
Anchor = (Enumerations.Anchor)value;
|
|
}
|
|
|
|
public void SetRoi(Rectangle srcRoi)
|
|
{
|
|
ROI = srcRoi;
|
|
|
|
MaxCols = (ushort)(ImageWidth / srcRoi.Width);
|
|
MaxRows = (ushort)(ImageHeight / srcRoi.Height);
|
|
|
|
MaxColSpacing = CalculateAutoColSpacing(MaxCols);
|
|
MaxRowSpacing = CalculateAutoRowSpacing(MaxRows);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fills the plate with maximum cols and rows
|
|
/// </summary>
|
|
public void Fill()
|
|
{
|
|
Cols = MaxCols;
|
|
ColSpacing = MaxColSpacing;
|
|
|
|
Rows = MaxRows;
|
|
RowSpacing = MaxRowSpacing;
|
|
}
|
|
|
|
public ushort CalculateAutoColSpacing(ushort cols)
|
|
{
|
|
if (cols <= 1) return 0;
|
|
return (ushort)((ImageWidth - ROI.Width * cols) / cols);
|
|
}
|
|
|
|
public ushort CalculateAutoRowSpacing(ushort rows)
|
|
{
|
|
if (rows <= 1) return 0;
|
|
return (ushort)((ImageHeight - ROI.Height * rows) / rows);
|
|
}
|
|
|
|
public Rectangle GetRoi(ushort col, ushort row)
|
|
{
|
|
var patternVolume = GetPatternVolume;
|
|
|
|
return new Rectangle(new Point(
|
|
(int) (col * ROI.Width + col * ColSpacing + (ImageWidth - patternVolume.Width) / 2),
|
|
(int) (row * ROI.Height + row * RowSpacing + (ImageHeight - patternVolume.Height) / 2)), ROI.Size);
|
|
}
|
|
|
|
public void FillColumnSpacing()
|
|
{
|
|
ColSpacing = CalculateAutoColSpacing(_cols);
|
|
}
|
|
|
|
public void FillRowSpacing()
|
|
{
|
|
RowSpacing = CalculateAutoRowSpacing(_rows);
|
|
}
|
|
|
|
public bool ValidateBounds()
|
|
{
|
|
var volume = GetPatternVolume;
|
|
return IsWithinBoundary = volume.Width <= ImageWidth && volume.Height <= ImageHeight;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
var result = $"[Rows: {Rows}] [Cols: {Cols}]" + LayerRangeString;
|
|
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
|
|
return result;
|
|
}
|
|
}
|
|
}
|