feat: линейный массив (linear_pattern) — ksMeshCopyDefinition o3d_meshCopy
- CoordinateAxis enum + CoordinateAxes.ToObj3dType/Parse (X/Y/Z → o3d_axisO*) - SketchGeometry.RequireMin; PartModeler.RequireFeature (источник по id из _features) - LinearPatternAsync: SetAxis1 + SetCopyParamAlongAxis(true,0,count,step,false), count2=1 - инструмент linear_pattern; unit-тесты (RequireMin, Parse), интеграционный тест (3 экз. ±5%) - эмпирически: count включает исходный, step мм между соседними, count2=1 выключает 2D
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
using Kompas.Mcp.Core.Modeling;
|
||||
|
||||
namespace Kompas.Mcp.Tests;
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class CoordinateAxisTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("X", CoordinateAxis.X)]
|
||||
[InlineData("y", CoordinateAxis.Y)]
|
||||
[InlineData(" Z ", CoordinateAxis.Z)]
|
||||
public void Parse_maps_known(string value, CoordinateAxis expected)
|
||||
=> Assert.Equal(expected, CoordinateAxes.Parse(value));
|
||||
|
||||
[Theory]
|
||||
[InlineData("W")]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
public void Parse_throws_on_unknown(string? value)
|
||||
=> Assert.Throws<ArgumentException>(() => CoordinateAxes.Parse(value!));
|
||||
}
|
||||
@@ -136,6 +136,35 @@ public sealed class FeatureOpsTests
|
||||
finally { await _docs.CloseAsync(save: false); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LinearPattern_replicates_cylinder_along_X()
|
||||
{
|
||||
await _docs.CreateAsync(KompasDocumentType.Part);
|
||||
try
|
||||
{
|
||||
// Цилиндр R5×H10 в центре (объём π·25·10 ≈ 785.4 мм³).
|
||||
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
|
||||
await _modeler.AddCircleAsync(s, 0, 0, 5);
|
||||
await _modeler.CloseSketchAsync(s);
|
||||
var cyl = await _modeler.ExtrudeAsync(s, depth: 10);
|
||||
var one = (await _query.GetPartInfoAsync()).Volume;
|
||||
|
||||
// Линейный массив: 3 экземпляра вдоль X с шагом 30 (R5 → не перекрываются).
|
||||
var id = await _modeler.LinearPatternAsync(new[] { cyl }, CoordinateAxis.X, count: 3, step: 30);
|
||||
Assert.True(id > 0);
|
||||
await _modeler.RebuildAsync();
|
||||
|
||||
// count=3 включает исходный → суммарный объём ≈ 3 цилиндра.
|
||||
var v = (await _query.GetPartInfoAsync()).Volume;
|
||||
Assert.InRange(v, one * 3 * 0.95, one * 3 * 1.05);
|
||||
|
||||
// Габарит вдоль X: копии в 0/30/60, R5 → от −5 до 65 → размер ≈70 (знак шага не важен).
|
||||
var box = await _query.GetBoundingBoxAsync();
|
||||
Assert.InRange(box.SizeX, 70 * 0.95, 70 * 1.05);
|
||||
}
|
||||
finally { await _docs.CloseAsync(save: false); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Loft_two_squares_makes_solid()
|
||||
{
|
||||
|
||||
@@ -45,6 +45,14 @@ public sealed class SketchGeometryTests
|
||||
Assert.Null(Record.Exception(() => SketchGeometry.RequireVertexCount(3)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequireMin_throws_below_min()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => SketchGeometry.RequireMin(1, 2, "count"));
|
||||
Assert.Null(Record.Exception(() => SketchGeometry.RequireMin(2, 2, "count")));
|
||||
Assert.Null(Record.Exception(() => SketchGeometry.RequireMin(5, 2, "count")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequirePoints_throws_on_null()
|
||||
=> Assert.Throws<ArgumentNullException>(
|
||||
|
||||
Reference in New Issue
Block a user