-
Notifications
You must be signed in to change notification settings - Fork 0
/
Geometry.cs
128 lines (104 loc) · 4.64 KB
/
Geometry.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
namespace Magnetostatics;
public class Point2DJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => typeof(Point2D) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
var array = JArray.Load(reader);
if (array.Count == 2) return new Point2D(array[0].Value<double>(), array[1].Value<double>());
throw new FormatException($"Wrong vector length({array.Count})!");
}
if (Point2D.TryParse((string?)reader.Value ?? "", out var point)) return point;
throw new FormatException($"Can't parse({(string?)reader.Value}) as Vector2D!");
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
value ??= new Point2D();
var p = (Point2D)value;
writer.WriteRawValue($"[{p.X}, {p.Y}]");
// [[0, 0],[0, 0]] // runtime exception if use method WriteRaw()
// [[0, 0][0, 0]]
}
}
[JsonConverter(typeof(Point2DJsonConverter))]
public readonly record struct Point2D(double X, double Y)
{
public static bool TryParse(string line, out Point2D point)
{
var words = line.Split(new[] { ' ', ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
if (words.Length != 3 || !float.TryParse(words[1], out var x) || !float.TryParse(words[2], out var y))
{
point = default;
return false;
}
point = new(x, y);
return true;
}
public static Point2D operator +(Point2D a, Point2D b) => new(a.X + b.X, a.Y + b.Y);
public static Point2D operator -(Point2D a, Point2D b) => new(a.X - b.X, a.Y - b.Y);
public static Point2D operator *(Point2D p, double value) => new(p.X * value, p.Y * value);
public static Point2D operator /(Point2D p, double value) => new(p.X / value, p.Y / value);
public static Point2D operator +(Point2D p, (double, double) value) => new(p.X + value.Item1, p.Y + value.Item2);
public static Point2D operator -(Point2D p, (double, double) value) => new(p.X - value.Item1, p.Y - value.Item2);
public static implicit operator Point2D((double, double) value) => new(value.Item1, value.Item2);
}
public class IntervalJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => typeof(Interval) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
var array = JArray.Load(reader);
if (array.Count == 2) return new Interval(array[0].Value<double>(), array[1].Value<double>());
throw new FormatException($"Wrong vector length({array.Count})!");
}
if (Interval.TryParse((string?)reader.Value ?? "", out var interval)) return interval;
throw new FormatException($"Can't parse({(string?)reader.Value}) as Interval!");
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
value ??= new Interval();
var interval = (Interval)value;
serializer.Serialize(writer, interval);
}
}
[JsonConverter(typeof(IntervalJsonConverter))]
public readonly record struct Interval(
[property: JsonProperty("Left border"), JsonRequired]
double LeftBorder,
[property: JsonProperty("Right border"), JsonRequired]
double RightBorder)
{
[JsonIgnore] public double Center => (LeftBorder + RightBorder) / 2.0;
[JsonIgnore] public double Length => Math.Abs(RightBorder - LeftBorder);
public static bool TryParse(string line, out Interval interval)
{
var words = line.Split(new[] { ' ', ',', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
if (words.Length != 2 || !float.TryParse(words[0], out var x) || !float.TryParse(words[1], out var y))
{
interval = default;
return false;
}
interval = new(x, y);
return true;
}
public bool IsContain(double point)
=> point >= LeftBorder && point <= RightBorder;
}
public readonly record struct Rectangle(Point2D LeftBottom, Point2D RightTop)
{
public Point2D LeftTop { get; } = new(LeftBottom.X, RightTop.Y);
public Point2D RightBottom { get; } = new(RightTop.X, LeftBottom.Y);
}
public class FiniteElement
{
public IReadOnlyList<int> Nodes { get; }
public int AreaNumber { get; }
public FiniteElement(IReadOnlyList<int> nodes, int areaNumber)
=> (Nodes, AreaNumber) = (nodes, areaNumber);
}