chore: add .editorconfig and pinned CSharpier tool manifest
Mirrors CSharpier conventions (4-space indent, Allman braces, System-first usings, 100-col wraps) so IDE auto-format and 'dotnet format' agree with the canonical formatter. Usage: dotnet tool restore && dotnet csharpier format .
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"csharpier": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"commands": [
|
||||||
|
"csharpier"
|
||||||
|
],
|
||||||
|
"rollForward": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Unified code style for OpenNest.
|
||||||
|
# Canonical formatter: CSharpier (see .config/dotnet-tools.json).
|
||||||
|
# dotnet tool restore
|
||||||
|
# dotnet csharpier check . # verify before committing
|
||||||
|
# dotnet csharpier format . # fix
|
||||||
|
# These settings match CSharpier's conventions so IDE auto-formatting
|
||||||
|
# (VS / Rider / VS Code) stays consistent with the formatter.
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{csproj,props,targets,xml,config,manifest}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{json,yml,yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{cs,csx}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
# CSharpier wraps code at 100 columns; dotnet format cannot re-wrap, but
|
||||||
|
# IDEs surface a visual guide and analyzers can flag hard violations.
|
||||||
|
max_line_length = 100
|
||||||
|
|
||||||
|
# --- Using directives (System first, outside the namespace) ---
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
csharp_using_directive_placement = outside_namespace:warning
|
||||||
|
|
||||||
|
# --- Brace placement: Allman (opening brace on its own line) ---
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
csharp_new_line_between_query_expression_clauses = true
|
||||||
|
|
||||||
|
# --- Spacing ---
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_comma = true
|
||||||
|
csharp_space_before_comma = false
|
||||||
|
|
||||||
|
# --- Code style preferences ---
|
||||||
|
# Project rule: always use var for locals (see CLAUDE.md).
|
||||||
|
csharp_style_var_for_built_in_types = true:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||||
|
csharp_style_var_elsewhere = true:suggestion
|
||||||
|
csharp_prefer_braces = true:suggestion
|
||||||
|
csharp_prefer_simple_using_statement = true:suggestion
|
||||||
|
csharp_style_namespace_declarations = file_scoped:silent
|
||||||
|
dotnet_style_prefer_auto_properties = true:suggestion
|
||||||
|
dotnet_style_object_initializer = true:suggestion
|
||||||
|
dotnet_style_collection_initializer = true:suggestion
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||||
@@ -6,7 +6,12 @@ using OpenNest.Geometry;
|
|||||||
|
|
||||||
namespace OpenNest.IO.Bending
|
namespace OpenNest.IO.Bending
|
||||||
{
|
{
|
||||||
public enum BendRepairUnits { Unspecified, Inches, Millimeters }
|
public enum BendRepairUnits
|
||||||
|
{
|
||||||
|
Unspecified,
|
||||||
|
Inches,
|
||||||
|
Millimeters,
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Explicit opt-in. Distances are physical millimeters, not drawing coordinates.</summary>
|
/// <summary>Explicit opt-in. Distances are physical millimeters, not drawing coordinates.</summary>
|
||||||
public sealed class BendRepairOptions
|
public sealed class BendRepairOptions
|
||||||
@@ -15,28 +20,49 @@ namespace OpenNest.IO.Bending
|
|||||||
public double MaxEndpointMovementMillimeters { get; set; }
|
public double MaxEndpointMovementMillimeters { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed record BendRepairReport(int BendIndex, string Status, string Reason,
|
public sealed record BendRepairReport(
|
||||||
Vector OriginalStart, Vector OriginalEnd, Vector Start, Vector End);
|
int BendIndex,
|
||||||
|
string Status,
|
||||||
|
string Reason,
|
||||||
|
Vector OriginalStart,
|
||||||
|
Vector OriginalEnd,
|
||||||
|
Vector Start,
|
||||||
|
Vector End
|
||||||
|
);
|
||||||
|
|
||||||
/// <summary>Conservative, atomic repair. Never edits cut entities or unassociated marks.</summary>
|
/// <summary>Conservative, atomic repair. Never edits cut entities or unassociated marks.</summary>
|
||||||
public static class BendRepair
|
public static class BendRepair
|
||||||
{
|
{
|
||||||
public static List<BendRepairReport> Apply(List<Entity> entities, List<Bend> bends, BendRepairOptions options)
|
public static List<BendRepairReport> Apply(
|
||||||
|
List<Entity> entities,
|
||||||
|
List<Bend> bends,
|
||||||
|
BendRepairOptions options
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var reports = new List<BendRepairReport>();
|
var reports = new List<BendRepairReport>();
|
||||||
if (options == null) return reports;
|
if (options == null)
|
||||||
|
return reports;
|
||||||
var scale = options.DrawingUnits == BendRepairUnits.Inches ? 1 / 25.4 : 1.0;
|
var scale = options.DrawingUnits == BendRepairUnits.Inches ? 1 / 25.4 : 1.0;
|
||||||
var tolerance = 0.001 * scale;
|
var tolerance = 0.001 * scale;
|
||||||
var limit = options.MaxEndpointMovementMillimeters * scale;
|
var limit = options.MaxEndpointMovementMillimeters * scale;
|
||||||
var valid = (options.DrawingUnits == BendRepairUnits.Inches || options.DrawingUnits == BendRepairUnits.Millimeters)
|
var valid =
|
||||||
&& double.IsFinite(limit) && limit > tolerance && options.MaxEndpointMovementMillimeters <= 3.175;
|
(
|
||||||
|
options.DrawingUnits == BendRepairUnits.Inches
|
||||||
|
|| options.DrawingUnits == BendRepairUnits.Millimeters
|
||||||
|
)
|
||||||
|
&& double.IsFinite(limit)
|
||||||
|
&& limit > tolerance
|
||||||
|
&& options.MaxEndpointMovementMillimeters <= 3.175;
|
||||||
var original = bends.Select(b => (b.StartPoint, b.EndPoint)).ToArray();
|
var original = bends.Select(b => (b.StartPoint, b.EndPoint)).ToArray();
|
||||||
var marks = entities.OfType<Line>().Where(IsMark).ToList();
|
var marks = entities.OfType<Line>().Where(IsMark).ToList();
|
||||||
var cuts = entities.Where(IsCut).ToList();
|
var cuts = entities.Where(IsCut).ToList();
|
||||||
// ShapeBuilder may reverse/weld its inputs; isolate it from all source geometry.
|
// ShapeBuilder may reverse/weld its inputs; isolate it from all source geometry.
|
||||||
var shapes = ShapeBuilder.GetShapes(cuts.CloneAll(), tolerance);
|
var shapes = ShapeBuilder.GetShapes(cuts.CloneAll(), tolerance);
|
||||||
var boundaries = shapes.Where(s => s.IsClosed()).SelectMany(s => s.Entities).ToList();
|
var boundaries = shapes.Where(s => s.IsClosed()).SelectMany(s => s.Entities).ToList();
|
||||||
var polygons = shapes.Where(s => s.IsClosed()).Select(s => s.ToPolygonWithTolerance(tolerance / 10)).ToList();
|
var polygons = shapes
|
||||||
|
.Where(s => s.IsClosed())
|
||||||
|
.Select(s => s.ToPolygonWithTolerance(tolerance / 10))
|
||||||
|
.ToList();
|
||||||
bool InMaterial(Vector point) => polygons.Count(p => p.ContainsPoint(point)) % 2 == 1;
|
bool InMaterial(Vector point) => polygons.Count(p => p.ContainsPoint(point)) % 2 == 1;
|
||||||
|
|
||||||
for (var i = 0; i < bends.Count; i++)
|
for (var i = 0; i < bends.Count; i++)
|
||||||
@@ -45,55 +71,96 @@ namespace OpenNest.IO.Bending
|
|||||||
var (start, end) = original[i];
|
var (start, end) = original[i];
|
||||||
var reason = "";
|
var reason = "";
|
||||||
var status = "Skipped";
|
var status = "Skipped";
|
||||||
if (!valid) reason = "Specify drawing units and a finite movement limit above 0.001 and at most 3.175 mm.";
|
if (!valid)
|
||||||
|
reason =
|
||||||
|
"Specify drawing units and a finite movement limit above 0.001 and at most 3.175 mm.";
|
||||||
else if (!Finite(start) || !Finite(end) || start.DistanceTo(end) <= 2 * limit)
|
else if (!Finite(start) || !Finite(end) || start.DistanceTo(end) <= 2 * limit)
|
||||||
reason = "Invalid or too-short bend axis.";
|
reason = "Invalid or too-short bend axis.";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var axis = (end - start) / start.DistanceTo(end);
|
var axis = (end - start) / start.DistanceTo(end);
|
||||||
var first = marks.Where(m => Associated(m, start, end, tolerance, scale)).ToList();
|
var first = marks
|
||||||
var last = marks.Where(m => Associated(m, end, start, tolerance, scale)).ToList();
|
.Where(m => Associated(m, start, end, tolerance, scale))
|
||||||
|
.ToList();
|
||||||
|
var last = marks
|
||||||
|
.Where(m => Associated(m, end, start, tolerance, scale))
|
||||||
|
.ToList();
|
||||||
if (first.Count != 1 || last.Count != 1 || ReferenceEquals(first[0], last[0]))
|
if (first.Count != 1 || last.Count != 1 || ReferenceEquals(first[0], last[0]))
|
||||||
reason = "Missing or ambiguous collinear ticks at both original endpoints.";
|
reason = "Missing or ambiguous collinear ticks at both original endpoints.";
|
||||||
else if (original.Where((_, j) => j != i).Any(b =>
|
else if (
|
||||||
Associated(first[0], b.StartPoint, b.EndPoint, tolerance, scale) ||
|
original
|
||||||
Associated(first[0], b.EndPoint, b.StartPoint, tolerance, scale) ||
|
.Where((_, j) => j != i)
|
||||||
Associated(last[0], b.StartPoint, b.EndPoint, tolerance, scale) ||
|
.Any(b =>
|
||||||
Associated(last[0], b.EndPoint, b.StartPoint, tolerance, scale)))
|
Associated(first[0], b.StartPoint, b.EndPoint, tolerance, scale)
|
||||||
|
|| Associated(first[0], b.EndPoint, b.StartPoint, tolerance, scale)
|
||||||
|
|| Associated(last[0], b.StartPoint, b.EndPoint, tolerance, scale)
|
||||||
|
|| Associated(last[0], b.EndPoint, b.StartPoint, tolerance, scale)
|
||||||
|
)
|
||||||
|
)
|
||||||
reason = "Tick is shared with another bend.";
|
reason = "Tick is shared with another bend.";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var probe = new Line(start - axis * limit, end + axis * limit);
|
var probe = new Line(start - axis * limit, end + axis * limit);
|
||||||
var hits = new List<Vector>();
|
var hits = new List<Vector>();
|
||||||
var uncertain = shapes.Where(s => !s.IsClosed()).Any(s => s.Intersects(probe));
|
var uncertain = shapes
|
||||||
|
.Where(s => !s.IsClosed())
|
||||||
|
.Any(s => s.Intersects(probe));
|
||||||
foreach (var edge in boundaries)
|
foreach (var edge in boundaries)
|
||||||
{
|
{
|
||||||
if (edge is Line line && OnAxis(line.StartPoint, start, axis, tolerance)
|
if (
|
||||||
|
edge is Line line
|
||||||
|
&& OnAxis(line.StartPoint, start, axis, tolerance)
|
||||||
&& OnAxis(line.EndPoint, start, axis, tolerance)
|
&& OnAxis(line.EndPoint, start, axis, tolerance)
|
||||||
&& System.Math.Max(Dot(line.StartPoint - start, axis), Dot(line.EndPoint - start, axis)) >= -limit
|
&& System.Math.Max(
|
||||||
&& System.Math.Min(Dot(line.StartPoint - start, axis), Dot(line.EndPoint - start, axis)) <= bend.Length + limit)
|
Dot(line.StartPoint - start, axis),
|
||||||
|
Dot(line.EndPoint - start, axis)
|
||||||
|
) >= -limit
|
||||||
|
&& System.Math.Min(
|
||||||
|
Dot(line.StartPoint - start, axis),
|
||||||
|
Dot(line.EndPoint - start, axis)
|
||||||
|
)
|
||||||
|
<= bend.Length + limit
|
||||||
|
)
|
||||||
uncertain = true;
|
uncertain = true;
|
||||||
if (edge.Intersects(probe, out var points))
|
if (edge.Intersects(probe, out var points))
|
||||||
foreach (var p in points)
|
foreach (var p in points)
|
||||||
if (Finite(p) && !hits.Any(h => h.DistanceTo(p) <= tolerance)) hits.Add(p);
|
if (Finite(p) && !hits.Any(h => h.DistanceTo(p) <= tolerance))
|
||||||
|
hits.Add(p);
|
||||||
}
|
}
|
||||||
var nearStart = hits.Where(p => p.DistanceTo(start) <= limit).ToList();
|
var nearStart = hits.Where(p => p.DistanceTo(start) <= limit).ToList();
|
||||||
var nearEnd = hits.Where(p => p.DistanceTo(end) <= limit).ToList();
|
var nearEnd = hits.Where(p => p.DistanceTo(end) <= limit).ToList();
|
||||||
if (uncertain || hits.Count != 2 || nearStart.Count != 1 || nearEnd.Count != 1)
|
if (
|
||||||
reason = "Missing/ambiguous closed cut boundaries, interior crossing, or movement exceeds limit.";
|
uncertain
|
||||||
|
|| hits.Count != 2
|
||||||
|
|| nearStart.Count != 1
|
||||||
|
|| nearEnd.Count != 1
|
||||||
|
)
|
||||||
|
reason =
|
||||||
|
"Missing/ambiguous closed cut boundaries, interior crossing, or movement exceeds limit.";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Project the intersection back onto the existing axis; never rotate a bend.
|
// Project the intersection back onto the existing axis; never rotate a bend.
|
||||||
var newStart = start + axis * Dot(nearStart[0] - start, axis);
|
var newStart = start + axis * Dot(nearStart[0] - start, axis);
|
||||||
var newEnd = start + axis * Dot(nearEnd[0] - start, axis);
|
var newEnd = start + axis * Dot(nearEnd[0] - start, axis);
|
||||||
var sample = axis * (10 * tolerance);
|
var sample = axis * (10 * tolerance);
|
||||||
if (!InMaterial((newStart + newEnd) / 2)
|
if (
|
||||||
|| !InMaterial(newStart + sample) || !InMaterial(newEnd - sample)
|
!InMaterial((newStart + newEnd) / 2)
|
||||||
|| InMaterial(newStart - sample) || InMaterial(newEnd + sample))
|
|| !InMaterial(newStart + sample)
|
||||||
reason = "Endpoints do not bound an unambiguous material interval (possible tangent).";
|
|| !InMaterial(newEnd - sample)
|
||||||
else if (Dot(newEnd - newStart, axis) <= first[0].Length + last[0].Length + tolerance)
|
|| InMaterial(newStart - sample)
|
||||||
|
|| InMaterial(newEnd + sample)
|
||||||
|
)
|
||||||
|
reason =
|
||||||
|
"Endpoints do not bound an unambiguous material interval (possible tangent).";
|
||||||
|
else if (
|
||||||
|
Dot(newEnd - newStart, axis)
|
||||||
|
<= first[0].Length + last[0].Length + tolerance
|
||||||
|
)
|
||||||
reason = "Repaired ticks would overlap or reverse the bend.";
|
reason = "Repaired ticks would overlap or reverse the bend.";
|
||||||
else if (newStart.DistanceTo(start) <= tolerance && newEnd.DistanceTo(end) <= tolerance)
|
else if (
|
||||||
|
newStart.DistanceTo(start) <= tolerance
|
||||||
|
&& newEnd.DistanceTo(end) <= tolerance
|
||||||
|
)
|
||||||
{
|
{
|
||||||
status = "Unchanged";
|
status = "Unchanged";
|
||||||
reason = "Already on cut boundaries.";
|
reason = "Already on cut boundaries.";
|
||||||
@@ -107,7 +174,8 @@ namespace OpenNest.IO.Bending
|
|||||||
b.Offset(newEnd - end);
|
b.Offset(newEnd - end);
|
||||||
var ai = entities.IndexOf(first[0]);
|
var ai = entities.IndexOf(first[0]);
|
||||||
var bi = entities.IndexOf(last[0]);
|
var bi = entities.IndexOf(last[0]);
|
||||||
if (ai < 0 || bi < 0) reason = "Tick was already consumed; unchanged.";
|
if (ai < 0 || bi < 0)
|
||||||
|
reason = "Tick was already consumed; unchanged.";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entities[ai] = a;
|
entities[ai] = a;
|
||||||
@@ -115,40 +183,85 @@ namespace OpenNest.IO.Bending
|
|||||||
bend.StartPoint = newStart;
|
bend.StartPoint = newStart;
|
||||||
bend.EndPoint = newEnd;
|
bend.EndPoint = newEnd;
|
||||||
status = "Repaired";
|
status = "Repaired";
|
||||||
reason = "Both endpoints snapped along axis; only their two associated ticks replaced.";
|
reason =
|
||||||
|
"Both endpoints snapped along axis; only their two associated ticks replaced.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reports.Add(new BendRepairReport(i, status, reason, start, end, bend.StartPoint, bend.EndPoint));
|
reports.Add(
|
||||||
|
new BendRepairReport(
|
||||||
|
i,
|
||||||
|
status,
|
||||||
|
reason,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
bend.StartPoint,
|
||||||
|
bend.EndPoint
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return reports;
|
return reports;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool Finite(Vector p) => double.IsFinite(p.X) && double.IsFinite(p.Y);
|
private static bool Finite(Vector p) => double.IsFinite(p.X) && double.IsFinite(p.Y);
|
||||||
|
|
||||||
private static double Dot(Vector a, Vector b) => a.X * b.X + a.Y * b.Y;
|
private static double Dot(Vector a, Vector b) => a.X * b.X + a.Y * b.Y;
|
||||||
|
|
||||||
private static bool OnAxis(Vector p, Vector origin, Vector axis, double tolerance) =>
|
private static bool OnAxis(Vector p, Vector origin, Vector axis, double tolerance) =>
|
||||||
System.Math.Abs((p.X - origin.X) * axis.Y - (p.Y - origin.Y) * axis.X) <= tolerance;
|
System.Math.Abs((p.X - origin.X) * axis.Y - (p.Y - origin.Y) * axis.X) <= tolerance;
|
||||||
private static bool Continuous(Entity e) => string.IsNullOrEmpty(e.LineTypeName)
|
|
||||||
|
private static bool Continuous(Entity e) =>
|
||||||
|
string.IsNullOrEmpty(e.LineTypeName)
|
||||||
|| string.Equals(e.LineTypeName, "Continuous", StringComparison.OrdinalIgnoreCase)
|
|| string.Equals(e.LineTypeName, "Continuous", StringComparison.OrdinalIgnoreCase)
|
||||||
|| string.Equals(e.LineTypeName, "ByLayer", StringComparison.OrdinalIgnoreCase);
|
|| string.Equals(e.LineTypeName, "ByLayer", StringComparison.OrdinalIgnoreCase);
|
||||||
private static bool IsMark(Entity e) => Continuous(e) &&
|
|
||||||
(string.Equals(e.Layer?.Name, "ETCH", StringComparison.OrdinalIgnoreCase)
|
private static bool IsMark(Entity e) =>
|
||||||
|| string.Equals(e.Layer?.Name, "SCRIBE", StringComparison.OrdinalIgnoreCase));
|
Continuous(e)
|
||||||
private static bool IsCut(Entity e) => Continuous(e) &&
|
&& (
|
||||||
(e.Layer?.Name == "0" || string.Equals(e.Layer?.Name, "CUT", StringComparison.OrdinalIgnoreCase))
|
string.Equals(e.Layer?.Name, "ETCH", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(e.Layer?.Name, "SCRIBE", StringComparison.OrdinalIgnoreCase)
|
||||||
|
);
|
||||||
|
|
||||||
|
private static bool IsCut(Entity e) =>
|
||||||
|
Continuous(e)
|
||||||
|
&& (
|
||||||
|
e.Layer?.Name == "0"
|
||||||
|
|| string.Equals(e.Layer?.Name, "CUT", StringComparison.OrdinalIgnoreCase)
|
||||||
|
)
|
||||||
&& (e is Line || e is Arc || e is Circle);
|
&& (e is Line || e is Arc || e is Circle);
|
||||||
private static bool Associated(Line mark, Vector endpoint, Vector other, double tolerance, double scale)
|
|
||||||
|
private static bool Associated(
|
||||||
|
Line mark,
|
||||||
|
Vector endpoint,
|
||||||
|
Vector other,
|
||||||
|
double tolerance,
|
||||||
|
double scale
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var length = endpoint.DistanceTo(other);
|
var length = endpoint.DistanceTo(other);
|
||||||
if (!Finite(endpoint) || !Finite(other) || length <= tolerance || !Finite(mark.StartPoint) || !Finite(mark.EndPoint)
|
if (
|
||||||
|| mark.Length <= tolerance || mark.Length > 25.4 * scale + tolerance || mark.Length >= length / 3) return false;
|
!Finite(endpoint)
|
||||||
|
|| !Finite(other)
|
||||||
|
|| length <= tolerance
|
||||||
|
|| !Finite(mark.StartPoint)
|
||||||
|
|| !Finite(mark.EndPoint)
|
||||||
|
|| mark.Length <= tolerance
|
||||||
|
|| mark.Length > 25.4 * scale + tolerance
|
||||||
|
|| mark.Length >= length / 3
|
||||||
|
)
|
||||||
|
return false;
|
||||||
var axis = (other - endpoint) / length;
|
var axis = (other - endpoint) / length;
|
||||||
if (!OnAxis(mark.StartPoint, endpoint, axis, tolerance) || !OnAxis(mark.EndPoint, endpoint, axis, tolerance)) return false;
|
if (
|
||||||
|
!OnAxis(mark.StartPoint, endpoint, axis, tolerance)
|
||||||
|
|| !OnAxis(mark.EndPoint, endpoint, axis, tolerance)
|
||||||
|
)
|
||||||
|
return false;
|
||||||
var a = Dot(mark.StartPoint - endpoint, axis);
|
var a = Dot(mark.StartPoint - endpoint, axis);
|
||||||
var b = Dot(mark.EndPoint - endpoint, axis);
|
var b = Dot(mark.EndPoint - endpoint, axis);
|
||||||
return System.Math.Abs(System.Math.Min(a, b)) <= tolerance && System.Math.Max(a, b) > tolerance;
|
return System.Math.Abs(System.Math.Min(a, b)) <= tolerance
|
||||||
|
&& System.Math.Max(a, b) > tolerance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,15 @@ cd OpenNest
|
|||||||
dotnet build OpenNest.sln
|
dotnet build OpenNest.sln
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Code formatting
|
||||||
|
|
||||||
|
C# sources are formatted with [CSharpier](https://csharpier.com/), pinned in `.config/dotnet-tools.json`; the matching style (4-space indent, Allman braces, System-first usings, 100-column wraps) is mirrored in `.editorconfig` so IDE auto-format agrees. Before committing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet tool restore
|
||||||
|
dotnet csharpier format . # apply; use `check` instead of `format` to verify only
|
||||||
|
```
|
||||||
|
|
||||||
### Cross-platform engine contract tests
|
### Cross-platform engine contract tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
Reference in New Issue
Block a user