You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
8.4 KiB
C#

1 month ago
/*******************************************************************************
* Author : Angus Johnson *
* Date : 16 September 2022 *
* Website : https://www.angusj.com *
* Copyright : Angus Johnson 2010-2022 *
* License : https://www.boost.org/LICENSE_1_0.txt *
*******************************************************************************/
using System;
using System.IO;
using System.Diagnostics;
namespace Clipper2Lib
{
public static class ClipperFileIO
{
public static Paths64 PathFromStr(string? s)
{
if (s == null) return new Paths64();
Path64 p = new Path64();
Paths64 pp = new Paths64();
int len = s.Length, i = 0;
while (i < len)
{
while (s[i] < 33 && i < len) i++;
if (i >= len) break;
//get X ...
bool isNeg = s[i] == 45;
if (isNeg) i++;
if (i >= len || s[i] < 48 || s[i] > 57) break;
int j = i + 1;
while (j < len && s[j] > 47 && s[j] < 58) j++;
if (!long.TryParse(s.Substring(i, j - i), out long x)) break;
if (isNeg) x = -x;
//skip space or comma between X & Y ...
i = j;
while (i < len && (s[i] == 32 || s[i] == 44)) i++;
//get Y ...
if (i >= len) break;
isNeg = s[i] == 45;
if (isNeg) i++;
if (i >= len || s[i] < 48 || s[i] > 57) break;
j = i + 1;
while (j < len && s[j] > 47 && s[j] < 58) j++;
if (!long.TryParse(s.Substring(i,j-i), out long y)) break;
if (isNeg) y = -y;
p.Add(new Point64(x, y));
//skip trailing space, comma ...
i = j;
int nlCnt = 0;
while (i < len && (s[i] < 33 || s[i] == 44))
{
if (i >= len) break;
if (s[i] == 10)
{
nlCnt++;
if (nlCnt == 2)
{
if (p.Count > 0) pp.Add(p);
p = new Path64();
}
}
i++;
}
}
if (p.Count > 0) pp.Add(p);
return pp;
}
//------------------------------------------------------------------------------
public static bool LoadTestNum(string filename, int num,
Paths64? subj, Paths64? subj_open, Paths64? clip,
out ClipType ct, out FillRule fillRule, out long area, out int count, out string caption)
{
if (subj == null) subj = new Paths64(); else subj.Clear();
if (subj_open == null) subj_open = new Paths64(); else subj_open.Clear();
if (clip == null) clip = new Paths64(); else clip.Clear();
ct = ClipType.Intersection;
fillRule = FillRule.EvenOdd;
bool result = false;
if (num < 1) num = 1;
caption = "";
area = 0;
count = 0;
StreamReader reader;
try
{
reader = new StreamReader(filename);
}
catch
{
return false;
}
while (true)
{
string? s = reader.ReadLine();
if (s == null) break;
if (s.IndexOf("CAPTION: ", StringComparison.Ordinal) == 0)
{
num--;
if (num != 0) continue;
caption = s.Substring(9);
result = true;
continue;
}
if (num > 0) continue;
if (s.IndexOf("CLIPTYPE: ", StringComparison.Ordinal) == 0)
{
if (s.IndexOf("INTERSECTION", StringComparison.Ordinal) > 0) ct = ClipType.Intersection;
else if (s.IndexOf("UNION", StringComparison.Ordinal) > 0) ct = ClipType.Union;
else if (s.IndexOf("DIFFERENCE", StringComparison.Ordinal) > 0) ct = ClipType.Difference;
else ct = ClipType.Xor;
continue;
}
if (s.IndexOf("FILLTYPE: ", StringComparison.Ordinal) == 0 ||
s.IndexOf("FILLRULE: ", StringComparison.Ordinal) == 0)
{
if (s.IndexOf("EVENODD", StringComparison.Ordinal) > 0) fillRule = FillRule.EvenOdd;
else if (s.IndexOf("POSITIVE", StringComparison.Ordinal) > 0) fillRule = FillRule.Positive;
else if (s.IndexOf("NEGATIVE", StringComparison.Ordinal) > 0) fillRule = FillRule.Negative;
else fillRule = FillRule.NonZero;
continue;
}
if (s.IndexOf("SOL_AREA: ", StringComparison.Ordinal) == 0)
{
area = long.Parse(s.Substring(10));
continue;
}
if (s.IndexOf("SOL_COUNT: ", StringComparison.Ordinal) == 0)
{
count = int.Parse(s.Substring(11));
continue;
}
int GetIdx;
if (s.IndexOf("SUBJECTS_OPEN", StringComparison.Ordinal) == 0) GetIdx = 2;
else if (s.IndexOf("SUBJECTS", StringComparison.Ordinal) == 0) GetIdx = 1;
else if (s.IndexOf("CLIPS", StringComparison.Ordinal) == 0) GetIdx = 3;
else continue;
while (true)
{
s = reader.ReadLine();
if (s == null) break;
Paths64? paths = PathFromStr(s); //0 or 1 path
if (paths == null || paths.Count == 0)
{
if (GetIdx == 3) return result;
if (s.IndexOf("SUBJECTS_OPEN", StringComparison.Ordinal) == 0) GetIdx = 2;
else if (s.IndexOf("CLIPS", StringComparison.Ordinal) == 0) GetIdx = 3;
else return result;
continue;
}
switch (GetIdx)
{
case 1:
subj.Add(paths[0]);
break;
case 2:
subj_open.Add(paths[0]);
break;
default:
clip.Add(paths[0]);
break;
}
}
}
return result;
}
//-----------------------------------------------------------------------
public static void SaveClippingOp(string filename, Paths64? subj,
Paths64? subj_open, Paths64? clip, ClipType ct, FillRule fillRule, bool append)
{
StreamWriter writer;
try
{
writer = new StreamWriter(filename, append);
}
catch
{
return;
}
writer.Write("CAPTION: 1. \r\n");
writer.Write("CLIPTYPE: {0}\r\n", ct.ToString().ToUpper());
writer.Write("FILLRULE: {0}\r\n", fillRule.ToString().ToUpper());
if (subj != null && subj.Count > 0)
{
writer.Write("SUBJECTS\r\n");
foreach (Path64 p in subj)
{
foreach (Point64 ip in p)
writer.Write("{0},{1} ", ip.X, ip.Y);
writer.Write("\r\n");
}
}
if (subj_open != null && subj_open.Count > 0)
{
writer.Write("SUBJECTS_OPEN\r\n");
foreach (Path64 p in subj_open)
{
foreach (Point64 ip in p)
writer.Write("{0},{1} ", ip.X, ip.Y);
writer.Write("\r\n");
}
}
if (clip != null && clip.Count > 0)
{
writer.Write("CLIPS\r\n");
foreach (Path64 p in clip)
{
foreach (Point64 ip in p)
writer.Write(ip.ToString());
writer.Write("\r\n");
}
}
writer.Close();
}
public static void SaveToBinFile(string filename, Paths64 paths)
{
FileStream filestream;
try
{
filestream = new FileStream(filename, FileMode.Create);
}
catch
{
return;
}
BinaryWriter writer;
try
{
writer = new BinaryWriter(filestream);
}
catch
{
return;
}
writer.Write(paths.Count);
foreach (Path64 path in paths)
{
writer.Write(path.Count);
foreach (Point64 pt in path)
{
writer.Write(pt.X);
writer.Write(pt.Y);
}
}
writer.Close();
}
//------------------------------------------------------------------------------
public static Paths64 AffineTranslatePaths(Paths64 paths, long dx, long dy)
{
Paths64 result = new Paths64(paths.Count);
foreach (Path64 path in paths)
{
Path64 p = new Path64(path.Count);
foreach (Point64 pt in path)
p.Add(new Point64(pt.X + dx, pt.Y + dy));
result.Add(p);
}
return result;
}
public static void OpenFileWithDefaultApp(string filename)
{
string path = Path.GetFullPath(filename);
if (!File.Exists(path)) return;
Process p = new Process() { StartInfo = new ProcessStartInfo(path) { UseShellExecute = true } };
p.Start();
}
}
}