Move MatterControl source code into a subdirectory

This commit is contained in:
Nettika 2026-01-28 21:30:58 -08:00
parent 2c6e34243a
commit 70af2d9ae8
Signed by: nettika
SSH key fingerprint: SHA256:f+PJrfIq49zrQ6dQrHj18b+PJKmAldeAMiGdj8IzXCA
2007 changed files with 13 additions and 8 deletions

View file

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Company>MatterHackers Inc.</Company>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ReleaseVersion>2.20.12</ReleaseVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MatterControl.Common\MatterControl.Common.csproj">
</ProjectReference>
<ProjectReference Include="..\MatterControl.Printing\MatterControl.Printing.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\agg\Agg.csproj">
</ProjectReference>
<ProjectReference Include="..\Submodules\agg-sharp\DataConverters3D\DataConverters3D.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\Localizations\Localizations.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\VectorMath\VectorMath.csproj">
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Update="StyleCop.Analyzers" Version="1.1.118" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,71 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System;
public static class ArraysEmulation
{
public static void Arraycopy(byte[] emptyRow, int v1, byte[] vs, int v2, int width)
{
throw new NotImplementedException();
}
public static byte[] CopyOfRange(byte[] src, int start, int end)
{
int len = end - start;
var dest = new byte[len];
// note i is always from 0
for (int i = 0; i < len; i++)
{
dest[i] = src[start + i]; // so 0..n = 0+x..n+x
}
return dest;
}
public static void Fill<T>(T[] array, int start, int end, T value)
{
if (array == null)
{
throw new ArgumentNullException("array is null");
}
if (start < 0 || start >= end)
{
throw new ArgumentOutOfRangeException("fromIndex");
}
if (end >= array.Length)
{
throw new ArgumentOutOfRangeException("toIndex");
}
for (int i = start; i < end; i++)
{
array[i] = value;
}
}
internal static void Arraycopy(int[] emptyCol, int v1, int[] pixels, int v2, int height)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,77 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.Collections;
/**
* by bn on 01/07/2018.
*/
namespace Photon.Parts
{
public static class BitArrayExtensions
{
/// <summary>
/// returns the next set bit or -1 if no more set bits
/// </summary>
/// <param name="bitArray">The array to check</param>
/// <param name="startIndex">The index to start checking from</param>
/// <returns>The next set bit or -1</returns>
public static int NextSetBit(this BitArray bitArray, int startIndex)
{
int offset = startIndex >> 6;
long mask = 1L << startIndex;
while (offset < bitArray.Length)
{
var h = bitArray[offset] ? 1 : 0;
do
{
if ((h & mask) != 0)
{
return startIndex;
}
mask <<= 1;
startIndex++;
}
while (mask != 0);
mask = 1;
offset++;
}
return -1;
}
public static void Set(this BitArray bitArray, int start, int end)
{
for (int i = start; i < end; i++)
{
bitArray[i] = true;
}
}
}
}

View file

@ -0,0 +1,81 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.Collections.Generic;
namespace Photon.Parts
{
public interface IFileHeader
{
int GetAALevels();
float GetBottomExposureTimeSeconds();
int GetBottomLayers();
float GetBuildAreaX();
float GetBuildAreaY();
int GetByteSize();
float GetExposureTimeSeconds();
string GetInformation();
float GetLayerHeight();
float GetNormalExposure();
int GetNumberOfLayers();
float GetOffTimeSeconds();
int GetPrintTimeSeconds();
int GetResolutionX();
int GetResolutionY();
int GetVersion();
bool HasAA();
bool IsMirrored();
void SetAALevels(int levels, List<PhotonFileLayer> layers);
void SetBottomLayers(int bottomLayers);
void SetExposureBottomTimeSeconds(float exposureBottomTimeSeconds);
void SetExposureTimeSeconds(float exposureTimeSeconds);
void SetFileVersion(int i);
void SetOffTimeSeconds(float offTimeSeconds);
void UnLink();
}
}

View file

@ -0,0 +1,118 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Photon.Parts
{
public class PhotonAaMatrix
{
public int[,] aaMatrix = new int[5, 5];
private readonly bool[] hasDivisor = new bool[5];
public int[,] Calc(int[,] source)
{
int[,] target = null;
if (source != null)
{
target = (int[,])source.Clone();
int divisor = 0;
for (int y = 0; y < 5; y++)
{
int rowDivistor = 0;
for (int x = 0; x < 5; x++)
{
rowDivistor += aaMatrix[y, x];
}
hasDivisor[y] = (rowDivistor > 0);
divisor += rowDivistor;
}
if (divisor > 0)
{
int height = source.Length;
if (height > 0)
{
int width = source.GetLength(0);
if (width > 0)
{
int sum; ;
int dy;
int dx;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
sum = 0;
for (int cy = -2; cy <= 2; cy++)
{
if (hasDivisor[2 + cy])
for (int cx = -2; cx <= 2; cx++)
{
dy = y + cy;
dx = x + cx;
if (dy >= 0 && dy < height)
{
if (dx >= 0 && dx < width)
{
sum += source[dy, dx] * aaMatrix[2 + cy, 2 + cx];
}
else
{
sum += source[y, x] * aaMatrix[2 + cy, 2 + cx];
}
}
else
{
sum += source[y, x] * aaMatrix[2 + cy, 2 + cx];
}
}
}
target[y, x] = sum / divisor;
}
}
}
}
}
}
return target;
}
public void Clear()
{
for (int y = 0; y < 5; y++)
{
for (int x = 0; x < 5; x++)
{
aaMatrix[y, x] = 0;
}
}
}
public void Set(int x, int y, int val)
{
aaMatrix[y - 1, x - 1] = val;
}
}
}

View file

@ -0,0 +1,66 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* by bn on 02/07/2018.
*/
namespace Photon.Parts
{
public class PhotonDot
{
public int x;
public int y;
public PhotonDot(int x, int y)
{
this.x = x;
this.y = y;
}
override public bool Equals(object o)
{
if (this == o)
{
return true;
}
if (!(o is PhotonDot))
{
return false;
}
var photonDot = (PhotonDot)o;
return x == photonDot.x && y == photonDot.y;
}
public override int GetHashCode()
{
int result = x;
result = 31 * result + y;
return result;
}
}
}

View file

