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#
284 lines
8.4 KiB
C#
/*******************************************************************************
|
|
* 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();
|
|
}
|
|
|
|
}
|
|
}
|