@ -0,0 +1,401 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.Collections.Generic;
using System.IO;
/**
* by bn on 30/06/2018.
*/
namespace Photon.Parts
{
public class PhotonFileHeader : IFileHeader
{
public PhotonFileMachineInfo photonFileMachineInfo;
public PhotonFilePrintParameters photonFilePrintParameters;
private int antiAliasingLevel;
private readonly float bedXmm;
private readonly float bedYmm;
private readonly float bedZmm;
private int bottomLayers;
private short bottomLightPWM;
private float exposureBottomTimeSeconds;
private float exposureTimeSeconds;
private readonly int header1;
private readonly float layerHeightMilimeter;
private int layersDefinitionOffsetAddress;
private short lightPWM;
private int machineInfoOffsetAddress;
private readonly int machineInfoSize;
private readonly int numberOfLayers;
private float offTimeSeconds;
private int previewOneOffsetAddress;
private int previewTwoOffsetAddress;
private int printParametersOffsetAddress;
private readonly int printParametersSize;
private readonly int printTimeSeconds;
private readonly PhotonProjectType projectType;
private readonly int resolutionX;
private readonly int resolutionY;
private readonly int unknown1;
private readonly int unknown2;
private readonly int unknown3;
private readonly int unknown4;
private int version;
public PhotonFileHeader(byte[] fileContent)
{
var reader = new BinaryReader(new MemoryStream(fileContent));
header1 = reader.ReadInt32();
version = reader.ReadInt32();
bedXmm = reader.ReadSingle();
bedYmm = reader.ReadSingle();
bedZmm = reader.ReadSingle();
unknown1 = reader.ReadInt32();
unknown2 = reader.ReadInt32();
unknown3 = reader.ReadInt32();
layerHeightMilimeter = reader.ReadSingle();
exposureTimeSeconds = reader.ReadSingle();
exposureBottomTimeSeconds = reader.ReadSingle();
offTimeSeconds = reader.ReadSingle();
bottomLayers = reader.ReadInt32();
resolutionX = reader.ReadInt32();
resolutionY = reader.ReadInt32();
previewOneOffsetAddress = reader.ReadInt32();
layersDefinitionOffsetAddress = reader.ReadInt32();
numberOfLayers = reader.ReadInt32();
previewTwoOffsetAddress = reader.ReadInt32();
printTimeSeconds = reader.ReadInt32();
projectType = (PhotonProjectType)reader.ReadInt32();
printParametersOffsetAddress = reader.ReadInt32();
printParametersSize = reader.ReadInt32();
antiAliasingLevel = reader.ReadInt32();
lightPWM = reader.ReadInt16();
bottomLightPWM = reader.ReadInt16();
unknown4 = reader.ReadInt32();
machineInfoOffsetAddress = reader.ReadInt32();
if (version > 1)
{
machineInfoSize = reader.ReadInt32();
}
}
public int GetAALevels()
{
if (GetVersion() > 1)
{
return GetAntiAliasingLevel();
}
return 1;
}
public int GetAntiAliasingLevel()
{
return antiAliasingLevel;
}
public float GetBottomExposureTimeSeconds()
{
return exposureBottomTimeSeconds;
}
public int GetBottomLayers()
{
return bottomLayers;
}
public float GetBuildAreaX()
{
return bedXmm;
}
public float GetBuildAreaY()
{
return bedYmm;
}
public int GetByteSize()
{
return 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + (version > 1 ? 4 : 0);
}
public float GetExposureTimeSeconds()
{
return exposureTimeSeconds;
}
public string GetInformation()
{
return string.Format("T: %.3f", layerHeightMilimeter) +
", E: " + exposureTimeSeconds +
", O: " + offTimeSeconds +
", BE: " + exposureBottomTimeSeconds +
string.Format(", BL: %d", bottomLayers);
}
public float GetLayerHeight()
{
return layerHeightMilimeter;
}
public int GetLayersDefinitionOffsetAddress()
{
return layersDefinitionOffsetAddress;
}
public int GetMachineInfoOffsetAddress()
{
return machineInfoOffsetAddress;
}
public int GetMachineInfoSize()
{
return machineInfoSize;
}
public float GetNormalExposure()
{
return exposureTimeSeconds;
}
public int GetNumberOfLayers()
{
return numberOfLayers;
}
public float GetOffTime()
{
return offTimeSeconds;
}
public float GetOffTimeSeconds()
{
return offTimeSeconds;
}
public int GetPreviewOneOffsetAddress()
{
return previewOneOffsetAddress;
}
public int GetPreviewTwoOffsetAddress()
{
return previewTwoOffsetAddress;
}
public int GetPrintParametersOffsetAddress()
{
return printParametersOffsetAddress;
}
public int GetPrintParametersSize()
{
return printParametersSize;
}
public int GetPrintTimeSeconds()
{
return printTimeSeconds;
}
public int GetResolutionX()
{
return resolutionX;
}
public int GetResolutionY()
{
return resolutionY;
}
public int GetVersion()
{
return version;
}
public bool HasAA()
{
return (GetVersion() > 1 && GetAntiAliasingLevel() > 1);
}
public bool IsMirrored()
{
return projectType == PhotonProjectType.lcdMirror;
}
public void ReadParameters(byte[] file)
{
photonFilePrintParameters = new PhotonFilePrintParameters(GetPrintParametersOffsetAddress(), file);
photonFileMachineInfo = new PhotonFileMachineInfo(GetMachineInfoOffsetAddress(), GetMachineInfoSize(), file);
}
public void Save(BinaryWriter os, int previewOnePos, int previewTwoPos, int layerDefinitionPos, int parametersPos, int machineInfoPos)
{
previewOneOffsetAddress = previewOnePos;
previewTwoOffsetAddress = previewTwoPos;
layersDefinitionOffsetAddress = layerDefinitionPos;
printParametersOffsetAddress = parametersPos;
machineInfoOffsetAddress = machineInfoPos;
os.Write(header1);
os.Write(version);
os.Write(bedXmm);
os.Write(bedYmm);
os.Write(bedZmm);
os.Write(unknown1);
os.Write(unknown2);
os.Write(unknown3);
os.Write(layerHeightMilimeter);
os.Write(exposureTimeSeconds);
os.Write(exposureBottomTimeSeconds);
os.Write(offTimeSeconds);
os.Write(bottomLayers);
os.Write(resolutionX);
os.Write(resolutionY);
os.Write(previewOneOffsetAddress);
os.Write(layersDefinitionOffsetAddress);
os.Write(numberOfLayers);
os.Write(previewTwoOffsetAddress);
os.Write(printTimeSeconds);
os.Write((int)projectType);
os.Write(printParametersOffsetAddress);
os.Write(printParametersSize);
os.Write(antiAliasingLevel);
os.Write(lightPWM);
os.Write(bottomLightPWM);
os.Write(unknown4);
os.Write(machineInfoOffsetAddress);
if (version > 1)
{
os.Write(machineInfoSize);
}
}
public void SetAALevels(int levels, List<PhotonFileLayer> layers)
{
if (GetVersion() > 1)
{
if (levels < GetAntiAliasingLevel())
{
ReduceAaLevels(levels, layers);
}
if (levels > GetAntiAliasingLevel())
{
IncreaseAaLevels(levels, layers);
}
}
}
public void SetAntiAliasingLevel(int antiAliasingLevel)
{
this.antiAliasingLevel = antiAliasingLevel;
}
public void SetBottomLayers(int bottomLayers)
{
this.bottomLayers = bottomLayers;
}
public void SetExposureBottomTimeSeconds(float exposureBottomTimeSeconds)
{
this.exposureBottomTimeSeconds = exposureBottomTimeSeconds;
}
public void SetExposureTimeSeconds(float exposureTimeSeconds)
{
this.exposureTimeSeconds = exposureTimeSeconds;
}
public void SetFileVersion(int i)
{
version = i;
antiAliasingLevel = 1;
lightPWM = 255;
bottomLightPWM = 255;
photonFilePrintParameters = new PhotonFilePrintParameters(GetBottomLayers());
}
public void SetOffTimeSeconds(float offTimeSeconds)
{
this.offTimeSeconds = offTimeSeconds;
}
public void UnLink()
{
}
private void IncreaseAaLevels(int levels, List<PhotonFileLayer> layers)
{
// insert base layer to the correct count, as we are to recalculate the AA anyway
foreach (var photonFileLayer in layers)
{
while (photonFileLayer.GetAntiAlias().Count < (levels - 1))
{
photonFileLayer.GetAntiAlias().Add(new PhotonFileLayer(photonFileLayer, this));
}
}
SetAntiAliasingLevel(levels);
}
private void ReduceAaLevels(int levels, List<PhotonFileLayer> layers)
{
// delete any layers to the correct count, as we are to recalculate the AA anyway
foreach (var photonFileLayer in layers)
{
while (photonFileLayer.GetAntiAlias().Count > (levels - 1))
{
photonFileLayer.GetAntiAlias().RemoveAt(0);
}
}
SetAntiAliasingLevel(levels);
}
}
}

View file

@ -0,0 +1,593 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
/**
* by bn on 01/07/2018.
*/
namespace Photon.Parts
{
public class PhotonFileLayer
{
public bool isCalculated;
private readonly List<PhotonFileLayer> antiAliasLayers = new List<PhotonFileLayer>();
private int dataAddress;
private int dataSize;
private bool extendsMargin;
private byte[] imageData;
private List<BitArray> islandRows;
private int isLandsCount;
private float layerExposure;
private float layerOffTimeSeconds;
private float layerPositionZ;
private byte[] packedLayerImage;
private PhotonFileHeader photonFileHeader;
private long pixels;
private readonly int unknown1;
private readonly int unknown2;
private readonly int unknown3;
private readonly int unknown4;
public PhotonFileLayer(PhotonFileLayer photonFileLayer, PhotonFileHeader photonFileHeader)
{
layerPositionZ = photonFileLayer.layerPositionZ;
layerExposure = photonFileLayer.layerExposure;
layerOffTimeSeconds = photonFileLayer.layerOffTimeSeconds;
dataAddress = photonFileLayer.dataAddress;
dataAddress = photonFileLayer.dataSize;
this.photonFileHeader = photonFileHeader;
// Dont copy data, we are building new AA layers anyway
//this.imageData = copy();
//this.packedLayerImage = copy();
}
private PhotonFileLayer(BinaryReader ds)
{
layerPositionZ = ds.ReadSingle();
layerExposure = ds.ReadSingle();
layerOffTimeSeconds = ds.ReadSingle();
dataAddress = ds.ReadInt32();
dataSize = ds.ReadInt32();
unknown1 = ds.ReadInt32();
unknown2 = ds.ReadInt32();
unknown3 = ds.ReadInt32();
unknown4 = ds.ReadInt32();
}
public static void CalculateAALayers(PhotonFileHeader photonFileHeader, List<PhotonFileLayer> layers, PhotonAaMatrix photonAaMatrix, Action<string> reportProgress)
{
var photonLayer = new PhotonLayer(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
int[,] source = new int[photonFileHeader.GetResolutionY(), photonFileHeader.GetResolutionX()];
int i = 0;
foreach (var layer in layers)
{
List<BitArray> unpackedImage = layer.UnpackImage(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
reportProgress?.Invoke("Calculating AA for photon file layer " + i + "/" + photonFileHeader.GetNumberOfLayers());
for (int y = 0; y < photonFileHeader.GetResolutionY(); y++)
{
for (int x = 0; x < photonFileHeader.GetResolutionX(); x++)
{
source[y, x] = 0;
}
}
for (int y = 0; y < unpackedImage.Count; y++)
{
BitArray currentRow = unpackedImage[y];
if (currentRow != null)
{
for (int x = 0; x < currentRow.Length; x++)
{
if (currentRow[x])
{
source[y, x] = 255;
}
}
}
}
// Calc
int[,] target = photonAaMatrix.Calc(source);
int aaTresholdDiff = 255 / photonFileHeader.GetAntiAliasingLevel();
int aaTreshold = 0;
foreach (var aaFileLayer in layer.antiAliasLayers)
{
photonLayer.Clear();
aaTreshold += aaTresholdDiff;
for (int y = 0; y < photonFileHeader.GetResolutionY(); y++)
{
for (int x = 0; x < photonFileHeader.GetResolutionX(); x++)
{
if (target[y, x] >= aaTreshold)
{
photonLayer.Supported(x, y);
}
}
}
aaFileLayer.SaveLayer(photonLayer);
}
i++;
}
photonLayer.UnLink();
}
public static void CalculateLayers(PhotonFileHeader photonFileHeader, List<PhotonFileLayer> layers, int margin, Action<string> reportProgress)
{
var photonLayer = new PhotonLayer(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
List<BitArray> previousUnpackedImage = null;
for (int i=0; i<layers.Count; i++)
{
var layer = layers[i];
List<BitArray> unpackedImage = layer.UnpackImage(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
reportProgress?.Invoke("Calculating photon file layer " + i + "/" + photonFileHeader.GetNumberOfLayers());
if (margin > 0)
{
layer.extendsMargin = layer.CheckMargin(unpackedImage, margin);
}
layer.UnknownPixels(unpackedImage, photonLayer);
layer.Calculate(unpackedImage, previousUnpackedImage, photonLayer);
if (previousUnpackedImage != null)
{
previousUnpackedImage.Clear();
}
previousUnpackedImage = unpackedImage;
layer.packedLayerImage = photonLayer.PackLayerImage();
layer.isCalculated = true;
if (photonFileHeader.GetVersion() > 1)
{
foreach (var aaFileLayer in layer.antiAliasLayers)
{
List<BitArray> aaUnpackedImage = aaFileLayer.UnpackImage(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
var aaPhotonLayer = new PhotonLayer(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
aaFileLayer.UnknownPixels(aaUnpackedImage, aaPhotonLayer);
aaFileLayer.packedLayerImage = aaPhotonLayer.PackLayerImage();
aaFileLayer.isCalculated = false;
}
}
}
photonLayer.UnLink();
}
public static void CalculateLayers(PhotonFileHeader photonFileHeader, List<PhotonFileLayer> layers, int margin, int layerIndex)
{
var photonLayer = new PhotonLayer(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
List<BitArray> previousUnpackedImage = null;
if (layerIndex > 0)
{
previousUnpackedImage = layers[layerIndex - 1].UnpackImage(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
}
for (int i = 0; i < 2; i++)
{
PhotonFileLayer layer = layers[layerIndex + i];
List<BitArray> unpackedImage = layer.UnpackImage(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
if (margin > 0)
{
layer.extendsMargin = layer.CheckMargin(unpackedImage, margin);
}
layer.UnknownPixels(unpackedImage, photonLayer);
layer.Calculate(unpackedImage, previousUnpackedImage, photonLayer);
if (previousUnpackedImage != null)
{
previousUnpackedImage.Clear();
}
previousUnpackedImage = unpackedImage;
layer.packedLayerImage = photonLayer.PackLayerImage();
layer.isCalculated = true;
i++;
}
photonLayer.UnLink();
}
public static int GetByteSize()
{
return 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4;
}
public static List<PhotonFileLayer> ReadLayers(PhotonFileHeader photonFileHeader, byte[] fileContent, int margin, Action<string> reportProgress)
{
var photonLayer = new PhotonLayer(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
var layers = new List<PhotonFileLayer>();
int antiAliasLevel = 1;
if (photonFileHeader.GetVersion() > 1)
{
antiAliasLevel = photonFileHeader.GetAntiAliasingLevel();
}
int layerCount = photonFileHeader.GetNumberOfLayers();
var start = photonFileHeader.GetLayersDefinitionOffsetAddress();
var ds = new BinaryReader(new MemoryStream(fileContent, start, fileContent.Length - start));
{
var layerMap = new Dictionary<int, PhotonFileLayer>();
for (int i = 0; i < layerCount; i++)
{
reportProgress?.Invoke("Reading photon file layer " + (i + 1) + "/" + photonFileHeader.GetNumberOfLayers());
var layer = new PhotonFileLayer(ds)
{
photonFileHeader = photonFileHeader
};
layer.imageData = ArraysEmulation.CopyOfRange(fileContent, layer.dataAddress, layer.dataAddress + layer.dataSize);
layers.Add(layer);
layerMap[i] = layer;
}
if (antiAliasLevel > 1)
{
for (int a = 0; a < (antiAliasLevel - 1); a++)
{
for (int i = 0; i < layerCount; i++)
{
reportProgress?.Invoke("Reading photon file AA " + (2 + a) + "/" + antiAliasLevel + " layer " + (i + 1) + "/" + photonFileHeader.GetNumberOfLayers());
var layer = new PhotonFileLayer(ds)
{
photonFileHeader = photonFileHeader
};
layer.imageData = ArraysEmulation.CopyOfRange(fileContent, layer.dataAddress, layer.dataAddress + layer.dataSize);
layerMap[i].AddAntiAliasLayer(layer);
}
}
}
}
photonLayer.UnLink();
return layers;
}
public bool DoExtendMargin()
{
return extendsMargin;
}
public PhotonFileLayer GetAntiAlias(int a)
{
if (antiAliasLayers.Count > a)
{
return antiAliasLayers[a];
}
return null;
}
public List<PhotonFileLayer> GetAntiAlias()
{
return antiAliasLayers;
}
public List<BitArray> GetIslandRows()
{
return islandRows;
}
public int GetIsLandsCount()
{
return isLandsCount;
}
public PhotonLayer GetLayer()
{
var photonLayer = new PhotonLayer(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
photonLayer.UnpackLayerImage(packedLayerImage);
return photonLayer;
}
public float GetLayerExposure()
{
return layerExposure;
}
public float GetLayerOffTime()
{
return layerOffTimeSeconds;
}
public float GetLayerPositionZ()
{
return layerPositionZ;
}
public long GetPixels()
{
return pixels;
}
public List<PhotonRow> GetRows()
{
return PhotonLayer.GetRows(packedLayerImage, photonFileHeader.GetResolutionX(), isCalculated);
}
public List<BitArray> GetUnknownRows()
{
return UnpackImage(photonFileHeader.GetResolutionX(), photonFileHeader.GetResolutionY());
}
public void GetUpdateLayer(PhotonLayer photonLayer)
{
photonLayer.UnpackLayerImage(packedLayerImage);
}
public void Save(BinaryWriter writer)
{
writer.Write(layerPositionZ);
writer.Write(layerExposure);
writer.Write(layerOffTimeSeconds);
writer.Write(dataAddress);
writer.Write(dataSize);
writer.Write(unknown1);
writer.Write(unknown2);
writer.Write(unknown3);
writer.Write(unknown4);
}
public void SaveData(BinaryWriter writer)
{
writer.Write(imageData, 0, dataSize);
}
public void SaveLayer(PhotonLayer photonLayer)
{
this.packedLayerImage = photonLayer.PackLayerImage();
this.imageData = photonLayer.PackImageData();
this.dataSize = imageData.Length;
islandRows = new List<BitArray>();
isLandsCount = photonLayer.SetIslands(islandRows);
}
public int SavePos(int dataPosition)
{
dataAddress = dataPosition;
return dataPosition + dataSize;
}
public void SetLayerExposure(float layerExposure)
{
this.layerExposure = layerExposure;
}
public void SetLayerOffTimeSeconds(float layerOffTimeSeconds)
{
this.layerOffTimeSeconds = layerOffTimeSeconds;
}
public void SetLayerPositionZ(float layerPositionZ)
{
this.layerPositionZ = layerPositionZ;
}
public void UnLink()
{
imageData = null;
packedLayerImage = null;
if (islandRows != null)
{
islandRows.Clear();
}
photonFileHeader = null;
}
public List<BitArray> UnpackImage(int resolutionX, int resolutionY)
{
pixels = 0;
resolutionX -= 1;
var unpackedImage = new List<BitArray>(resolutionY);
var currentRow = new BitArray(resolutionX);
unpackedImage.Add(currentRow);
int x = 0;
foreach (var rle in imageData)
{
int length = rle & 0x7F;
bool color = (rle & 0x80) == 0x80;
if (color)
{
pixels += length;
}
int endPosition = x + (length - 1);
int lineEnd = Math.Min(endPosition, resolutionX);
if (color)
{
currentRow.Set(x, 1 + lineEnd);
}
if (endPosition > resolutionX)
{
currentRow = new BitArray(resolutionX);
unpackedImage.Add(currentRow);
lineEnd = endPosition - (resolutionX + 1);
if (color)
{
currentRow.Set(0, 1 + lineEnd);
}
}
x = lineEnd + 1;
if (x > resolutionX)
{
currentRow = new BitArray(resolutionX);
unpackedImage.Add(currentRow);
x = 0;
}
}
return unpackedImage;
}
public void UpdateLayerIslands(PhotonLayer photonLayer)
{
islandRows = new List<BitArray>();
isLandsCount = photonLayer.SetIslands(islandRows);
}
private void AaPixels(List<BitArray> unpackedImage, PhotonLayer photonLayer)
{
photonLayer.Clear();
for (int y = 0; y < unpackedImage.Count; y++)
{
BitArray currentRow = unpackedImage[y];
if (currentRow != null)
{
for (int x = 0; x < currentRow.Length; x++)
{
if (currentRow[x])
{
photonLayer.UnSupported(x, y);
}
}
}
}
}
private void AddAntiAliasLayer(PhotonFileLayer layer)
{
antiAliasLayers.Add(layer);
}
private void Calculate(List<BitArray> unpackedImage, List<BitArray> previousUnpackedImage, PhotonLayer photonLayer)
{
islandRows = new List<BitArray>();
isLandsCount = 0;
photonLayer.Clear();
for (int y = 0; y < unpackedImage.Count; y++)
{
BitArray currentRow = unpackedImage[y];
BitArray prevRow = previousUnpackedImage?[y];
if (currentRow != null)
{
int x = 0;
while ((x = currentRow.NextSetBit(x)) >= 0)
{
if (prevRow == null || prevRow[x])
{
photonLayer.Supported(x, y);
}
else
{
photonLayer.Island(x, y);
}
++x;
}
}
}
photonLayer.Reduce();
isLandsCount = photonLayer.SetIslands(islandRows);
}
private bool CheckMargin(List<BitArray> unpackedImage, int margin)
{
if (unpackedImage.Count > margin)
{
// check top margin rows
for (int i = 0; i < margin; i++)
{
if (unpackedImage[i].Count > 0)
{
return true;
}
}
// check bottom margin rows
for (int i = unpackedImage.Count - margin; i < unpackedImage.Count; i++)
{
if (unpackedImage[i].Count > 0)
{
return true;
}
}
for (int i = margin; i < unpackedImage.Count - margin; i++)
{
BitArray row = unpackedImage[i];
int nextBit = row.NextSetBit(0);
if (nextBit >= 0 && nextBit < margin)
{
return true;
}
nextBit = row.NextSetBit(photonFileHeader.GetResolutionX() - margin);
if (nextBit > photonFileHeader.GetResolutionX() - margin)
{
return true;
}
}
}
return false;
}
private void UnknownPixels(List<BitArray> unpackedImage, PhotonLayer photonLayer)
{
photonLayer.Clear();
for (int y = 0; y < unpackedImage.Count; y++)
{
BitArray currentRow = unpackedImage[y];
if (currentRow != null)
{
int x = 0;
while ((x = currentRow.NextSetBit(x)) >= 0)
{
photonLayer.Supported(x, y);
++x;
}
}
}
}
}
}

View file

@ -0,0 +1,115 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.IO;
/**
* by bn on 01/07/2018.
*/
namespace Photon.Parts
{
public class PhotonFileMachineInfo
{
private readonly int infoByteSize;
private readonly byte[] machineName = { };
private readonly int machineNameAddress;
private readonly int machineNameSize;
private readonly int u1, u2, u3, u4, u5, u6, u7;
private readonly int u8, u9, u10, u11, u12, u13, u14, u15, u16, u17;
public PhotonFileMachineInfo(int address, int byteSize, byte[] file)
{
this.infoByteSize = byteSize;
if (byteSize > 0)
{
byte[] data = ArraysEmulation.CopyOfRange(file, address, address + byteSize);
var ds = new BinaryReader(new MemoryStream(data));
{
u1 = ds.ReadInt32();
u2 = ds.ReadInt32();
u3 = ds.ReadInt32();
u4 = ds.ReadInt32();
u5 = ds.ReadInt32();
u6 = ds.ReadInt32();
u7 = ds.ReadInt32();
machineNameAddress = ds.ReadInt32();
machineNameSize = ds.ReadInt32();
u8 = ds.ReadInt32();
u9 = ds.ReadInt32();
u10 = ds.ReadInt32();
u11 = ds.ReadInt32();
u12 = ds.ReadInt32();
u13 = ds.ReadInt32();
u14 = ds.ReadInt32();
u15 = ds.ReadInt32();
u16 = ds.ReadInt32();
u17 = ds.ReadInt32();
}
machineName = ArraysEmulation.CopyOfRange(file, machineNameAddress, machineNameAddress + machineNameSize);
}
}
public int GetByteSize()
{
return infoByteSize + machineName.Length;
}
public void Save(BinaryWriter os, int startAddress)
{
if (infoByteSize > 0)
{
os.Write(u1);
os.Write(u2);
os.Write(u3);
os.Write(u4);
os.Write(u5);
os.Write(u6);
os.Write(u7);
os.Write(startAddress + infoByteSize);
os.Write(machineName.Length);
os.Write(u8);
os.Write(u9);
os.Write(u10);
os.Write(u11);
os.Write(u12);
os.Write(u13);
os.Write(u14);
os.Write(u15);
os.Write(u16);
os.Write(u17);
os.Write(machineName);
}
}
public void UnLink()
{
}
}
}

View file

@ -0,0 +1,133 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.IO;
/**
* by bn on 01/07/2018.
*/
namespace Photon.Parts
{
public class PhotonFilePreview
{
private readonly int dataSize;
private readonly int imageAddress;
private int[] imageData;
private readonly int p1;
private readonly int p2;
private readonly int p3;
private readonly int p4;
private byte[] rawImageData;
private readonly int resolutionX;
private readonly int resolutionY;
public PhotonFilePreview(int previewAddress, byte[] file)
{
byte[] data = ArraysEmulation.CopyOfRange(file, previewAddress, previewAddress + 32);
var ds = new BinaryReader(new MemoryStream(data));
resolutionX = ds.ReadInt32();
resolutionY = ds.ReadInt32();
imageAddress = ds.ReadInt32();
dataSize = ds.ReadInt32();
p1 = ds.ReadInt32();
p2 = ds.ReadInt32();
p3 = ds.ReadInt32();
p4 = ds.ReadInt32();
rawImageData = ArraysEmulation.CopyOfRange(file, imageAddress, imageAddress + dataSize);
DecodeImageData();
}
public int GetByteSize()
{
return 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + dataSize;
}
public int[] GetImageData()
{
return imageData;
}
public int GetResolutionX()
{
return resolutionX;
}
public int GetResolutionY()
{
return resolutionY;
}
public void Save(BinaryWriter os, int startAddress)
{
os.Write(resolutionX);
os.Write(resolutionY);
os.Write(startAddress + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
os.Write(dataSize);
os.Write(p1);
os.Write(p2);
os.Write(p3);
os.Write(p4);
os.Write(rawImageData, 0, dataSize);
}
public void UnLink()
{
rawImageData = null;
imageData = null;
}
private void DecodeImageData()
{
imageData = new int[resolutionX * resolutionY];
int d = 0;
for (int i = 0; i < dataSize; i++)
{
int dot = rawImageData[i] & 0xFF | ((rawImageData[++i] & 0xFF) << 8);
int color = ((dot & 0xF800) << 8) | ((dot & 0x07C0) << 5) | ((dot & 0x001F) << 3);
// int red = ((dot >> 11) & 0x1F) << 3;
// int green = ((dot >> 6) & 0x1F) << 3;
// int blue = (dot & 0x1F) << 3;
// color = red<<16 | green<<8 | blue;
int repeat = 1;
if ((dot & 0x0020) == 0x0020)
{
repeat += rawImageData[++i] & 0xFF | ((rawImageData[++i] & 0x0F) << 8);
}
while (repeat > 0)
{
imageData[d++] = color;
repeat--;
}
}
}
}
}

View file

@ -0,0 +1,108 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.IO;
namespace Photon.Parts
{
public class PhotonFilePrintParameters
{
public int bottomLayerCount;
public float bottomLiftDistance = 5.0f;
public float bottomLiftSpeed = 300.0f;
public float bottomLightOffDelay = 0.0f;
public float costDollars = 0;
public float liftingDistance = 5.0f;
public float liftingSpeed = 300.0f;
public float lightOffDelay = 0.0f;
public int p1;
public int p2;
public int p3;
public int p4;
public float retractSpeed = 300.0f;
public float volumeMl = 0;
public float weightG = 0;
public PhotonFilePrintParameters(int bottomLayerCount)
{
this.bottomLayerCount = bottomLayerCount;
}
public PhotonFilePrintParameters(int parametersPos, byte[] file)
{
byte[] data = ArraysEmulation.CopyOfRange(file, parametersPos, parametersPos + GetByteSize());
var ds = new BinaryReader(new MemoryStream(data));
bottomLiftDistance = ds.ReadSingle();
bottomLiftSpeed = ds.ReadSingle();
liftingDistance = ds.ReadSingle();
liftingSpeed = ds.ReadSingle();
retractSpeed = ds.ReadSingle();
volumeMl = ds.ReadSingle();
weightG = ds.ReadSingle();
costDollars = ds.ReadSingle();
bottomLightOffDelay = ds.ReadSingle();
lightOffDelay = ds.ReadSingle();
bottomLayerCount = ds.ReadInt32();
p1 = ds.ReadInt32();
p2 = ds.ReadInt32();
p3 = ds.ReadInt32();
p4 = ds.ReadInt32();
}
public int GetByteSize()
{
return 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4;
}
public void Save(BinaryWriter os)
{
os.Write(bottomLiftDistance);
os.Write(bottomLiftSpeed);
os.Write(liftingDistance);
os.Write(liftingSpeed);
os.Write(retractSpeed);
os.Write(volumeMl);
os.Write(weightG);
os.Write(costDollars);
os.Write(bottomLightOffDelay);
os.Write(lightOffDelay);
os.Write(bottomLayerCount);
os.Write(p1);
os.Write(p2);
os.Write(p3);
os.Write(p4);
}
}
}

View file

@ -0,0 +1,536 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using MatterHackers.Agg;
using System.Collections;
using System.Collections.Generic;
/**
* by bn on 02/07/2018.
*/
namespace Photon.Parts
{
public class PhotonLayer
{
public static readonly byte CONNECTED = 0x03;
public static readonly byte ISLAND = 0x02;
public static readonly byte OFF = 0x00;
public static readonly byte SUPPORTED = 0x01;
private static int[] emptyCol;
private static byte[] emptyRow;
private static byte[] scratchPad;
private readonly int height;
private byte[][] iArray;
private int islandCount = 0;
private int[] pixels;
private int[] rowIslands;
private readonly int width;
public PhotonLayer(int width, int height)
{
this.width = width;
this.height = height;
iArray = new byte[height][];
for (int i = 0; i < height; i++)
{
iArray[i] = new byte[width];
}
pixels = new int[height];
rowIslands = new int[height];
if (emptyRow == null || emptyRow.Length < width)
{
emptyRow = new byte[width];
}
if (emptyCol == null || emptyCol.Length < height)
{
emptyCol = new int[height];
}
if (scratchPad == null || scratchPad.Length < width * height)
{
scratchPad = new byte[width * height];
}
}
public static List<PhotonRow> GetRows(byte[] packedLayerImage, int width, bool isCalculated)
{
var colors = new Dictionary<byte, Color>
{
{ OFF, Color.Black }
};
if (isCalculated)
{
colors.Add(SUPPORTED, new Color("#008800"));
}
else
{
colors.Add(SUPPORTED, new Color("#000088"));
}
colors.Add(CONNECTED, new Color("#FFFF00"));
colors.Add(ISLAND, new Color("#FF0000"));
var rows = new List<PhotonRow>();
int resolutionX = width - 1;
var currentRow = new PhotonRow();
rows.Add(currentRow);
int x = 0;
if (packedLayerImage != null)
{ // when user tries to show a layer before its calculated
for (int i = 0; i < packedLayerImage.Length; i++)
{
byte rle = packedLayerImage[i];
byte colorCode = (byte)((rle & 0x60) >> 5);
Color color = colors[colorCode];
bool extended = (rle & 0x80) == 0x80;
int length = rle & 0x1F;
if (extended)
{
i++;
length = (length << 8) | packedLayerImage[i] & 0x00ff;
}
currentRow.lines.Add(new PhotonLine(color, length));
x += length;
if (x >= resolutionX)
{
currentRow = new PhotonRow();
rows.Add(currentRow);
x = 0;
}
}
}
return rows;
}
public void Clear()
{
for (int y = 0; y < height; y++)
{
ArraysEmulation.Arraycopy(emptyRow, 0, iArray[y], 0, width);
}
ArraysEmulation.Arraycopy(emptyCol, 0, pixels, 0, height);
ArraysEmulation.Arraycopy(emptyCol, 0, rowIslands, 0, height);
}
public int Fixlayer()
{
var photonMatix = new PhotonMatix();
var dots = new List<PhotonDot>();
if (islandCount > 0)
{
for (int y = 0; y < height; y++)
{
if (rowIslands[y] > 0)
{
for (int x = 0; x < width; x++)
{
if (iArray[y][x] == ISLAND)
{
photonMatix.Clear();
int blanks = photonMatix.Set(x, y, iArray, width, height);
if (blanks > 0)
{ // one or more neighbor pixels are OFF
photonMatix.Calc();
photonMatix.Level();
photonMatix.Calc();
for (int ry = 0; ry < 3; ry++)
{
for (int rx = 0; rx < 3; rx++)
{
int iy = y - 1 + ry;
int ix = x - 1 + rx;
if (iArray[iy][ix] == OFF)
{
if (photonMatix.calcMatrix[1 + ry, 1 + rx] > 3)
{
dots.Add(new PhotonDot(ix, iy));
}
}
}
}
}
}
}
}
}
}
foreach (var dot in dots)
{
Island(dot.x, dot.y);
}
return dots.Count;
}
public byte Get(int x, int y)
{
return iArray[y][x];
}
public void Island(int x, int y)
{
iArray[y][x] = ISLAND;
rowIslands[y]++;
islandCount++;
pixels[y]++;
}
public byte[] PackImageData()
{
int ptr = 0;
for (int y = 0; y < height; y++)
{
if (pixels[y] == 0)
{
ptr = AddPhotonRLE(ptr, true, width);
}
else
{
byte current = OFF;
int length = 0;
for (int x = 0; x < width; x++)
{
byte next = iArray[y][x];
if (next != current)
{
if (length > 0)
{
ptr = AddPhotonRLE(ptr, current == OFF, length);
}
current = next;
length = 1;
}
else
{
length++;
}
}
if (length > 0)
{
ptr = AddPhotonRLE(ptr, current == OFF, length);
}
}
}
byte[] img = new byte[ptr];
ArraysEmulation.Arraycopy(scratchPad, 0, img, 0, ptr);
return img;
}
public byte[] PackLayerImage()
{
int ptr = 0;
for (int y = 0; y < height; y++)
{
if (pixels[y] == 0)
{
ptr = Add(ptr, OFF, width);
}
else
{
byte current = OFF;
int length = 0;
for (int x = 0; x < width; x++)
{
byte next = iArray[y][x];
if (next != current)
{
if (length > 0)
{
ptr = Add(ptr, current, length);
}
current = next;
length = 1;
}
else
{
length++;
}
}
if (length > 0)
{
ptr = Add(ptr, current, length);
}
}
}
byte[] img = new byte[ptr];
ArraysEmulation.Arraycopy(scratchPad, 0, img, 0, ptr);
return img;
}
public void Reduce()
{
// Double reduce to handle single line connections.
for (int i = 0; i < 2; i++)
{
if (islandCount > 0)
{
for (int y = 0; y < height; y++)
{
if (rowIslands[y] > 0)
{
for (int x = 0; x < width; x++)
{
if (iArray[y][x] == ISLAND)
{
if (Connected(x, y))
{
MakeConnected(x, y);
CheckUp(x, y);
if (rowIslands[y] == 0)
{
break;
}
}
}
}
}
}
}
}
}
public void Remove(int x, int y, byte type)
{
iArray[y][x] = OFF;
if (type == ISLAND)
{
rowIslands[y]--;
islandCount--;
}
pixels[y]--;
}
public int RemoveIslands()
{
int count = 0;
if (islandCount > 0)
{
for (int y = 0; y < height; y++)
{
if (rowIslands[y] > 0)
{
for (int x = 0; x < width; x++)
{
if (iArray[y][x] == ISLAND)
{
Remove(x, y, ISLAND);
++count;
}
}
}
}
}
return count;
}
public int SetIslands(List<BitArray> islandRows)
{
int islands = 0;
for (int y = 0; y < height; y++)
{
var bitSet = new BitArray(width - 1);
if (rowIslands[y] > 0)
{
for (int x = 0; x < width; x++)
{
if (iArray[y][x] == ISLAND)
{
bitSet[x] = true;
}
}
}
islandRows.Add(bitSet);
islands += rowIslands[y];
}
return islands;
}
public void Supported(int x, int y)
{
iArray[y][x] = SUPPORTED;
pixels[y]++;
}
public void UnLink()
{
iArray = null;
pixels = null;
rowIslands = null;
}
public void UnpackLayerImage(byte[] packedLayerImage)
{
Clear();
int x = 0;
int y = 0;
int imageLength = packedLayerImage.Length;
for (int i = 0; i < imageLength; i++)
{
byte rle = packedLayerImage[i];
byte colorCode = (byte)((rle & 0x60) >> 5);
bool extended = (rle & 0x80) == 0x80;
int length = rle & 0x1F;
if (extended)
{
i++;
length = (length << 8) | packedLayerImage[i] & 0x00ff;
}
ArraysEmulation.Fill(iArray[y], x, x + length, colorCode);
if (colorCode == SUPPORTED)
{
pixels[y] += length;
}
else if (colorCode == CONNECTED)
{
pixels[y] += length;
}
else if (colorCode == ISLAND)
{
rowIslands[y] += length;
islandCount += length;
pixels[y] += length;
}
x += length;
if (x >= width)
{
y++;
x = 0;
}
}
}
public void UnSupported(int x, int y)
{
iArray[y][x] = CONNECTED;
pixels[y]++;
}
private int Add(int ptr, byte current, int length)
{
if (length < 32)
{
scratchPad[ptr++] = (byte)((current << 5) | (length & 0x1f));
}
else
{
scratchPad[ptr++] = (byte)(0x80 | (current << 5) | (length >> 8 & 0x00FF));
scratchPad[ptr++] = (byte)(length & 0x00FF);
}
return ptr;
}
private int AddPhotonRLE(int ptr, bool off, int length)
{
while (length > 0)
{
int lineLength = length < 125 ? length : 125; // max storage length of 0x7D (125) ?? Why not 127?
scratchPad[ptr++] = (byte)((off ? 0x00 : 0x80) | (lineLength & 0x7f));
length -= lineLength;
}
return ptr;
}
private void CheckBackUp(int x, int y)
{
if (y > 0 && rowIslands[y - 1] > 0 && iArray[y - 1][x] == ISLAND)
{
MakeConnected(x, y - 1);
CheckBackUp(x, y - 1);
}
if (x > 0 && rowIslands[y] > 0 && iArray[y][x - 1] == ISLAND)
{
MakeConnected(x - 1, y);
CheckBackUp(x - 1, y);
}
}
private void CheckFrontUp(int x, int y)
{
if (y > 0 && rowIslands[y - 1] > 0 && iArray[y - 1][x] == ISLAND)
{
MakeConnected(x, y - 1);
CheckFrontUp(x, y - 1);
}
if (x < (width - 1) && rowIslands[y] > 0 && iArray[y][x + 1] == ISLAND)
{
MakeConnected(x + 1, y);
CheckFrontUp(x + 1, y);
}
}
private void CheckUp(int x, int y)
{
if (y > 0 && rowIslands[y - 1] > 0 && iArray[y - 1][x] == ISLAND)
{
MakeConnected(x, y - 1);
CheckUp(x, y - 1);
}
if (x > 0 && rowIslands[y] > 0 && iArray[y][x - 1] == ISLAND)
{
MakeConnected(x - 1, y);
CheckBackUp(x - 1, y);
}
if (x < (width - 1) && rowIslands[y] > 0 && iArray[y][x + 1] == ISLAND)
{
MakeConnected(x + 1, y);
CheckFrontUp(x + 1, y);
}
}
private bool Connected(int x, int y)
{
return x > 0 && (iArray[y][x - 1] & 0x01) == SUPPORTED
|| x < (width - 1) && (iArray[y][x + 1] & 0x01) == SUPPORTED
|| y > 0 && (iArray[y - 1][x] & 0x01) == SUPPORTED
|| (y < (height - 1) && (iArray[y + 1][x] & 0x01) == SUPPORTED);
}
private void MakeConnected(int x, int y)
{
iArray[y][x] = CONNECTED;
rowIslands[y]--;
islandCount--;
}
/**
* Get a layer image for drawing.
* <p/>
* This will decode the RLE packed layer information and return a list of rows, with color and length information
*
* @param packedLayerImage The packed layer image information
* @param width The width of the current layer, used to change rows
* @return A list with the
*/
}
}

View file

@ -0,0 +1,44 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using MatterHackers.Agg;
/**
* by bn on 10/07/2018.
*/
namespace Photon.Parts
{
public class PhotonLine
{
public Color color;
public int length;
public PhotonLine(Color color, int length)
{
this.color = color;
this.length = length;
}
}
}

View file

@ -0,0 +1,124 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* by bn on 14/07/2018.
*/
namespace Photon.Parts
{
public class PhotonMatix
{
public int[,] calcMatrix = new int[5, 5];
public void Calc()
{
int[,] temp = new int[3, 3];
for (int yi = 0; yi < 3; yi++)
{
for (int xi = 0; xi < 3; xi++)
{
if (calcMatrix[yi + 1, xi + 1] == PhotonLayer.OFF)
{
temp[yi, xi] = Calc(xi + 1, yi + 1);
}
}
}
for (int yi = 0; yi < 3; yi++)
{
for (int xi = 0; xi < 3; xi++)
{
if (calcMatrix[yi + 1, xi + 1] == PhotonLayer.OFF)
{
calcMatrix[yi + 1, xi + 1] = temp[yi, xi];
}
}
}
}
public void Clear()
{
for (int y = 0; y < 5; y++)
{
for (int x = 0; x < 5; x++)
{
calcMatrix[y, x] = 0;
}
}
}
public void Level()
{
for (int yi = 0; yi < 5; yi++)
{
for (int xi = 0; xi < 5; xi++)
{
if (calcMatrix[yi, xi] < 4) calcMatrix[yi, xi] = 0;
}
}
}
public int Set(int x, int y, byte[][] iArray, int width, int height)
{
int blanks = 0;
int x0 = x - 2;
int y0 = y - 2;
for (int yi = 0; yi < 5; yi++)
{
for (int xi = 0; xi < 5; xi++)
{
int y2 = y0 + yi;
int x2 = x0 + xi;
if (y2 >= 0 && y2 < height && x2 >= 0 && x2 < width)
{
var value = iArray[y2][x2];
if (value == PhotonLayer.SUPPORTED
|| value == PhotonLayer.CONNECTED)
{
calcMatrix[yi, xi] = 16;
}
else if (value == PhotonLayer.ISLAND)
{
calcMatrix[yi, xi] = 4;
}
else if (value == PhotonLayer.OFF)
{
if (yi > 0 && yi < 4 && xi > 0 && xi < 4)
{
blanks++;
}
}
}
}
}
return blanks;
}
private int Calc(int x, int y)
{
return (calcMatrix[y - 1, x] / 4) + (calcMatrix[y, x - 1] / 4) + (calcMatrix[y, x + 1] / 4) + (calcMatrix[y + 1, x] / 4);
}
}
}

View file

@ -0,0 +1,36 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* by bn on 30/06/2018.
*/
namespace Photon.Parts
{
public enum PhotonProjectType
{
cast = 0,
lcdMirror = 1
}
}

View file

@ -0,0 +1,37 @@
/*
* MIT License
*
* Copyright (c) 2018 Bonosoft, 2021 Lars Brubaker c# port
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System.Collections.Generic;
/**
* by bn on 10/07/2018.
*/
namespace Photon.Parts
{
public class PhotonRow
{
public List<PhotonLine> lines = new List<PhotonLine>();
}
}

View file

@ -0,0 +1,610 @@
/*
* MIT License
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
/**
* by bn on 30/06/2018.
*/
namespace Photon.Parts
{
public class PhotonFile
{
private IFileHeader iFileHeader;
private int islandLayerCount;
private List<int> islandLayers;
private StringBuilder islandList;
private List<PhotonFileLayer> layers;
private int margin;
private List<int> marginLayers;
private PhotonFilePreview previewOne;
private PhotonFilePreview previewTwo;
public void AdjustLayerSettings()
{
for (int i = 0; i < layers.Count; i++)
{
PhotonFileLayer layer = layers[i];
if (i < iFileHeader.GetBottomLayers())
{
layer.SetLayerExposure(iFileHeader.GetBottomExposureTimeSeconds());
}
else
{
layer.SetLayerExposure(iFileHeader.GetNormalExposure());
}
layer.SetLayerOffTimeSeconds(iFileHeader.GetOffTimeSeconds());
}
}
public void Calculate(Action<string> reportProgress)
{
PhotonFileLayer.CalculateLayers((PhotonFileHeader)iFileHeader, layers, margin, reportProgress);
ResetMarginAndIslandInfo();
}
public void Calculate(int layerNo)
{
PhotonFileLayer.CalculateLayers((PhotonFileHeader)iFileHeader, layers, margin, layerNo);
ResetMarginAndIslandInfo();
}
public void CalculateAaLayers(Action<string> reportProgress, PhotonAaMatrix photonAaMatrix)
{
PhotonFileLayer.CalculateAALayers((PhotonFileHeader)iFileHeader, layers, photonAaMatrix, reportProgress);
}
public void ChangeToVersion2()
{
iFileHeader.SetFileVersion(2);
}
public void FixAll(Action<string> reportProgress)
{
bool layerWasFixed;
do
{
do
{
// Repeatedly fix layers until none are possible to fix
// Fixing some layers can make other layers auto-fixable
layerWasFixed = FixLayers(reportProgress);
} while (layerWasFixed);
if (islandLayers.Count > 0)
{
// Nothing can be done further, just remove all layers left
layerWasFixed = RemoveAllIslands(reportProgress) || layerWasFixed;
}
if (layerWasFixed && islandLayers.Count > 0)
{
// We could've created new islands by removing islands, repeat fixing process
// until everything is fixed or nothing can be done
reportProgress?.Invoke("<br>Some layers were fixed, but " + islandLayers.Count + " still unsupported, repeating...<br>");
}
} while (layerWasFixed);
}
public void FixLayerHeights()
{
int index = 0;
foreach (var layer in layers)
{
layer.SetLayerPositionZ(index * iFileHeader.GetLayerHeight());
index++;
}
}
public bool FixLayers(Action<string> reportProgress)
{
bool layersFixed = false;
PhotonLayer layer = null;
foreach (int layerNo in islandLayers)
{
reportProgress?.Invoke("Checking layer " + layerNo);
// Unpack the layer data to the layer utility class
PhotonFileLayer fileLayer = layers[layerNo];
if (layer == null)
{
layer = fileLayer.GetLayer();
}
else
{
fileLayer.GetUpdateLayer(layer);
}
int changed = Fixit(reportProgress, layer, fileLayer, 10);
if (changed == 0)
{
reportProgress?.Invoke(", but nothing could be done.");
}
else
{
fileLayer.SaveLayer(layer);
Calculate(layerNo);
if (layerNo < GetLayerCount() - 1)
{
Calculate(layerNo + 1);
}
layersFixed = true;
}
reportProgress?.Invoke("<br>");
}
FindIslands();
return layersFixed;
}
public int GetAALevels()
{
return iFileHeader.GetAALevels();
}
public int GetHeight()
{
return iFileHeader.GetResolutionX();
}
public string GetInformation()
{
if (iFileHeader == null) return "";
return iFileHeader.GetInformation();
}
public int GetIslandLayerCount()
{
if (islandList == null)
{
FindIslands();
}
return islandLayerCount;
}
public List<int> GetIslandLayers()
{
if (islandList == null)
{
FindIslands();
}
return islandLayers;
}
public PhotonFileLayer GetLayer(int i)
{
if (layers != null && layers.Count > i)
{
return layers[i];
}
return null;
}
public int GetLayerCount()
{
return iFileHeader.GetNumberOfLayers();
}
public string GetLayerInformation()
{
if (islandList == null)
{
FindIslands();
}
if (islandLayerCount == 0)
{
return "Whoopee, all is good, no unsupported areas";
}
else if (islandLayerCount == 1)
{
return "Unsupported islands found in layer " + islandList.ToString();
}
return "Unsupported islands found in layers " + islandList.ToString();
}
public string GetMarginInformation()
{
if (marginLayers == null)
{
return "No safety margin set, printing to the border.";
}
else
{
if (marginLayers.Count == 0)
{
return "The model is within the defined safety margin (" + this.margin + " pixels).";
}
else if (marginLayers.Count == 1)
{
return "The layer " + marginLayers[0] + " contains model parts that extend beyond the margin.";
}
var marginList = new StringBuilder();
int count = 0;
foreach (var layer in marginLayers)
{
if (count > 10)
{
marginList.Append(", ...");
break;
}
else
{
if (marginList.Length > 0) marginList.Append(", ");
marginList.Append(layer);
}
count++;
}
return "The layers " + marginList.ToString() + " contains model parts that extend beyond the margin.";
}
}
public List<int> GetMarginLayers()
{
if (marginLayers == null)
{
return new List<int>();
}
return marginLayers;
}
public IFileHeader GetPhotonFileHeader()
{
return iFileHeader;
}
public long GetPixels()
{
long total = 0;
if (layers != null)
{
foreach (var layer in layers)
{
total += layer.GetPixels();
}
}
return total;
}
public PhotonFilePreview GetPreviewOne()
{
return previewOne;
}
public PhotonFilePreview GetPreviewTwo()
{
return previewTwo;
}
public int GetVersion()
{
return iFileHeader.GetVersion();
}
public int GetWidth()
{
return iFileHeader.GetResolutionY();
}
public float GetZdrift()
{
float expectedHeight = iFileHeader.GetLayerHeight() * (iFileHeader.GetNumberOfLayers() - 1);
float actualHeight = layers[layers.Count - 1].GetLayerPositionZ();
return expectedHeight - actualHeight;
}
public bool HasAA()
{
return iFileHeader.HasAA();
}
public PhotonFile ReadFile(string fileName, Action<string> reportProgress)
{
using (var file = File.OpenRead(fileName))
{
return ReadFile(GetBinaryData(file), reportProgress);
}
}
public bool RemoveAllIslands(Action<string> reportProgress)
{
bool layersFixed = false;
reportProgress?.Invoke("Removing islands from " + islandLayers.Count + " layers...<br>");
PhotonLayer layer = null;
foreach (var layerNo in islandLayers)
{
PhotonFileLayer fileLayer = layers[layerNo];
if (layer == null)
{
layer = fileLayer.GetLayer();
}
else
{
fileLayer.GetUpdateLayer(layer);
}
reportProgress?.Invoke("Removing islands from layer " + layerNo);
int removed = layer.RemoveIslands();
if (removed == 0)
{
reportProgress?.Invoke(", but nothing could be done.");
}
else
{
reportProgress?.Invoke(", " + removed + " islands removed");
fileLayer.SaveLayer(layer);
Calculate(layerNo);
if (layerNo < GetLayerCount() - 1)
{
Calculate(layerNo + 1);
}
layersFixed = true;
}
reportProgress?.Invoke("<br>");
}
FindIslands();
return layersFixed;
}
public void SaveFile(string fileName)
{
using (var fileOutputStream = new BinaryWriter(File.OpenWrite(fileName)))
{
WriteFile(fileOutputStream);
}
}
// only call this when recalculating AA levels
public void SetAALevels(int levels)
{
iFileHeader.SetAALevels(levels, layers);
}
public void SetMargin(int margin)
{
this.margin = margin;
}
public void UnLink()
{
while (layers.Count > 0)
{
PhotonFileLayer layer = layers[0];
layers.RemoveAt(0);
layer.UnLink();
}
if (islandLayers != null)
{
islandLayers.Clear();
}
if (marginLayers != null)
{
marginLayers.Clear();
}
iFileHeader.UnLink();
iFileHeader = null;
previewOne.UnLink();
previewOne = null;
previewTwo.UnLink();
previewTwo = null;
}
private void FindIslands()
{
if (islandLayers != null)
{
islandLayers.Clear();
islandList = new StringBuilder();
islandLayerCount = 0;
if (layers != null)
{
for (int i = 0; i < iFileHeader.GetNumberOfLayers(); i++)
{
PhotonFileLayer layer = layers[i];
if (layer.GetIsLandsCount() > 0)
{
if (islandLayerCount < 11)
{
if (islandLayerCount == 10)
{
islandList.Append(", ...");
}
else
{
if (islandList.Length > 0) islandList.Append(", ");
islandList.Append(i);
}
}
islandLayerCount++;
islandLayers.Add(i);
}
}
}
}
}
private int Fixit(Action<string> reportProgress, PhotonLayer layer, PhotonFileLayer fileLayer, int loops)
{
int changed = layer.Fixlayer();
if (changed > 0)
{
layer.Reduce();
fileLayer.UpdateLayerIslands(layer);
reportProgress?.Invoke(", " + changed + " pixels changed");
if (loops > 0)
{
changed += Fixit(reportProgress, layer, fileLayer, loops - 1);
}
}
return changed;
}
private byte[] GetBinaryData(FileStream entry)
{
int fileSize = (int)entry.Length;
byte[] fileData = new byte[fileSize];
var stream = new BinaryReader(entry);
int bytesRead = 0;
while (bytesRead < fileSize)
{
int readCount = stream.Read(fileData, bytesRead, fileSize - bytesRead);
if (readCount < 0)
{
throw new IOException("Could not read all bytes of the file");
}
bytesRead += readCount;
}
return fileData;
}
private PhotonFile ReadFile(byte[] file, Action<string> reportProgress)
{
reportProgress?.Invoke("Reading Photon file header information...");
var photonFileHeader = new PhotonFileHeader(file);
iFileHeader = photonFileHeader;
reportProgress?.Invoke("Reading photon large preview image information...");
previewOne = new PhotonFilePreview(photonFileHeader.GetPreviewOneOffsetAddress(), file);
reportProgress?.Invoke("Reading photon small preview image information...");
previewTwo = new PhotonFilePreview(photonFileHeader.GetPreviewTwoOffsetAddress(), file);
if (photonFileHeader.GetVersion() > 1)
{
reportProgress?.Invoke("Reading Print parameters information...");
photonFileHeader.ReadParameters(file);
}
reportProgress?.Invoke("Reading photon layers information...");
layers = PhotonFileLayer.ReadLayers(photonFileHeader, file, margin, reportProgress);
ResetMarginAndIslandInfo();
return this;
}
private void ResetMarginAndIslandInfo()
{
islandList = null;
islandLayerCount = 0;
islandLayers = new List<int>();
if (margin > 0)
{
marginLayers = new List<int>();
int i = 0;
foreach (PhotonFileLayer layer in layers)
{
if (layer.DoExtendMargin())
{
marginLayers.Add(i);
}
i++;
}
}
}
private void WriteFile(BinaryWriter writer)
{
int antiAliasLevel = iFileHeader.GetAALevels();
int headerPos = 0;
int previewOnePos = headerPos + iFileHeader.GetByteSize();
int previewTwoPos = previewOnePos + previewOne.GetByteSize();
int layerDefinitionPos = previewTwoPos + previewTwo.GetByteSize();
int parametersPos = 0;
int machineInfoPos = 0;
if (iFileHeader.GetVersion() > 1)
{
parametersPos = layerDefinitionPos;
if (((PhotonFileHeader)iFileHeader).photonFileMachineInfo.GetByteSize() > 0)
{
machineInfoPos = parametersPos + ((PhotonFileHeader)iFileHeader).photonFilePrintParameters.GetByteSize();
layerDefinitionPos = machineInfoPos + ((PhotonFileHeader)iFileHeader).photonFileMachineInfo.GetByteSize();
}
else
{
layerDefinitionPos = parametersPos + ((PhotonFileHeader)iFileHeader).photonFilePrintParameters.GetByteSize();
}
}
int dataPosition = layerDefinitionPos + (PhotonFileLayer.GetByteSize() * iFileHeader.GetNumberOfLayers() * antiAliasLevel);
((PhotonFileHeader)iFileHeader).Save(writer, previewOnePos, previewTwoPos, layerDefinitionPos, parametersPos, machineInfoPos);
previewOne.Save(writer, previewOnePos);
previewTwo.Save(writer, previewTwoPos);
if (iFileHeader.GetVersion() > 1)
{
((PhotonFileHeader)iFileHeader).photonFilePrintParameters.Save(writer);
((PhotonFileHeader)iFileHeader).photonFileMachineInfo.Save(writer, machineInfoPos);
}
// Optimize order for speed read on photon
for (int i = 0; i < iFileHeader.GetNumberOfLayers(); i++)
{
PhotonFileLayer layer = layers[i];
dataPosition = layer.SavePos(dataPosition);
if (antiAliasLevel > 1)
{
for (int a = 0; a < (antiAliasLevel - 1); a++)
{
dataPosition = layer.GetAntiAlias(a).SavePos(dataPosition);
}
}
}
// Order for backward compatibility with photon/cbddlp version 1
for (int i = 0; i < iFileHeader.GetNumberOfLayers(); i++)
{
layers[i].Save(writer);
}
if (antiAliasLevel > 1)
{
for (int a = 0; a < (antiAliasLevel - 1); a++)
{
for (int i = 0; i < iFileHeader.GetNumberOfLayers(); i++)
{
layers[i].GetAntiAlias(a).Save(writer);
}
}
}
// Optimize order for speed read on photon
for (int i = 0; i < iFileHeader.GetNumberOfLayers(); i++)
{
PhotonFileLayer layer = layers[i];
layer.SaveData(writer);
if (antiAliasLevel > 1)
{
for (int a = 0; a < (antiAliasLevel - 1); a++)
{
layer.GetAntiAlias(a).SaveData(writer);
}
}
}
}
}
}

View file

@ -0,0 +1,126 @@
/*
Copyright (c) 2019, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.DataConverters3D;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.VectorMath;
namespace MatterHackers.gsBundle
{
public class SlaSlicer : IObjectSlicer
{
public async Task<bool> Slice(IEnumerable<IObject3D> printableItems, PrinterSettings printerSettings, string filePath, Action<double, string> progressReporter, CancellationToken cancellationToken)
{
using (var outputStream = File.OpenWrite(filePath))
{
foreach (var item in printableItems.Where(d => d.MeshPath != null))
{
//string sourceFilePath = await item.ResolveFilePath(null, cancellationToken);
//// Load Mesh
//if (File.Exists(sourceFilePath))
//{
// var mesh = StandardMeshReader.ReadMesh(sourceFilePath);
// if (mesh != null)
// {
// sourceMeshes.Add(mesh);
// }
// var printCenter = printerSettings.GetValue<Vector2>(SettingsKey.print_center);
// ApplyTransform(mesh, item.WorldMatrix(), printCenter);
//}
}
//var settings = LoadSettingsForPrinter(printerSettings);
// Construct slicer
//var slicer = new GeometrySlicer();
//slicer.SliceMeshes(sourceMeshes, settings);
//bool valid = slicer.ExtractResultsIfValid(out PrintMeshAssembly meshes, out PlanarSliceStack slices);
//// Construct GCode generator
//var pathGenerator = new ToolpathGenerator();
//pathGenerator.CreateToolPaths(meshes, slices, settings);
//// Write GCode file
//var gcodeWriter = new StandardGCodeWriter();
//var streamWriter = new StreamWriter(outputStream);
//gcodeWriter.WriteFile(pathGenerator.CurrentGCode, streamWriter);
return true;
}
}
public Dictionary<string, ExportField> Exports { get; } = new Dictionary<string, ExportField>()
{
[SettingsKey.bed_size] = new ExportField(""),
[SettingsKey.build_height] = new ExportField(""),
[SettingsKey.make] = new ExportField(""),
[SettingsKey.model] = new ExportField(""),
[SettingsKey.resin_cost] = new ExportField(""),
[SettingsKey.resin_density] = new ExportField(""),
[SettingsKey.sla_auto_support] = new ExportField(""),
[SettingsKey.sla_base_exposure_time] = new ExportField(""),
[SettingsKey.sla_base_min_off_time] = new ExportField(""),
[SettingsKey.sla_min_off_time] = new ExportField(""),
[SettingsKey.sla_base_lift_distance] = new ExportField(""),
[SettingsKey.sla_lift_distance] = new ExportField(""),
[SettingsKey.sla_base_lift_speed] = new ExportField(""),
[SettingsKey.sla_lift_speed] = new ExportField(""),
[SettingsKey.sla_base_layers] = new ExportField(""),
[SettingsKey.sla_create_raft] = new ExportField(""),
[SettingsKey.sla_exposure_time] = new ExportField(""),
[SettingsKey.sla_layer_height] = new ExportField(""),
[SettingsKey.sla_printable_area_inset] = new ExportField(""),
[SettingsKey.sla_resolution] = new ExportField(""),
[SettingsKey.slice_engine] = new ExportField(""),
[SettingsKey.sla_mirror_mode] = new ExportField(""),
[SettingsKey.sla_decend_speed] = new ExportField(""),
};
public bool ValidateFile(string filePath)
{
// TODO: Implement solution
System.Diagnostics.Debugger.Break();
return true;
}
public PrinterType PrinterType => PrinterType.SLA;
}
}

View file

@ -0,0 +1,51 @@
/*
Copyright (c) 2019, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using MatterHackers.MatterControl.Extensibility;
using MatterHackers.MatterControl.SlicerConfiguration;
namespace MatterHackers.gsBundle
{
public class SlaSlicerPlugin : IApplicationPlugin
{
public void Initialize()
{
PrinterSettings.SliceEngines["MH-SLA Slicer"] = new SlaSlicer();
}
public PluginInfo MetaData => new PluginInfo()
{
About = "MatterHackers SLA Slicer for MatterControl",
Developer = "MatterHackers Inc.",
Name = "MH-SLA-Slicer",
Url = "https://www.matterhackers.com/MatterControl",
UUID = "637FD858-1C6A-4B37-B001-6306933DF379"
};
}
}