Compare commits

..
31 Commits
Author SHA1 Message Date
iambossandClaude Opus 5.5 bc67d8469b fix(demos): the machining demos dispose their LocalProjectService before LocalApp.AppEnd -- DemoUseMachiningProject, DemoBuildMachiningProject and DemoBuildGeomOnlyMachiningProject ended with machiningProject.Dispose(); LocalApp.AppEnd();, so the service was never disposed: MachiningProject.Dispose releases only the project's TimeMapping, while the service's machining runner keeps its threads, its native pipeline, the strip and the workpiece tree, everything AppEnd's documentation asks to be gone before it ends the native core. Each demo now disposes the service right after the project, one line with a comment saying why; not a using declaration, which would dispose it after AppEnd.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:07:15 +08:00
iambossandClaude Fable 5.1 a03aa1c1ff fix(demos): DemoBuildMachineTool puts the spindle's pivot on the tool-mount offset
CreateFromChainCode now seeds S with a DynamicRotation about -Z through S's origin (the spindle
role); the sample moves the tool mount to (-72.40, 72.40, 176.44) right after, so it moves the
spindle's pivot there too -- otherwise turning the spindle would swing the tool around S's origin.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 16:42:52 +08:00
iambossandClaude Fable 5.1 46bfea4a87 refactor(Hi.Sample): Mat4d is spelled mat4d_t -- the workspace-wide word-boundary rename that follows HiGeom naming the matrix struct after the C++ typedef; compound identifiers (GetMat4dMap, Mat4dKey, ProgramZeroToGeomMat4d, ...) and the "Mat4d" JSON key keep their spelling, no behaviour changes
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 15:48:56 +08:00
iambossandClaude Fable 5.1 734ed008b0 refactor(Hi.Sample): geometry slots take new Box3d(...) -- DemoBuildGeom's IGetStl list and the fixture and workpiece geometries of DemoBuildGeomOnlyMachiningProject and DemoBuildMachiningProject: box3d_t is the value only after HiGeom's box geometry split and no longer fits an IGetStl / IMakeXmlSource slot; the demos' value uses (bounds, ExpandToBox3d, drawings) stay box3d_t
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 00:22:01 +08:00
iambossandClaude Fable 5.1 1b834cff0d refactor(Hi.Sample)!: Box3d, Tri3d, DVec3d and Box2d are named box3d_t, tri3d_t, dvec3d_t and box2d_t -- the C++ typedef names, following HiGeom; the Hi.Native vec3d/tri3d/box3d mirrors are the Hi.Geom values now and vec3f is Hi.Geom.vec3f_t (a word-boundary identifier rename; compound names, string literals and the wire kind names are untouched)
BREAKING CHANGE: source that names these types must use the _t names; the Hi.Native mirrors are gone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 13:54:35 +08:00
iambossandClaude Fable 5.1 7d79db5685 refactor(Hi.Sample): follow HiGeom's Box3d struct -- the demo displayees take ref Box3d and expand through Expanded, DemoSatellite scales its boxes with ScaledFromCenter, and MachiningProjectDisplayee forwards ref dst to the assembly
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 13:05:35 +08:00
iambossandClaude Fable 5.1 060fb66029 refactor(Hi.Sample): follow HiGeom's Tri3d struct -- DemoDrawing reads the apexes through the indexer instead of the ps array
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 12:19:45 +08:00
iambossandClaude Fable 5.1 6571576eaa refactor(Hi.Sample)!: Vec3d and Vec2d are named vec3d_t and vec2d_t -- the C++ typedef names, following HiGeom 43fccaf (a word-boundary identifier rename over the 14 demo files the 09-24 rename batch left behind; the repo builds against the HiGeom project reference, so it had stopped compiling)
BREAKING CHANGE: source that names Hi.Geom.Vec3d or Hi.Geom.Vec2d as the vector type must say vec3d_t / vec2d_t.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 10:21:20 +08:00
iambossandClaude Fable 5.1 f4ec31806b refactor(Hi.Sample): the two coordinate-entry displayees place their markers through TryGetIsoCoordinatePosition and TryGetMachinePositionAtTableMountZero -- follows HiMech
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-23 00:21:35 +08:00
iambossandClaude Fable 5.1 2cf5d31bf6 refactor(Hi.Sample): follow the Buckle to Mount rename -- the machine-tool and machining-project build demos and the coordinate-entry displayees use the ...Mount members
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 01:46:26 +08:00
iambossandClaude Opus 5 40214ca6f4 feat(demos): take over the ten framework-independent samples from Hi.Sample.Wpf
Hi.WinForm and Hi.WpfPlus are being retired, and Hi.Sample.Wpf existed only to
demonstrate Hi.WpfPlus -- but ten of its fourteen files never touched WPF at all. Those
move here rather than leaving with it:

- The three displayees upgrading-to-3.2/breaking-changes.md tells callers to copy --
  MachiningProjectDisplayee, IsoCoordinateEntryDisplayee,
  HeidenhainCoordinateEntryDisplayee. They compose only public API over
  LocalProjectService, which is the point of shipping them as a starting sample; that doc
  now points at Hi.Sample/Disp/.
- Seven display demos -- Cylindroid, DiscreteRgb, Drawing, Pick1, Pick2, Pickable,
  Satellite. Their only WPF coupling was the closing DemoUtil.RunApplication call.

DemoUtil is rewritten for a project with no canvas. HiAPI ships none any more, so a
sample cannot end by opening a window; Present() initializes the app, reports the
displayee's type and bounding box, and shuts down, which makes the samples runnable and
checkable headlessly and puts the handover where it actually is -- the application
assigns the composed IDisplayee to its own canvas' DispEngine.

The four files that genuinely need WPF (DemoStl, the old DemoUtil, and the two Machining
demos) stay behind and retire with Hi.Sample.Wpf. Each moved file's own
[!code-csharp] doc-comment path was repointed from ~/../Hi.Sample.Wpf/Disp/ to
~/../Hi.Sample/Disp/. Builds clean at x64: 0 warnings, 0 errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 11:48:33 +08:00
iambossandClaude Opus 5 b27c36acb8 refactor(demos): build the fixture and the workpiece with CreateDefault() and set the workpiece-buckle offset on the fixture's branch
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 23:46:25 +08:00
iambossandClaude Opus 5 65a8cce19e refactor(demos): build the sample machine tools with GeneralXyzabcMachineTool.CreateFromChainCode and set the buckle and axis transformers through the machine
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 20:23:25 +08:00
iambossandClaude Fable 5.1 04bffeccaf refactor(demos): follow the Asmb.DescendantAnchors rename
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:33:49 +08:00
iambossandClaude Opus 5 7beb671352 refactor(demos): build sample machine tools as GeneralXyzabcMachineTool
Follows the CodeXyzabcMachineTool retirement in HiMech. DemoBuildMachineTool
drops IGetCodeXyzabcMachineTool, which no longer exists, and spells out the
doc comments the inherited interface used to supply.

The two GenByFile<CodeXyzabcMachineTool> call sites are fixed rather than
merely renamed: they read Resource machine tools rooted at
<GeneralXyzabcMachineTool>, so the factory's `as` cast handed back null and
the demo project got no machining chain at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 19:57:54 +08:00
iamboss 7ed5372805 deploy obfuscation-safe ToPresentDto dictionary DTOs (HiGeom/HiCbtr/HiMech) + webservice member-name wire keys.
Deployed-Version: Hi.Sample 3.2.0
2026-08-24 00:55:57 +08:00
iambossandClaude Fable 5 73bcf2802b refactor(demos): follow the ContourTray to Fluting rename
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 20:05:07 +08:00
iambossandClaude Opus 5 f83f8b9fb1 refactor(demos): follow the Table-B1 rename and the marked resource names
The shipped machine tool is now MachineTool/Table-B1.default/Table-B1.mt
and the shipped cutting-parameter / workpiece-material files carry the
`.default` marker, so the three hard-coded resource paths move with them.
These samples are compiled into the public docsite verbatim, so a stale
path here ships as documentation.

Also removes the commented-out PmcB1MachineToolSource line and renames
the class summary, both of which put the retired name on the public docs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:29:19 +08:00
iambossandClaude Opus 5 84f9828233 build(Hi.Sample): keep the version line on 3.1
Follows the libraries back off the retracted 3.2 line: VersionPrefix returns to
3.1 and the floating HiAPI references to 3.1.*, which is what the feed serves.
This build counter was never reset, so it just keeps running.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 14:27:48 +08:00
iambossandClaude Opus 5 038e7469d2 build(Hi.Sample): move the version line to 3.2 and retarget HiAPI references
VersionPrefix follows the workspace onto the 3.2 line and the floating HiAPI
package references move from 3.1.* to 3.2.*, which is what the libraries now
publish. The build counter keeps running -- only the packages on the Gitea feed
restart, the same split as the 1.4 -> 3.1 move.

The last 3.1 build of this repo is tagged and kept alive on support/3.1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 18:00:19 +08:00
iambossandClaude Fable 5 1ba32813bb refactor(demos): retarget session-message samples off MixedProgress0 to the three partitioned sinks
DemoUseSessionMessageHost now reads ShellProgress / NcDiagnosticProgress /
StepDiagnosticProgress (severity + id + notification, with the per-kind NC-line
/ step anchors). Drop DemoUseSessionMessageHost2 — its premise (reading
MachiningStep objects out of the mixed message list) dissolves under the
partition; step-data demos live in ShowStepPresent and SessionStepBuilt.
DemoUseMachiningProject's abnormal-message log now subscribes the three sinks'
MessageAdded events (shell via the OnShellMessageAdded app-lifetime bridge).

Part of MixedProgress0 retirement (migration P6). Build x64 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 12:50:33 +08:00
iamboss 7a4d0d7999 refactor(demos): use MachiningStep.EndTimecode instead of obsolete AccumulatedTime
DemoSessionMessage console output and the step-present default key list switch off the [Obsolete] AccumulatedTime alias.
2026-06-27 19:16:45 +08:00
iambossandClaude Opus 4.8 0fdba701fa fix(demos): DemoUseMachiningProject subscribes CollectionItemAdded on MixedProgress
CollectionItemAdded is an event on MixedProgress0; the new SessionProgress sink does not expose it. Follows the SessionProgress->MixedProgress property rename.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 23:25:14 +08:00
iambossandClaude Opus 4.8 6f0cb1bc1c refactor(demos): DemoSessionMessage reads IMessage instead of MultiTagMessage
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:38:20 +08:00
iambossandClaude Opus 4.8 5ed0c3311e refactor(demos): own UserConfig/UserService copy for Hi.Sample
UserService moved out of the HiNc core package; Hi.Sample keeps its own copy under Sample.Common so the DemoSessionMessage #ShowStepPresent region (a live docfx code snippet referenced by two app-anatomy pages) still compiles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 14:24:34 +08:00
iambossandClaude Opus 4.7 05ada6189b refactor(Hi.Sample): convert DemoBuildMachineTool to Reg(XFactory factory=null)
Static ctor rewritten as public static void Reg(XFactory factory = null).

Part of the workspace-wide ~270-class XFactory refactor; see HiGeom commit
for the XFactory instance refactor and full pattern rationale.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 10:34:11 +08:00
iamboss 7e2a4b116a rename XFactory.Regs to XFactory.Generators. 2026-05-23 21:23:11 +08:00
iamboss af599f36e6 fix SoftNcRunner GM code normalization. 2026-05-16 18:08:34 +08:00
iamboss 6139c84ff9 refactor(Sample): adapt demos for SessionStepBuilt rename and ILogger injection
Made-with: Cursor
2026-04-14 17:18:05 +08:00
iamboss dd4c3ef28f refactor(Sample): adapt demos to XFactory IProgress<object> signature
Made-with: Cursor
2026-04-11 11:19:36 +08:00
iamboss e5ea1961a5 refactor(demos): update machining demos and remove legacy demo message handling
Made-with: Cursor
2026-04-08 16:33:17 +08:00
26 changed files with 1744 additions and 327 deletions
-57
View File
@@ -1,57 +0,0 @@
using System;
using System.Threading.Tasks;
using Hi.Common;
using Hi.Common.Messages;
namespace Sample.Common;
/// <summary>
/// Demonstrates common message and exception handling patterns in HiAPI applications
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Common/DemoMessageAndExceptionHandling.cs)]
/// </remarks>
public static class DemoMessageAndExceptionHandling
{
/// <summary>
/// Demonstrates normal message handling
/// </summary>
internal static void DemoNormalMessages()
{
#region Normal_Messages
MessageUtil.ReportMessage("Operation completed successfully.");
MessageUtil.ReportWarning("Please check your input.");
#endregion
}
/// <summary>
/// Demonstrates exception handling in synchronous code
/// </summary>
internal static void DemoSynchronousExceptionHandling()
{
#region Sync_Exception
try
{
// Your code here
throw new NotImplementedException("Demo exception");
}
catch (Exception ex)
{
ExceptionUtil.ShowException(ex, null);
}
#endregion
}
/// <summary>
/// Demonstrates exception handling in asynchronous code
/// </summary>
internal static async Task DemoAsynchronousExceptionHandling()
{
#region Async_Exception
await Task.Run(() =>
{
// Your async operation here
throw new NotImplementedException("Demo async exception");
}).ShowIfCatched(null);
#endregion
}
}
+28 -106
View File
@@ -2,16 +2,12 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Hi.Common;
using Hi.Common.FileLines;
using Hi.Geom;
using Hi.Common.Messages;
using Hi.HiNcKits;
using Hi.MachiningProcs;
using Hi.MachiningSteps;
using Hi.Mech;
using Hi.Mech.Topo;
using Hi.Numerical;
using Hi.NcParsers;
namespace Sample.Common;
@@ -24,114 +20,40 @@ public static class DemoSessionMessage
#region Demo_UseSessionMessageHost
internal static void DemoUseSessionMessageHost(LocalProjectService localProjectService)
{
SessionProgress sessionMessageHost = localProjectService.SessionProgress;
// Session messages are partitioned by kind into three sinks on LocalProjectService:
// - ShellProgress: session-level routine / lifecycle messages
// (session-scoped: null outside BeginSession/EndSession).
// - NcDiagnosticProgress: NC-pipeline diagnostics, anchored to the NC source sentence.
// - StepDiagnosticProgress: diagnostics anchored to a motion step.
SessionProgress.FilterFlag filterFlags =
SessionProgress.FilterFlag.NC |
SessionProgress.FilterFlag.Progress |
SessionProgress.FilterFlag.Error;
string filterText = null;
var filteredSessionMessageList = sessionMessageHost
.GetFliteredList(filterFlags, filterText);
ShellProgress shellProgress = localProjectService.ShellProgress;
List<IMessage> shellMessages = shellProgress == null
? new List<IMessage>() : shellProgress.Messages.ToList();
foreach (IMessage message in shellMessages)
Console.WriteLine(
$"Shell [{message.GetSeverity()}] {message.GetId()}: {message.GetNotification()}");
foreach (var sessionMessage in filteredSessionMessageList)
foreach (NcDiagnostic diagnostic in
localProjectService.NcDiagnosticProgress.Diagnostics.ToList())
{
//M.I.: Message Index.
Console.Write($"M.I.: {sessionMessage.Index}; Role: {sessionMessage.MessageRoleText}");
// For SessionMessageHost.FilterFlag.NC
var nc = sessionMessage.DirectInstantSourceCommand;
if (nc != null)
Console.Write($"Message/NC: {nc.Line}; File: {nc.FilePath}; LineNo: {nc.GetLineNo()}; ");
// For SessionMessageHost.FilterFlag.Progress or Error.
var multiTagMessage = sessionMessage.MultiTagMessage;
if (multiTagMessage != null)
Console.WriteLine($"Message/NC: {multiTagMessage.Message}");
var exception = sessionMessage.Exception;
if (exception != null)
Console.WriteLine($"Message/NC: {exception.Message}");
var ncLine = diagnostic.SentenceCarrier?.GetSentence()?.FirstIndexedFileLine;
Console.WriteLine(
$"NC [{diagnostic.GetSeverity()}] {diagnostic.GetId()}: {diagnostic.GetNotification()}; " +
$"File: {ncLine?.FilePath}; LineNo: {ncLine?.GetLineNo()}; NC: {ncLine?.Line}");
}
foreach (StepDiagnostic diagnostic in
localProjectService.StepDiagnosticProgress.Messages.ToList())
Console.WriteLine(
$"Step {diagnostic.StepIndex} [{diagnostic.GetSeverity()}] " +
$"{diagnostic.GetId()}: {diagnostic.GetNotification()}");
File.WriteAllLines("output-session-messages.txt",
filteredSessionMessageList.Select(m =>
$"Msg[{m.Index}][{m.MessageRoleText}]: {m}"));
shellMessages.Select(m =>
$"[{m.GetSeverity()}] {m.GetId()}: {m.GetNotification()}"));
}
#endregion
internal static void DemoUseSessionMessageHost2(LocalProjectService localProjectService)
{
SessionProgress sessionMessageHost = localProjectService.SessionProgress;
IMachiningChain machiningChain = localProjectService.MachiningChain;
PresentAttribute mrrPresent = typeof(MachiningStep).GetProperty(nameof(MachiningStep.Mrr_mm3ds)).GetCustomAttribute<PresentAttribute>();
string mrrUnit = mrrPresent?.TailUnitString;
string mrrFormat = mrrPresent?.DataFormatString;
PresentAttribute torquePresent = typeof(MachiningStep).GetProperty(nameof(MachiningStep.AvgAbsTorque_Nm)).GetCustomAttribute<PresentAttribute>();
string torqueUnit = torquePresent?.TailUnitString;
string torqueFormat = torquePresent?.DataFormatString;
SessionProgress.FilterFlag filterFlags =
SessionProgress.FilterFlag.Step |
SessionProgress.FilterFlag.NC |
SessionProgress.FilterFlag.Progress |
SessionProgress.FilterFlag.Error;
string filterText = null;
var filteredSessionMessageList = sessionMessageHost
.GetFliteredList(filterFlags, filterText);
foreach (var sessionMessage in filteredSessionMessageList)
{
//M.I.: Message Index.
Console.Write($"M.I.: {sessionMessage.Index}; Role: {sessionMessage.MessageRoleText}");
// For SessionMessageHost.FilterFlag.Step
var step = sessionMessage.MachiningStep;
if (step != null)
{
string[] machineCoordinateValueTexts = GetMachineCoordinateValueTexts(step, machiningChain);
var machineCoordinatesText = string.Join("; ", Enumerable.Range(0, machiningChain.McCodes.Length)
.Select(i => $"MC.{machiningChain.McCodes[i]}: {machineCoordinateValueTexts[i]}"));
Console.Write($"Time: {step.AccumulatedTime:G}; MRR = {step.Mrr_mm3ds.ToString(mrrFormat)} {mrrUnit}; Torque = {step.AvgAbsTorque_Nm?.ToString(torqueFormat)} {torqueUnit}; {machineCoordinatesText}; ");
var nc_ = sessionMessageHost.GetSourceCommand(sessionMessage);
Console.WriteLine($"Message/NC: {nc_.Line}; File: {nc_.FilePath}; LineNo: {nc_.GetLineNo()}");
}
// For SessionMessageHost.FilterFlag.NC
var nc = sessionMessage.DirectInstantSourceCommand;
if (nc != null)
{
Console.Write($"Message/NC: {nc.Line}; File: {nc.FilePath}; LineNo: {nc.GetLineNo()}; ");
if (nc is HardNcLine ncLine)
Console.WriteLine($"T: {ncLine.T}; S: {ncLine.S}; F: {ncLine.F}; NC-Flags: {ncLine.FlagsText}");
}
// For SessionMessageHost.FilterFlag.Progress or Error.
var multiTagMessage = sessionMessage.MultiTagMessage;
if (multiTagMessage != null)
Console.WriteLine($"Message/NC: {multiTagMessage.Message}");
var exception = sessionMessage.Exception;
if (exception != null)
Console.WriteLine($"Message/NC: {exception.Message}");
}
}
static string[] GetMachineCoordinateValueTexts(MachiningStep step, IMachiningChain machiningChain)
{
var mcTransformers = machiningChain.McTransformers;
string[] dst = new string[mcTransformers.Length];
if (mcTransformers != null)
{
for (int i = 0; i < mcTransformers.Length; i++)
{
if (mcTransformers[i] == null)
continue;
if (mcTransformers[i] is DynamicRotation)
dst[i] = MathUtil.ToDeg(step.GetMcValue(i).Value).ToString("F4");
else
dst[i] = step.GetMcValue(i)?.ToString("F5");
}
}
return dst;
}
#region ShowStepPresent
internal static void ShowStepPresent(
UserService userEnv, MachiningStep machiningStep)
+141
View File
@@ -0,0 +1,141 @@
using Hi.Common;
using Hi.Common.XmlUtils;
using System.Xml;
using System.Xml.Linq;
namespace Sample.Common;
/// <summary>
/// Per-user visibility flags for the Player page's divisions (charts and
/// info panels), flattened into a single all-boolean config persisted through
/// <see cref="UserConfig"/>.
/// </summary>
/// <remarks>
/// Defaults are tuned for a first-time user: the two info panels
/// (<see cref="EnableStepDiv"/> and <see cref="MessageTable"/>) are ON
/// so the Player page looks populated without having to open the
/// Division Visibility dropdown; every chart toggle starts OFF.
/// </remarks>
public class PlayerDivConfig : IMakeXmlSource
{
#region XML IO
/// <summary>
/// Registers this type's deserializer with the given <see cref="XFactory"/>
/// (or <see cref="XFactory.Default"/> when <paramref name="factory"/> is
/// <c>null</c>). Idempotent.
/// </summary>
public static void Reg(XFactory factory = null)
{
factory ??= XFactory.Default;
factory.Generators.TryAdd(XName, (xml, baseDirectory, relFile, progress, res)
=> new PlayerDivConfig(xml));
}
/// <summary>
/// Name for XML IO.
/// </summary>
public static string XName => nameof(PlayerDivConfig);
/// <summary>
/// Default constructor.
/// </summary>
public PlayerDivConfig() { }
/// <summary>
/// Initializes a new instance of the <see cref="PlayerDivConfig"/> class from XML data.
/// </summary>
/// <param name="src">XML element containing player-div data.</param>
public PlayerDivConfig(XElement src)
{
if (src == null) return;
src.Element(nameof(EnableStripAvailabilityChart))?.Value?.SelfInvoke(
v => EnableStripAvailabilityChart = XmlConvert.ToBoolean(v));
src.Element(nameof(EnableStripRoughnessChart))?.Value?.SelfInvoke(
v => EnableStripRoughnessChart = XmlConvert.ToBoolean(v));
src.Element(nameof(ColorIndexTimeChart))?.Value?.SelfInvoke(
v => ColorIndexTimeChart = XmlConvert.ToBoolean(v));
src.Element(nameof(ForceCycleLineDiv))?.Value?.SelfInvoke(
v => ForceCycleLineDiv = XmlConvert.ToBoolean(v));
src.Element(nameof(SimSpindleMomentCycleLineDiv))?.Value?.SelfInvoke(
v => SimSpindleMomentCycleLineDiv = XmlConvert.ToBoolean(v));
src.Element(nameof(SensorSpindleMomentCycleLineDiv))?.Value?.SelfInvoke(
v => SensorSpindleMomentCycleLineDiv = XmlConvert.ToBoolean(v));
src.Element(nameof(DynamometerForceCycleLineDiv))?.Value?.SelfInvoke(
v => DynamometerForceCycleLineDiv = XmlConvert.ToBoolean(v));
src.Element(nameof(EnableStepDiv))?.Value?.SelfInvoke(
v => EnableStepDiv = XmlConvert.ToBoolean(v));
src.Element(nameof(MessageTable))?.Value?.SelfInvoke(
v => MessageTable = XmlConvert.ToBoolean(v));
src.Element(nameof(EnableDetailDiv0))?.Value?.SelfInvoke(
v => EnableDetailDiv0 = XmlConvert.ToBoolean(v));
}
/// <inheritdoc/>
public XElement MakeXmlSource(string baseDirectory, string relFile, bool exhibitionOnly)
{
return new XElement(XName,
new XElement(nameof(EnableStripAvailabilityChart), EnableStripAvailabilityChart),
new XElement(nameof(EnableStripRoughnessChart), EnableStripRoughnessChart),
new XElement(nameof(ColorIndexTimeChart), ColorIndexTimeChart),
new XElement(nameof(ForceCycleLineDiv), ForceCycleLineDiv),
new XElement(nameof(SimSpindleMomentCycleLineDiv), SimSpindleMomentCycleLineDiv),
new XElement(nameof(SensorSpindleMomentCycleLineDiv), SensorSpindleMomentCycleLineDiv),
new XElement(nameof(DynamometerForceCycleLineDiv), DynamometerForceCycleLineDiv),
new XElement(nameof(EnableStepDiv), EnableStepDiv),
new XElement(nameof(MessageTable), MessageTable),
new XElement(nameof(EnableDetailDiv0), EnableDetailDiv0)
);
}
#endregion
/// <summary>
/// Availability strip chart (per-step timeline coloured by availability aspect).
/// </summary>
public bool EnableStripAvailabilityChart { get; set; } = false;
/// <summary>
/// Surface-roughness strip chart (per-step timeline coloured by surface-roughness aspect).
/// </summary>
public bool EnableStripRoughnessChart { get; set; } = false;
/// <summary>
/// Color-index strip chart (single-strip timeline coloured by arbitrary numeric/bool aspect).
/// </summary>
public bool ColorIndexTimeChart { get; set; } = false;
/// <summary>
/// Cycle-line chart of cutting force along the step's rotation cycle.
/// </summary>
public bool ForceCycleLineDiv { get; set; } = false;
/// <summary>
/// Cycle-line chart of simulation-derived spindle moment on spindle-rotation coordinate.
/// </summary>
public bool SimSpindleMomentCycleLineDiv { get; set; } = false;
/// <summary>
/// Cycle-line chart of sensor-measured spindle moment (overlay on sim moment).
/// </summary>
public bool SensorSpindleMomentCycleLineDiv { get; set; } = false;
/// <summary>
/// Cycle-line chart of sensor-measured force from an external dynamometer.
/// </summary>
public bool DynamometerForceCycleLineDiv { get; set; } = false;
/// <summary>
/// Full / condensed step information panel (Selected Step Info).
/// </summary>
public bool EnableStepDiv { get; set; } = true;
/// <summary>
/// Session messages panel.
/// </summary>
public bool MessageTable { get; set; } = true;
/// <summary>
/// Developer-only raw step-property dump panel.
/// </summary>
public bool EnableDetailDiv0 { get; set; } = false;
}
+173
View File
@@ -0,0 +1,173 @@
using Hi.Cbtr;
using Hi.Common;
using Hi.Common.XmlUtils;
using Hi.MachiningSteps;
using Hi.NcMech.Fixtures;
using Hi.NcMech.Workpieces;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
namespace Sample.Common;
/// <summary>
/// User Configuration.
/// </summary>
/// <remarks>
/// Sample-owned copy of the per-GUI user configuration, kept so the
/// <see cref="DemoSessionMessage"/> step-present demo still compiles. Each
/// GUI/APP keeps its own version; the core engine package (HiNc) no longer
/// carries any GUI configuration type.
/// </remarks>
public class UserConfig : IMakeXmlSource
{
/// <summary>
/// Registers this type's deserializer with the given <see cref="XFactory"/>
/// (or <see cref="XFactory.Default"/> when <paramref name="factory"/> is
/// <c>null</c>). Idempotent.
/// </summary>
public static void Reg(XFactory factory = null)
{
factory ??= XFactory.Default;
factory.Generators.TryAdd(XName, (xml, baseDirectory, relFile, progress, res)
=> new UserConfig(xml, baseDirectory));
}
#region XML IO
/// <summary>
/// Name for XML IO.
/// </summary>
public static string XName => nameof(UserConfig);
/// <summary>
/// Initializes a new instance of the <see cref="UserConfig"/> class from XML data.
/// </summary>
/// <param name="src">XML element containing configuration data</param>
/// <param name="baseDirectory">Base directory for resolving relative paths</param>
public UserConfig(XElement src, string baseDirectory)
{
if (src == null) return;
src.Element(nameof(ShowPhysicsOptions))?.Value?.SelfInvoke(
v => ShowPhysicsOptions = XmlConvert.ToBoolean(v));
src.Element(nameof(LanguageCode))?.Value?.SelfInvoke(v => LanguageCode = v);
src.Element(nameof(EnableFullControl))?.Value?.SelfInvoke(
v => EnableFullControl = XmlConvert.ToBoolean(v));
src.Element(nameof(GraphicCacheLowerLimitMb))?.Value?.SelfInvoke(
v => GraphicCacheLowerLimitMb = XmlConvert.ToDouble(v));
src.Element(nameof(GraphicCacheUpperLimitMb))?.Value?.SelfInvoke(
v => GraphicCacheUpperLimitMb = XmlConvert.ToDouble(v));
src.Element(nameof(GraphicCacheMb))?.Value?.SelfInvoke(
v => GraphicCacheMb = XmlConvert.ToInt64(v));
src.Element(nameof(DisplayedStepPresentKeyList))?.SelfInvoke(ee =>
{
DisplayedStepPresentKeyList = ee.Elements("Item").Select(e => e.Value).ToList();
});
// Load FixtureSetupDisplayeeConfig
src.Element(nameof(FixtureSetupDisplayeeConfig))?.SelfInvoke(e =>
{
FixtureSetupDisplayeeConfig = new FixtureEditorDisplayeeConfig(e);
});
// Load EquipmentWorkpieceSetupDisplayeeConfig
src.Element(nameof(EquipmentWorkpieceSetupDisplayeeConfig))?.SelfInvoke(e =>
{
EquipmentWorkpieceSetupDisplayeeConfig = new WorkpieceEditorDisplayeeConfig(e);
});
// Load PlayerDivConfig
src.Element(nameof(PlayerDivConfig))?.SelfInvoke(e =>
{
PlayerDivConfig = new PlayerDivConfig(e);
});
}
/// <inheritdoc/>
public XElement MakeXmlSource(string baseDirectory, string relFile, bool exhibitionOnly)
{
XElement dst = new XElement(XName,
new XElement(nameof(ShowPhysicsOptions), ShowPhysicsOptions),
new XElement(nameof(LanguageCode), LanguageCode),
new XElement(nameof(EnableFullControl), EnableFullControl),
new XElement(nameof(GraphicCacheLowerLimitMb), GraphicCacheLowerLimitMb),
new XElement(nameof(GraphicCacheUpperLimitMb), GraphicCacheUpperLimitMb),
new XElement(nameof(GraphicCacheMb), GraphicCacheMb),
new XElement(nameof(DisplayedStepPresentKeyList),
DisplayedStepPresentKeyList.Select(v => new XElement("Item", v))),
new XElement(nameof(FixtureSetupDisplayeeConfig),
FixtureSetupDisplayeeConfig?.MakeXmlSource(baseDirectory, relFile, exhibitionOnly)),
new XElement(nameof(EquipmentWorkpieceSetupDisplayeeConfig),
EquipmentWorkpieceSetupDisplayeeConfig?.MakeXmlSource(baseDirectory, relFile, exhibitionOnly)),
PlayerDivConfig?.MakeXmlSource(baseDirectory, relFile, exhibitionOnly)
);
return dst;
}
#endregion
/// <summary>
/// Gets or sets whether to show physics options in the UI.
/// </summary>
public bool ShowPhysicsOptions { get; set; } = false;
/// <summary>
/// Gets or sets the language code for the application UI.
/// </summary>
public string LanguageCode { get; set; } = "en";
/// <summary>
/// Enable Full control of the application.
/// Eanble System.Diagnostics.Process in GUI Script Command.
/// Not used yet.
/// </summary>
public bool EnableFullControl { get; set; }
/// <summary>
/// Gets or sets the lower limit of graphic cache in megabytes.
/// </summary>
public double GraphicCacheLowerLimitMb { get; set; } = 10;
/// <summary>
/// Gets or sets the upper limit of graphic cache in megabytes.
/// </summary>
public double GraphicCacheUpperLimitMb { get; set; } = 1200;
/// <summary>
/// Gets or sets the graphic cache size in megabytes.
/// </summary>
public long GraphicCacheMb
{
get => CubeTree.DispCacheMb;
set => CubeTree.DispCacheMb = value;
}
/// <summary>
/// Step infomation key list to show.
/// </summary>
public List<string> DisplayedStepPresentKeyList { get; set; } = new List<string>([
nameof(MachiningStep.StepIndex),
nameof(MachiningStep.FileNo), nameof(MachiningStep.LineNo),
nameof(MachiningStep.FilePath),nameof(MachiningStep.EndTimecode),
nameof(MachiningStep.LineText),nameof(MachiningStep.FlagsText),
nameof(MachiningStep.ToolId),
nameof(MachiningStep.SpindleSpeed_rpm),nameof(MachiningStep.Feedrate_mmdmin),
nameof(MachiningStep.Mrr_mm3ds),
nameof(MachiningStep.AvgAbsTorque_Nm),
]);
/// <summary>
/// Configuration for FixtureSetupDisplayee
/// </summary>
public FixtureEditorDisplayeeConfig FixtureSetupDisplayeeConfig { get; set; } = new FixtureEditorDisplayeeConfig();
/// <summary>
/// Configuration for EquipmentWorkpieceSetupDisplayee
/// </summary>
public WorkpieceEditorDisplayeeConfig EquipmentWorkpieceSetupDisplayeeConfig { get; set; } = new WorkpieceEditorDisplayeeConfig();
/// <summary>
/// Per-user visibility flags for the Player page's divisions (charts and info panels).
/// Persisted alongside the rest of this <see cref="UserConfig"/>.
/// </summary>
public PlayerDivConfig PlayerDivConfig { get; set; } = new PlayerDivConfig();
/// <summary>
/// Default constructor
/// </summary>
public UserConfig() { }
}
+160
View File
@@ -0,0 +1,160 @@
using Hi.Common;
using Hi.Common.XmlUtils;
using Hi.Licenses;
using Hi.MachiningSteps;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Sample.Common;
/// <summary>
/// User Service.
/// </summary>
/// <remarks>
/// Sample-owned copy, kept so the <see cref="DemoSessionMessage"/> step-present
/// demo still compiles. Each GUI/APP keeps its own version; the core engine
/// package (HiNc) no longer carries this GUI service type.
/// </remarks>
public class UserService : IDisposable
{
/// <summary>
/// Gets or sets the application configuration.
/// </summary>
public UserConfig UserConfig { get; set; } = new UserConfig();
/// <summary>
/// Gets or sets the path to the application configuration file.
/// </summary>
public string UserConfigPath { get; set; }
/// <summary>
/// Gets whether physics features are enabled based on configuration and license.
/// </summary>
public bool EnablePhysics =>
UserConfig.ShowPhysicsOptions && IsPhysicsLicensed;
/// <summary>
/// Gets whether advanced physics features are licensed.
/// </summary>
public bool IsPhysicsLicensed => License.IsLoggedIn(AuthFeature.AdvancedPhysics);
//runtime properties are not in the category of canonical IO.
#region Runtime Property
private readonly ILogger _logger;
LooseRunner SaveConfigLooseRunner;
/// <summary>
/// Gets or sets the currently selected item in the application.
/// </summary>
public object SelectedItem { get; set; }
private bool disposedValue;
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="UserService"/> class.
/// </summary>
/// <param name="logger">The logger instance.</param>
public UserService(ILogger logger) { _logger = logger; SaveConfigLooseRunner = new LooseRunner(logger); }
/// <summary>
/// Initializes a new instance of the <see cref="UserService"/> class with the specified configuration.
/// </summary>
/// <param name="appConfig">The application configuration.</param>
/// <param name="logger">The logger instance.</param>
public UserService(UserConfig appConfig, ILogger logger) : this(logger) { UserConfig = appConfig; }
/// <summary>
/// Saves the user configuration to the file specified by <see cref="UserConfigPath"/>.
/// </summary>
public void SaveUserConfig()
{
try
{
if (UserConfigPath != null)
UserConfig.MakeXmlSourceToFile(UserConfigPath);
}
catch (Exception ex)
{
_logger?.LogError(ex, "{Message}", ex.Message);
}
}
/// <summary>
/// Schedules a loose save of the user configuration using a LooseRunner.
/// </summary>
public void LooseSaveUserConfig()
{
SaveConfigLooseRunner.TryRun(token => SaveUserConfig());
}
#region step present
/// <summary>
/// Gets or sets additional step presentation access configurations.
/// </summary>
public Dictionary<string, PresentAccess> AdditionalStepPresentAccess { get; set; } = new Dictionary<string, PresentAccess>();
/// <summary>
/// StepPresentAccessDictionary.
/// Read only.
/// </summary>
public Dictionary<string, PresentAccess> StepPresentAccessDictionary
{
get
{
var originalPresentAccessDictionary = typeof(MachiningStep).GetProperties()
.Where(p => p.GetCustomAttribute<PresentAttribute>() != null)
.ToDictionary(prop => prop.Name, prop =>
new PresentAccess(prop.GetCustomAttribute<PresentAttribute>(),
step => prop.GetValue(step)));
var presentAccessDictionary = new Dictionary<string, PresentAccess>(
AdditionalStepPresentAccess.Concat(originalPresentAccessDictionary));
return presentAccessDictionary;
}
}
/// <summary>
/// Candidate Step Present Key List for display.
/// Read only.
/// </summary>
public List<string> CandidateStepPresentKeyList => StepPresentAccessDictionary.Keys.ToList();
/// <summary>
/// StepPresentAccessList for display.
/// Read only.
/// </summary>
public List<KeyValuePair<string, PresentAccess>> DisplayedStepPresentAccessList
{
get
{
var displayedStepPresentKeyList = UserConfig.DisplayedStepPresentKeyList;
List<KeyValuePair<string, PresentAccess>> dst
= new List<KeyValuePair<string, PresentAccess>>(
displayedStepPresentKeyList.Count);
var stepPresentAccessDictionary = StepPresentAccessDictionary;
foreach (var key in displayedStepPresentKeyList)
{
if (stepPresentAccessDictionary.TryGetValue(
key, out var access))
{
dst.Add(new KeyValuePair<string, PresentAccess>(key, access));
}
}
return dst;
}
}
#endregion
/// <inheritdoc/>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
SaveConfigLooseRunner.Dispose();
}
disposedValue = true;
}
}
/// <inheritdoc/>
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
+53
View File
@@ -0,0 +1,53 @@
using Hi.Disp;
using Hi.Geom;
using System;
namespace Sample.Disp
{
/// <summary>
/// Demonstrates the creation and visualization of <see cref="Cylindroid"/> objects.
/// Includes examples of building a <see cref="Cylindroid"/> programmatically with
/// <see cref="PairZr"/> points and serializing/deserializing via XML.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoCylindroid.cs)]
/// </remarks>
public static class DemoCylindroid
{
internal static void BuildCylindorid()
{
Cylindroid cylindroid = new Cylindroid(
new PairZr(0, 1),
new PairZr(1, 1),
new PairZr(1, 2),
new PairZr(2, 2),
new PairZr(8, 3));
DispEngine.Init();
DemoUtil.Present("BuildCylindorid", cylindroid.ToFaceDrawing());
}
internal static void TestCylindoridXml()
{
Cylindroid cylindroid = new Cylindroid(
new PairZr(0, 1),
new PairZr(1, 1),
new PairZr(1, 2),
new PairZr(2, 2),
new PairZr(4, 3));
var xmlElement = cylindroid.MakeXmlSource(null, null, true);
Console.WriteLine("XML:" + xmlElement);
cylindroid = new Cylindroid(xmlElement);
DispEngine.Init();
DemoUtil.Present("BuildCylindorid", cylindroid.ToFaceDrawing());
}
static void Main()
{
BuildCylindorid();
//TestCylindoridXml();
}
}
}
+45
View File
@@ -0,0 +1,45 @@
using Hi.Disp;
using Hi.Disp.Flag;
using Hi.Geom;
using Hi.Coloring;
namespace Sample.Disp
{
/// <summary>
/// Demonstrates the use of discrete RGB colors for rendering multiple objects.
/// Shows how to apply different colors to similar geometric shapes using the
/// <see cref="ColorUtil.GetDiscreteRGB_Env"/> method from <see cref="ColorUtil"/> class.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoDiscreteRgb.cs)]
/// </remarks>
public class DemoDiscreteRgb : IDisplayee
{
/// <inheritdoc/>
public void Display(Bind bind)
{
bind.Rgb = ColorUtil.GetDiscreteRGB_Env();
new box3d_t(0, 0, 0, 1, 1, 1).ToDraw_Face().Display(bind);
bind.Rgb = ColorUtil.GetDiscreteRGB_Env();
new box3d_t(1, 0, 0, 2, 1, 1).ToDraw_Face().Display(bind);
bind.Rgb = ColorUtil.GetDiscreteRGB_Env();
new box3d_t(2, 0, 0, 3, 1, 1).ToDraw_Face().Display(bind);
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
dst = dst.Expanded(new vec3d_t(0, 0, 0));
dst = dst.Expanded(new vec3d_t(3, 1, 1));
}
static void Main()
{
DemoUtil.Present("Demo Discrete I",
new DispList(new CoordinateDrawing(), new DemoDiscreteRgb()));
}
}
}
+201
View File
@@ -0,0 +1,201 @@
using Hi.Geom;
using Hi.Disp;
using System.Collections.Generic;
using Hi.Disp.Treat;
using Hi.Coloring;
namespace Sample.Disp
{
/// <summary>
/// Demonstrates various drawing techniques using the HiAPI graphics system.
/// Provides examples of primitive drawing, attribute specification, and rendering options.
/// Includes methods for drawing lines, points, triangles, and other geometric primitives.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoDrawing.cs)]
/// </remarks>
public static class DemoDrawing
{
/// <summary>
/// Demonstrates simple line drawing using raw vertex coordinates.
/// Creates a basic line strip from three vertices and displays it using DemoUtil.
/// </summary>
public static void FreeDrawing()
{
#region DocSite.FreeDrawing
double[] vs =
{0,0,0
,1,0,0
,0,0,1};
DemoUtil.Present("EasyDraw"
, new Drawing(vs, Stamp.V, GL.GL_LINE_STRIP));
#endregion
}
/// <summary>
/// Demonstrates various types of line drawing techniques.
/// Shows how to create points, line strips, line strips with normals, and colored line strips.
/// Illustrates different ways to specify vertex attributes like position, color, and normal.
/// </summary>
public static void DrawLines()
{
List<vec3d_t> ps;
double[] vs;
int n = 10; //vertex num
////create drawPoints
ps = new List<vec3d_t>(n);
for (int i = 0; i < n; i++)
ps.Add(new vec3d_t(i, 0, 0));
vs = new double[ps.Count * 3];
for (int i = 0; i < ps.Count; i++)
{
vs[3 * i] = ps[i].x;
vs[3 * i + 1] = ps[i].y;
vs[3 * i + 2] = ps[i].z;
}
//V means Vertex
Drawing drawPoints = new Drawing(vs, Stamp.V, GL.GL_POINTS);
////create drawLineStrip
vs = new double[ps.Count * 3];
for (int i = 0; i < ps.Count; i++)
{
vs[3 * i] = i;
vs[3 * i + 1] = 0;
vs[3 * i + 2] = 1;
}
Drawing drawLineStrip = new Drawing(vs, Stamp.V, GL.GL_LINE_STRIP);
////create drawLineStripWithNormal
//the content of vs is Nx,Ny,Nz,Vx,Vy,Vz, Nx,Ny,Nz,Vx,Vy,Vz, ...
vs = new double[n * 6];
for (int i = 0; i < n; i++)
{
//nx,ny,nz
vs[6 * i] = 1;
vs[6 * i + 1] = 0;
vs[6 * i + 2] = 0;
//x,y,z
vs[6 * i + 3] = i;
vs[6 * i + 4] = 0;
vs[6 * i + 5] = 2;
}
//V means Vertex; N means Normal
Drawing drawLineStripWithNormal =
new Drawing(vs, Stamp.NV, GL.GL_LINE_STRIP);
////create drawColorLines
vs = new double[n * 6];
for (int i = 0; i < n; i++)
{
//the rgb values set casually.
//r,g,b
vs[6 * i] = i % 3 / 2D;
vs[6 * i + 1] = i % 5 / 4D;
vs[6 * i + 2] = i % 7 / 6D;
//x,y,z
vs[6 * i + 3] = i;
vs[6 * i + 4] = 0;
vs[6 * i + 5] = 3;
}
//V means Vertex; C means Color
Drawing drawLineStripWithColor = new Drawing(vs, Stamp.CV, GL.GL_LINE_STRIP);
DemoUtil.Present("DrawLines",
new DispList(drawPoints, drawLineStrip
, drawLineStripWithNormal, drawLineStripWithColor));
}
/// <summary>
/// Demonstrates drawing triangles using OpenGL primitives.
/// Shows how to create colored triangles (CV) and colored triangles with normals (CNV).
/// Illustrates packing of vertex attributes (color, normal, position) into arrays for rendering.
/// </summary>
public static void DrawTrianglesByPrimitives()
{
int n = 10;// triangle num
double[] vs;
////create drawTrisCV
//each triangle has 3 point; each point has r,g,b,x,y,z, totally 6 doubles.
vs = new double[n * 3 * 6];
for (int i = 0, k = 0; i < n; i++)
{
//the rgb values set as casual.
vec3d_t rgb = ColorUtil.GetDiscreteRgb(i);
tri3d_t tri = new tri3d_t(new vec3d_t(i, 0, 0), new vec3d_t(i + 1, 0, 0), new vec3d_t(i + 0.5, 0, 1));
for (int j = 0; j < 3; j++)
{
vs[k++] = rgb.x;
vs[k++] = rgb.y;
vs[k++] = rgb.z;
vs[k++] = tri[j].x;
vs[k++] = tri[j].y;
vs[k++] = tri[j].z;
}
}
//V means Vertex; C means Color
Drawing drawTrisCV = new Drawing(vs, Stamp.CV, GL.GL_TRIANGLES);
////create drawTrisCNV
/////each triangle has 3 point; each point has r,g,b,nx,ny,nz,x,y,z, totally 6 doubles.
vs = new double[n * 3 * 9];
for (int i = 0, k = 0; i < n; i++)
{
//the rgb values set as casual.
vec3d_t rgb = ColorUtil.GetDiscreteRgb(i);
tri3d_t tri = new tri3d_t(new vec3d_t(i, 0, 3), new vec3d_t(i + 1, 0, 3), new vec3d_t(i + 0.5, 0, 4));
vec3d_t nn = tri.GetNormal();
for (int j = 0; j < 3; j++)
{
vs[k++] = rgb.x;
vs[k++] = rgb.y;
vs[k++] = rgb.z;
vs[k++] = nn.x;
vs[k++] = nn.y;
vs[k++] = nn.z;
vs[k++] = tri[j].x;
vs[k++] = tri[j].y;
vs[k++] = tri[j].z;
}
}
//V means Vertex; C means Color; N means Normal
Drawing drawTrisCNV = new Drawing(vs, Stamp.CNV, GL.GL_TRIANGLES);
//the color of colorTrisDraw is not influence by outer color setting.
DemoUtil.Present("DrawTrianglesByPrimitives",
new DispList(new RgbTreat(1, 0, 0), drawTrisCV, drawTrisCNV));
}
/// <summary>
/// Demonstrates drawing 3D triangles using the tri3d_t helper class.
/// Creates a series of triangles and renders them as both face (filled) and line (wireframe) drawings.
/// Shows how to apply different colors to faces and lines of the same geometry.
/// </summary>
public static void DrawTri3d()
{
int n = 10;
List<tri3d_t> tris = new List<tri3d_t>(n);
for (int i = 0; i < n; i++)
tris.Add(new tri3d_t(new vec3d_t(i, 0, 0), new vec3d_t(i + 1, 0, 0), new vec3d_t(i + 0.5, 0, 1)));
Drawing faceDraw = tris.GetFaceDrawing();
Drawing linesDraw = tris.ToLineDrawing();
DemoUtil.Present("DrawTri3d",
new DispList(new RgbTreat(0, 0, 1), linesDraw
, new RgbTreat(1, 0, 0), faceDraw));
}
static void Main()
{
//FreeDrawing();
//DrawLines();
//DrawTrianglesByPrimitives();
DrawTri3d();
}
}
}
+52
View File
@@ -0,0 +1,52 @@
using Hi.Geom;
using Hi.Disp;
using Hi.Native;
namespace Sample.Disp
{
/// <summary>
/// Demonstrates basic object picking with mouse interaction in the HiAPI system.
/// Shows how to create a pickable 3D object that responds to mouse events by changing its appearance.
/// Implements the Pickable base class to enable mouse event handling.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoPick1.cs)]
/// </remarks>
public class DemoPick1 : Pickable, IDisplayee
{
bool isMouseOver = false;
/// <inheritdoc/>
public void Display(Bind bind)
{
bind.PickID = PickingID;
bind.Rgb = new vec3d_t(isMouseOver ? 0 : 1, 1, 1);
new box3d_t(0, 0, 0, 1, 1, 1).DisplayFace(bind);
bind.PickID = 0;
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
dst = dst.Expanded(new vec3d_t(0, 0, 0));
dst = dst.Expanded(new vec3d_t(1, 1, 1));
}
/// <inheritdoc/>
public override void OnMouseEnter(ui_event_type e, DispEngine dispEngine)
{
isMouseOver = true;
}
/// <inheritdoc/>
public override void OnMouseLeave(ui_event_type e, DispEngine dispEngine)
{
isMouseOver = false;
}
/// <summary>
/// Entry point for the DemoPick1 example.
/// Creates and displays a simple pickable object that changes color on mouse hover.
/// </summary>
static void Main()
{
DemoUtil.Present("DemoPick1", new DemoPick1());
}
}
}
+78
View File
@@ -0,0 +1,78 @@
using Hi.Geom;
using Hi.Disp;
using System;
using Hi.Coloring;
namespace Sample.Disp
{
/// <summary>
/// Demonstrates advanced object picking with multiple pickable objects.
/// Shows how to create and manage multiple pickable objects with different visual appearances.
/// Implements proper resource cleanup through the IDisposable interface.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoPick2.cs)]
/// </remarks>
public class DemoPick2 : IDisplayee, IDisposable
{
readonly Pickable pickableA = new ShowEventPickable { Tag = "A" };
readonly Pickable pickableB = new ShowEventPickable { Tag = "B" };
readonly Pickable pickableC = new ShowEventPickable { Tag = "C" };
/// <inheritdoc/>
public void Display(Bind bind)
{
bind.PickID = pickableA.PickingID;
bind.Rgb = ColorUtil.GetDiscreteRgb(1);
new box3d_t(0, 0, 0, 1, 1, 1).DisplayFace(bind);
bind.PickID = pickableB.PickingID;
bind.Rgb = ColorUtil.GetDiscreteRgb(2);
new box3d_t(0, 0, 1, 1, 1, 2).DisplayFace(bind);
bind.PickID = pickableC.PickingID;
bind.Rgb = ColorUtil.GetDiscreteRgb(3);
new box3d_t(0, 0, 2, 1, 1, 3).DisplayFace(bind);
bind.PickID = 0;
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
dst = dst.Expanded(new vec3d_t(0, 0, 0));
dst = dst.Expanded(new vec3d_t(1, 1, 3));
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
/// <inheritdoc/>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
pickableA.Dispose();
pickableB.Dispose();
pickableC.Dispose();
}
disposedValue = true;
}
}
/// <inheritdoc/>
public void Dispose()
{
Dispose(true);
}
#endregion
/// <summary>
/// Entry point for the DemoPick2 example.
/// Creates and displays multiple pickable objects with distinct colors and positions.
/// Demonstrates separation of picking behavior from visual representation.
/// </summary>
static void Main()
{
DemoUtil.Present("DemoPick2", new DemoPick2());
}
}
}
+58
View File
@@ -0,0 +1,58 @@
using Hi.Disp;
using Hi.Geom;
using System;
namespace Sample.Disp;
/// <summary>
/// Demonstrates creation of pickable 3D geometry at the primitive level.
/// Shows how to assign picking IDs directly to geometry vertices and create interactive triangles.
/// Uses a lower-level approach than the Pickable base class for more precise control.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoPickable.cs)]
/// </remarks>
public class DemoPickable : IDisplayee
{
private readonly Drawing draw;
private readonly ShowEventPickable pickable;
/// <summary>
/// Initializes a new instance of DemoPickable.
/// Creates a pickable triangle with a specific picking ID for user interaction.
/// </summary>
public DemoPickable()
{
pickable = new ShowEventPickable();
double pid = pickable.PickingID;
double[] vs = new double[] {
//pickID, x,y,z
pid, 0,0.1,0.1,
pid, 0.1,0,0,
pid, 0.1,0,0.1
};
draw = new Drawing(vs, Stamp.PV, GL.GL_TRIANGLES);
}
/// <inheritdoc/>
public void Display(Bind bind)
{
draw.Display(bind);
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
draw.ExpandToBox3d(ref dst);
}
/// <summary>
/// Entry point for the DemoPickable example.
/// Creates and displays a pickable triangle that can respond to mouse events.
/// Demonstrates integration of picking functionality with geometric primitives.
/// </summary>
[STAThread]
public static void Main()
{
DemoUtil.Present("DemoPickable", new DemoPickable());
}
}
+55
View File
@@ -0,0 +1,55 @@
using Hi.Geom;
using Hi.Disp;
namespace Sample.Disp
{
/// <summary>
/// Demonstrates a simple solar system animation using <see cref="IDisplayee"/> interface.
/// Shows how to create a hierarchical transform structure with sun, earth and moon using
/// <see cref="mat4d_t"/> matrices and model matrix stack transformations.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoSatellite.cs)]
/// </remarks>
public class DemoSatellite : IDisplayee
{
Drawing sun;
Drawing earth;
Drawing moon;
double angle_earth;
double angle_moon;
DemoSatellite()
{
sun = box3d_t.CenterUnitBox.ScaledFromCenter(4).ToDraw_Face();
earth = box3d_t.CenterUnitBox.ScaledFromCenter(2).ToDraw_Face();
moon = box3d_t.CenterUnitBox.ToDraw_Face();
}
/// <inheritdoc/>
public void Display(Bind bind)
{
sun.Display(bind);
bind.ModelMatStack.Push();
bind.ModelMatStack.Mul(new mat4d_t(new AxisAngle4d(new vec3d_t(0, 0, 1), angle_earth += 0.03)));
bind.ModelMatStack.Mul(new mat4d_t(new vec3d_t(12, 0, 0)));
earth.Display(bind);
bind.ModelMatStack.Push();
bind.ModelMatStack.Mul(new mat4d_t(new AxisAngle4d(new vec3d_t(0, 0, 1), angle_moon += 0.02)));
bind.ModelMatStack.Mul(new mat4d_t(new vec3d_t(4, 0, 0)));
moon.Display(bind);
bind.ModelMatStack.Pop();
bind.ModelMatStack.Pop();
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
dst = dst.Expanded(new vec3d_t(-14, -14, -2));
dst = dst.Expanded(new vec3d_t(14, 14, 2));
}
static void Main()
{
DemoUtil.Present("DemoSatellite", new DemoSatellite());
}
}
}
+45
View File
@@ -0,0 +1,45 @@
using Hi.Disp;
using Hi.Geom;
using Hi.HiNcKits;
using Microsoft.Extensions.Logging;
using System;
namespace Sample.Disp;
/// <summary>
/// Runs a display sample to the point where its <see cref="IDisplayee"/> is ready to be rendered.
/// HiAPI ships no rendering canvas, so the samples in this project stop at the handover: they
/// compose the displayee and report it, and the application hands that same object to a canvas of
/// its own. See the Building Your Own Rendering Canvas guide for the canvas side.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoUtil.cs)]
/// </remarks>
public static class DemoUtil
{
/// <summary>
/// Initializes the application, reports the displayee's extent, and shuts down again —
/// the headless equivalent of opening a window on it.
/// </summary>
/// <param name="title">A name for the sample, used in the console output.</param>
/// <param name="displayee">The object a rendering canvas would display.</param>
public static void Present(string title, IDisplayee displayee)
{
if (displayee is null) throw new ArgumentNullException(nameof(displayee));
using var loggerFactory = LoggerFactory.Create(b => b.AddConsole());
LocalApp.AppBegin(loggerFactory.CreateLogger("Hi.Sample"));
try
{
box3d_t box = new box3d_t();
displayee.ExpandToBox3d(ref box);
Console.WriteLine($"{title}: {displayee.GetType().Name} bounding {box}");
Console.WriteLine("Assign it to your canvas' DispEngine.Displayee to see it.");
}
finally
{
LocalApp.AppEnd();
}
}
}
+119
View File
@@ -0,0 +1,119 @@
using Hi.Disp.Flag;
using Hi.Disp;
using Hi.Machining.MachiningEquipmentUtils;
using Hi.Mech.Topo;
using Hi.Numerical;
using Hi.Numerical.NcArgs;
using System.Collections;
using System;
using Hi.Geom;
using System.Linq;
namespace Sample.Disp
{
/// <summary>
/// Displayee for Heidenhain coordinate entry visualization.
/// </summary>
public class HeidenhainCoordinateEntryDisplayee : IAnchoredDisplayee
{
/// <summary>
/// Gets or sets whether to show Heidenhain datum preset information.
/// </summary>
public bool ShowHeidenhainDatumPreset { get; set; } = true;
/// <summary>
/// Gets or sets whether to show Heidenhain datum shift information.
/// </summary>
public bool ShowHeidenhainDatumShift { get; set; } = true;
/// <summary>
/// Gets or sets the function that provides the NcEnv instance.
/// </summary>
public Func<HardNcEnv> NcEnvFunc { get; set; }
/// <summary>
/// Gets or sets the function that provides the machining equipment.
/// </summary>
public Func<IMachiningEquipment> MillingEquipmentFunc { get; set; }
HardNcEnv NcEnv => NcEnvFunc?.Invoke();
/// <summary>
/// Gets or sets the Heidenhain Cycle Def 247 Q339 value.
/// </summary>
public int HeidenhainCycleDef247Q339 { get; set; }
/// <summary>
/// Gets or sets the Heidenhain Cycle Def 7 arguments.
/// </summary>
public HeidenhainCycleDef7Arg HeidenhainCycleDef7Arg { get; set; }
/// <summary>
/// Initializes a new instance.
/// </summary>
/// <param name="ncEnvFunc">The function that provides the NcEnv instance.</param>
/// <param name="millingEquipmentSource">The function that provides the machining equipment.</param>
public HeidenhainCoordinateEntryDisplayee(Func<HardNcEnv> ncEnvFunc, Func<IMachiningEquipment> millingEquipmentSource)
{
NcEnvFunc = ncEnvFunc;
MillingEquipmentFunc = millingEquipmentSource;
}
/// <inheritdoc/>
public void Display(Bind bind)
{
HardNcEnv ncEnv = NcEnv;
if (ncEnv == null || NcEnv.CncBrand != CncBrand.Heidenhain)
return;
////Console.WriteLine($"B: {CoordinateIndex}; {coordinateMove}");
IMachiningEquipment equipment = MillingEquipmentFunc?.Invoke();
if (equipment == null
|| !equipment.TryGetMachinePositionAtTableMountZero(out vec3d_t mcXyz_AttacherAtTableMountZero))
return;
vec3d_t coordinateMove;
string text;
if (HeidenhainCycleDef247Q339 == 0 && HeidenhainCycleDef7Arg == null)
return;
coordinateMove = NcFlagUtil.GetHeidenhainCoordinateOffset(
HeidenhainCycleDef247Q339, HeidenhainCycleDef7Arg, ncEnv);
//Console.WriteLine($"HeidenhainCycleDef7Arg: {HeidenhainCycleDef7Arg==null}");
string datumPresetText = null;
if (HeidenhainCycleDef247Q339 != 0 && ShowHeidenhainDatumPreset)
datumPresetText = $"Datum Preset Q339={HeidenhainCycleDef247Q339}";
string datumShiftText = null;
if (HeidenhainCycleDef7Arg != null && ShowHeidenhainDatumShift)
datumShiftText = $"Datum Shift: {HeidenhainCycleDef7Arg?.ToString() ?? "None"}";
text = string.Join(", ",
(new string[] { datumPresetText, datumShiftText }).
Where(v => v != null));
//text = $"Datum Preset Q339={HeidenhainCycleDef247Q339}, Datum Shift: #1";
//Console.WriteLine($"text: [{text}]");
bind.ModelMatStack.Push();
bind.ModelMatStack.Trans(coordinateMove - mcXyz_AttacherAtTableMountZero);
CoordinateDrawing.Display(bind, text);
bind.ModelMatStack.Pop();
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
HardNcEnv ncEnv = NcEnv;
if (ncEnv == null || NcEnv.CncBrand != CncBrand.Heidenhain)
return;
IMachiningEquipment equipment = MillingEquipmentFunc?.Invoke();
if (equipment == null
|| !equipment.TryGetMachinePositionAtTableMountZero(out vec3d_t mcXyz_AttacherAtTableMountZero))
return;
vec3d_t coordinateMove;
if (HeidenhainCycleDef247Q339 == 0 && HeidenhainCycleDef7Arg == null)
return;
coordinateMove = NcFlagUtil.GetHeidenhainCoordinateOffset(
HeidenhainCycleDef247Q339, HeidenhainCycleDef7Arg, ncEnv);
dst = dst.Expanded(-mcXyz_AttacherAtTableMountZero + coordinateMove);
}
/// <inheritdoc/>
public Anchor GetAnchor()
{
return MillingEquipmentFunc?.Invoke()?.GetMachiningChain()
?.GetTableMount()?.GetAnchor();
}
}
}
+81
View File
@@ -0,0 +1,81 @@
using Hi.Disp;
using Hi.Disp.Flag;
using Hi.Geom;
using Hi.Machining.MachiningEquipmentUtils;
using Hi.Mech.Topo;
using Hi.Numerical;
using System;
namespace Sample.Disp;
/// <summary>
/// Displayee for ISO coordinate entry visualization.
/// </summary>
public class IsoCoordinateEntryDisplayee : IAnchoredDisplayee
{
/// <summary>
/// Gets or sets the ISO coordinate key (e.g. "G54", "G59.2").
/// </summary>
public string IsoCoordinateId { get; set; } = "G54";
/// <summary>
/// Gets or sets the function that provides the NcEnv instance.
/// </summary>
public Func<HardNcEnv> NcEnvFunc { get; set; }
/// <summary>
/// Gets or sets the function that provides the machining equipment.
/// </summary>
public Func<IMachiningEquipment> MillingEquipmentFunc { get; set; }
HardNcEnv NcEnv => NcEnvFunc?.Invoke();
/// <summary>
/// Initializes a new instance of the <see cref="IsoCoordinateEntryDisplayee"/> class.
/// </summary>
/// <param name="ncEnvFunc">The function that provides the NcEnv instance.</param>
/// <param name="millingEquipmentSource">The function that provides the machining equipment.</param>
public IsoCoordinateEntryDisplayee(Func<HardNcEnv> ncEnvFunc,
Func<IMachiningEquipment> millingEquipmentSource)
{
NcEnvFunc = ncEnvFunc;
MillingEquipmentFunc = millingEquipmentSource;
}
/// <inheritdoc/>
public void Display(Bind bind)
{
HardNcEnv ncEnv = NcEnv;
if (ncEnv == null)
return;
if (ncEnv.IsoCoordinateTable?.TryGetValue(IsoCoordinateId, out vec3d_t coordinateMove) != true)
return;
string text = IsoCoordinateId ?? "";
IMachiningEquipment equipment = MillingEquipmentFunc?.Invoke();
if (equipment == null || !equipment.TryGetIsoCoordinatePosition(coordinateMove, out vec3d_t attacherPos))
return;
bind.ModelMatStack.Push();
bind.ModelMatStack.Trans(attacherPos);
CoordinateDrawing.Display(bind, text);
bind.ModelMatStack.Pop();
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
HardNcEnv ncEnv = NcEnv;
if (ncEnv == null)
return;
if (ncEnv.IsoCoordinateTable?.TryGetValue(IsoCoordinateId, out vec3d_t coordinateMove) != true)
return;
IMachiningEquipment equipment = MillingEquipmentFunc?.Invoke();
if (equipment == null || !equipment.TryGetIsoCoordinatePosition(coordinateMove, out vec3d_t attacherPos))
return;
dst = dst.Expanded(attacherPos);
}
/// <inheritdoc/>
/// <returns>Table Mount if existed; otherwise, return null.</returns>
public Anchor GetAnchor()
{
return MillingEquipmentFunc?.Invoke()?.GetMachiningChain()?.GetAnchor();
}
}
+250
View File
@@ -0,0 +1,250 @@
using Hi.Coloring;
using Hi.MachiningProcs;
using Hi.Common;
using Hi.Disp;
using Hi.Disp.Flag;
using Hi.Mech.Topo;
using System.Collections.Generic;
using System.Collections;
using Hi.Geom;
using System.Linq;
using Hi.NcMech.Solids;
using Hi.Numerical;
using System;
namespace Sample.Disp;
/// <summary>
/// Represents a displayable wrapper for a machining project.
/// </summary>
public class MachiningProjectDisplayee : IDisplayee, IGetAnchor
{
/// <summary>
/// Gets the current milling course from the host function.
/// </summary>
public MachiningProject MachiningProject => LocalProjectService.MachiningProject;
/// <summary>
/// Gets or sets the function that provides the machining project.
/// </summary>
public LocalProjectService LocalProjectService { get; set; }
///// <summary>
///// Initializes a new instance of the <see cref="MachiningProjectDisplayee"/> class.
///// </summary>
///// <param name="machiningProject">The machining project to display.</param>
///// <param name="renderingFlagBitArray">The bit array controlling rendering flags.</param>
//public MachiningProjectDisplayee(MachiningProject machiningProject,
// BitArray renderingFlagBitArray)
// {
// RenderingFlagBitArray = renderingFlagBitArray;
// }
/// <summary>
/// Initializes a new instance of the <see cref="MachiningProjectDisplayee"/> class with default rendering flags.
/// </summary>
public MachiningProjectDisplayee(LocalProjectService localProjectService)
{ LocalProjectService = localProjectService; }
/// <summary>
/// Gets or sets the bit array that controls which elements are rendered.
/// </summary>
public BitArray RenderingFlagBitArray { get; set; } = new BitArray(EnumUtil.GetEnumBitArrayCap<RenderingFlag>())
{
[(int)RenderingFlag.DimensionBar] = true,
[(int)RenderingFlag.WorkpieceGeom] = true,
[(int)RenderingFlag.Fixture] = true,
[(int)RenderingFlag.ClStrip] = true,
//[(int)RenderingFlag.Mech] = true,
};
IsoCoordinateEntryDisplayee isoCoordinateEntryDisplayee;
/// <summary>
/// Gets the ISO coordinate entry displayee for ISO-based coordinate systems.
/// </summary>
public IsoCoordinateEntryDisplayee IsoCoordinateEntryDisplayee =>
isoCoordinateEntryDisplayee ??= new IsoCoordinateEntryDisplayee(
() => MachiningProject.NcEnv,
() => LocalProjectService.MachiningEquipment);
HeidenhainCoordinateEntryDisplayee heidenhainCoordinateEntryDisplayee;
/// <summary>
/// Gets the Heidenhain coordinate entry displayee for Heidenhain-based coordinate systems.
/// </summary>
public HeidenhainCoordinateEntryDisplayee HeidenhainCoordinateEntryDisplayee =>
heidenhainCoordinateEntryDisplayee ??= new HeidenhainCoordinateEntryDisplayee(
() => MachiningProject.NcEnv,
() => LocalProjectService.MachiningEquipment);
/// <summary>
/// Gets a list of anchored displayees based on current rendering flags.
/// </summary>
/// <returns>A list of anchored displayees for rendering</returns>
List<IAnchoredDisplayee> GetAnchoredDisplayeeList()
{
List<IAnchoredDisplayee> dst = new List<IAnchoredDisplayee>();
MachiningProject machiningProject = MachiningProject;
if (machiningProject == null)
return dst;
LocalProjectService localProjectService = LocalProjectService;
HardNcEnv ncEnv = machiningProject.NcEnv;
//the execution scene draws the RUNTIME face throughout (equipment
//split: the service facades expose the authored setup face instead)
var machiningEquipment = localProjectService.MachiningEquipment;
var workpiece = machiningEquipment?.Workpiece;
if (RenderingFlagBitArray[(int)RenderingFlag.ClStrip])
{
localProjectService.ClStrip.IsKeepingDispAlive = true;
dst.Add(new AnchoredDisplayee(
workpiece?.ProgramZeroAnchor,
localProjectService.ClStrip));
}
if (RenderingFlagBitArray[(int)RenderingFlag.Mech])
{
if (machiningEquipment != null)
{
List<IAnchoredDisplayee> machAncDisplayees =
machiningEquipment.GetAnchoredDisplayeeList() ?? [];
HashSet<Anchor> exclusiveAnchorSet = new([
.. workpiece?.Asmb.DescendantAnchors()??[],
.. machiningEquipment.MachiningTool?.GetAsmb().DescendantAnchors()??[],
.. machiningEquipment.Fixture?.Asmb.DescendantAnchors()??[],
]);
dst.AddRange(machAncDisplayees.Where(ad =>
!exclusiveAnchorSet.Contains(ad.GetAnchor())));
}
}
if (RenderingFlagBitArray[(int)RenderingFlag.WorkpieceGeom])
{
if (workpiece != null)
dst.AddRange(localProjectService.WorkpieceService
.GetAnchoredDisplayeeList());
}
if (RenderingFlagBitArray[(int)RenderingFlag.Tool])
{
if (machiningEquipment?.MachiningTool != null)
dst.Add(new AnchoredDisplayee(
machiningEquipment.MachiningTool?.GetAnchor(),
machiningEquipment.MachiningTool));
}
if (RenderingFlagBitArray[(int)RenderingFlag.Fixture])
{
if (machiningEquipment?.Fixture != null)
dst.Add(new AnchoredDisplayee(
machiningEquipment.Fixture.GetAnchor(),
machiningEquipment.Fixture));
}
if (RenderingFlagBitArray[(int)RenderingFlag.ProgramZero])
{
if (workpiece != null)
dst.Add(workpiece.ProgramZeroAnchor);
}
if (RenderingFlagBitArray[(int)RenderingFlag.IsoCoordinate])
{
dst.Add(IsoCoordinateEntryDisplayee);
}
if (RenderingFlagBitArray[(int)RenderingFlag.HeidenhainCoordinate]
&& ncEnv.CncBrand == CncBrand.Heidenhain)
{
dst.Add(HeidenhainCoordinateEntryDisplayee);
}
return dst;
}
/// <summary>
/// Gets the root anchor for the display hierarchy based on current rendering flags.
/// </summary>
/// <returns>The root anchor to use for rendering</returns>
internal static Anchor GetRootAnchor(
LocalProjectService localProjectService, BitArray renderingFlagBitArray)
{
//runtime face throughout: this roots the execution scene
var machiningEquipment = localProjectService?.MachiningEquipment;
if (renderingFlagBitArray[(int)RenderingFlag.Mech])
return machiningEquipment?.GetAnchor();
else if (renderingFlagBitArray[(int)RenderingFlag.WorkpieceGeom])
return machiningEquipment?.Workpiece?.GetAnchor();
else if (renderingFlagBitArray[(int)RenderingFlag.Fixture])
return machiningEquipment?.Fixture?.GetAnchor();
else if (renderingFlagBitArray[(int)RenderingFlag.Tool])
return machiningEquipment?.MachiningTool?.GetAnchor();
else
return null;
}
/// <inheritdoc/>
public Anchor GetAnchor() => GetRootAnchor(LocalProjectService, RenderingFlagBitArray);
/// <inheritdoc/>
public void Display(Bind bind)
{
//Console.WriteLine($"RB: {string.Join(',', Enumerable.Range(0,
// RenderingFlagBitArray.Length).Select(RenderingFlagBitArray.Get))}");
//ClStrip pos has to be update by ClStrip.
if (RenderingFlagBitArray[(int)RenderingFlag.WorkpieceGeom]
&& !RenderingFlagBitArray[(int)RenderingFlag.ClStrip]
&& LocalProjectService?.ClStrip.CallRefreshDrawing == true)
LocalProjectService?.ClStrip.RefreshDrawingInRendering(false);
bind.PushCoveringPixelMode();
double offsetHOnCover = 0;
if (RenderingFlagBitArray[(int)RenderingFlag.DimensionBar])
{
bind.ModelMatStack.Push();
bind.ModelMatStack.Trans(0, offsetHOnCover, 0);
DimensionBar.Display(bind, "mm");
bind.ModelMatStack.Pop();
offsetHOnCover += DimensionBar.OffsetH;
}
if (RenderingFlagBitArray[(int)RenderingFlag.ColorScaleBar]
&& MachiningProject?.MillingGuide?.DictionaryColorGuide?.SelectedColorGuide
is IGetRangeColorRule getRangeColorRule)
{
var rangeColorRule = getRangeColorRule.GetRangeColorRule();
if (rangeColorRule != null)
{
bind.ModelMatStack.Push();
bind.ModelMatStack.Trans(0, offsetHOnCover, 0);
ColorScaleBar.Display(bind,
rangeColorRule.Floor, rangeColorRule.Ceiling,
rangeColorRule.GetRgb, "L.", "");
bind.ModelMatStack.Pop();
offsetHOnCover += ColorScaleBar.OffsetH;
}
}
if (LocalProjectService?.WorkpieceService?.HasDiffOverlay == true)
{
bind.ModelMatStack.Push();
bind.ModelMatStack.Trans(0, offsetHOnCover, 0);
var rangeColorRule = LocalProjectService.WorkpieceService.DiffRangeColorRule;
ColorScaleBar.Display(bind,
rangeColorRule.Floor, rangeColorRule.Ceiling,
rangeColorRule.GetRgb, "Df.", "");
bind.ModelMatStack.Pop();
offsetHOnCover += ColorScaleBar.OffsetH;
}
bind.ModelMatStack.Pop();
bind.PushColorByRgb(1, 1, 1);
var machiningEquipment = LocalProjectService?.MachiningEquipment;
//Collision red is per-scenario state owned by the execution equipment
//(never stored on the shared Solid geometry): scope it to this scene
//so the setup topology never paints it.
using (CollisionRedScope.Enter(
machiningEquipment == null ? null : machiningEquipment.IsCollisionRed))
{
machiningEquipment?.GetAsmb()?.Display(bind,
GetAnchor(),
GetAnchoredDisplayeeList().ToArray());
}
bind.PopColor();
}
/// <inheritdoc/>
public void ExpandToBox3d(ref box3d_t dst)
{
//Console.WriteLine($"dst.A: {dst}");
LocalProjectService?.MachiningEquipment?.GetAsmb()?.ExpandToBox3d(ref dst,
GetAnchor(),
GetAnchoredDisplayeeList().ToArray());
//Console.WriteLine($"dst.B: {dst}");
}
}
+2 -2
View File
@@ -30,8 +30,8 @@ public static class DemoBuildGeom
TransformationGeom transformationGeom = new TransformationGeom()
{
Transformer = new GeneralTransform(1,
new StaticRotation(new Vec3d(0, 0, 1), MathUtil.ToRad(15), new Vec3d(0, 0, 0)),
new StaticTranslation(new Vec3d(0, 0, 0))),
new StaticRotation(new vec3d_t(0, 0, 1), MathUtil.ToRad(15), new vec3d_t(0, 0, 0)),
new StaticTranslation(new vec3d_t(0, 0, 0))),
Geom = stl
};
GeomCombination geomCombination = new GeomCombination(stlFile, transformationGeom);
+5 -5
View File
@@ -5,7 +5,7 @@ namespace Sample.Geom;
/// <summary>
/// Demonstrates how to create and calculate bounding boxes for different geometric objects.
/// Shows the use of Box3d to encompass multiple geometric elements with a single boundary.
/// Shows the use of box3d_t to encompass multiple geometric elements with a single boundary.
/// </summary>
/// <remarks>
/// ### Source Code
@@ -16,11 +16,11 @@ public static class DemoIExpandToBox3d
static void Main()
{
#region DocSite.CountBoundingBox
Box3d objA = new Box3d(0, 0, 0, 1, 1, 1);
Box3d objB = new Box3d(-1, -2, -3, 3, 2, 1);
Vec3d objC = new Vec3d(-2, 3, -5);
box3d_t objA = new box3d_t(0, 0, 0, 1, 1, 1);
box3d_t objB = new box3d_t(-1, -2, -3, 3, 2, 1);
vec3d_t objC = new vec3d_t(-2, 3, -5);
Box3d boundingbox = new Box3d(objA, objB, objC);
box3d_t boundingbox = new box3d_t(objA, objB, objC);
Console.WriteLine("boundingbox: " + boundingbox);
#endregion
}
+3 -1
View File
@@ -1,4 +1,5 @@
using Hi.HiNcKits;
using Microsoft.Extensions.Logging;
using System;
namespace Sample
@@ -18,7 +19,8 @@ namespace Sample
static int Main(string[] args)
{
Console.WriteLine("HiAPI starting.");
LocalApp.AppBegin();
using var loggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(b => b.AddConsole());
LocalApp.AppBegin(loggerFactory.CreateLogger("Hi.Sample"));
Console.WriteLine("Hello World! HiAPI.");
+2 -2
View File
@@ -11,7 +11,7 @@
</Description>
<Configurations>Debug;Release</Configurations>
<VersionBuild>0</VersionBuild>
<VersionPrefix>3.1.$(VersionBuild)</VersionPrefix>
<VersionPrefix>3.2.$(VersionBuild)</VersionPrefix>
<Product>$(AssemblyName)</Product>
<ApplicationIcon>techcoordinate.ico</ApplicationIcon>
<Copyright>Copyright 2025 Tech Coordinate Co., Ltd.</Copyright>
@@ -32,7 +32,7 @@
<ProjectReference Include="..\HiNc\HiNc.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Release'">
<PackageReference Include="HiNc" Version="3.1.*" />
<PackageReference Include="HiNc" Version="3.2.*" />
</ItemGroup>
</Project>
+32 -19
View File
@@ -1,4 +1,4 @@
using Hi.Common.XmlUtils;
using Hi.Common.XmlUtils;
using Hi.Geom;
using Hi.Mech;
using Hi.Mech.Topo;
@@ -15,28 +15,38 @@ using System.Xml.Linq;
namespace Sample.MachineTool
{
/// <summary>
/// Provides access to the PMC-B1 machine tool model.
/// Provides access to the Table-B1 machine tool model.
/// </summary>
/// <remarks>
/// ### Source Code
/// [!code-csharp[SampleCode](~/../Hi.Sample/MachineTool/DemoBuildMachineTool.cs)]
/// </remarks>
public class DemoBuildMachineTool : IGetCodeXyzabcMachineTool
public class DemoBuildMachineTool
{
static DemoBuildMachineTool()
/// <summary>
/// Registers this type's deserializer with the given <see cref="XFactory"/>
/// (or <see cref="XFactory.Default"/> when <paramref name="factory"/> is
/// <c>null</c>). Idempotent.
/// </summary>
public static void Reg(XFactory factory = null)
{
XFactory.Regs.Add(XName, (xml, baseDirectory, relFile, res) => new DemoBuildMachineTool());
factory ??= XFactory.Default;
factory.Generators.TryAdd(XName, (xml, baseDirectory, relFile, progress, res) => new DemoBuildMachineTool());
}
/// <summary>
/// Generates an XYZ-ABC machine tool instance from embedded resources.
/// </summary>
/// <returns>A configured machine tool model.</returns>
public static CodeXyzabcMachineTool GenXyzabcMachineTool()
public static GeneralXyzabcMachineTool GenXyzabcMachineTool()
{
CodeXyzabcChain chain = new CodeXyzabcChain("[O][Y][X][C][w];[O][Z][B][S][t]");
if (chain.ToolBuckleTransformer is StaticTranslation st)
st.Trans = new Vec3d(-72.40, 72.40, 176.44);
chain.TransformerB.Pivot = new Vec3d(-72.4, -177.4, 225.94);
GeneralXyzabcMachineTool dst = GeneralXyzabcMachineTool.CreateFromChainCode(
"[O][Y][X][C][w];[O][Z][B][S][t]");
if (dst.ToolMountTransformer is StaticTranslation st)
st.Trans = new vec3d_t(-72.40, 72.40, 176.44);
//the spindle turns the tool about its own axis: the rotation's pivot
//sits on the tool mount's origin, where the offset above moved it.
dst.SpindleTransformer.Pivot = new vec3d_t(-72.40, 72.40, 176.44);
dst.TransformerB.Pivot = new vec3d_t(-72.4, -177.4, 225.94);
Dictionary<string, Solid> solidMap = new Dictionary<string, Solid>()
{
["O"] = new Solid(new Stl("MachineTool/base.stl")),
@@ -47,10 +57,8 @@ namespace Sample.MachineTool
["C"] = new Solid(new Stl("MachineTool/C.stl")),
["S"] = new Solid(new Stl("MachineTool/spindle.stl")),
};
chain.AnchorToSolid.BuildAnchorToSolid(
chain.Asmb.GetDescendantAnchors(), solidMap);
CodeXyzabcMachineTool dst = new CodeXyzabcMachineTool(chain);
dst.AnchorToSolid.BuildAnchorToSolid(
dst.Asmb.DescendantAnchors(), solidMap);
dst.GenerateCollisionIndexPairs();
return dst;
}
@@ -58,7 +66,7 @@ namespace Sample.MachineTool
/// <summary>
/// The cached machine tool instance.
/// </summary>
CodeXyzabcMachineTool MachineTool { get; }
GeneralXyzabcMachineTool MachineTool { get; }
/// <summary>
/// Default constructor that initializes the machine tool model.
@@ -68,7 +76,6 @@ namespace Sample.MachineTool
MachineTool = GenXyzabcMachineTool();
}
#region XML IO
//public PmcB1MachineToolSource(XElement src, object res) : this() { }
/// <summary>
/// XML element name for serialization.
/// </summary>
@@ -76,9 +83,15 @@ namespace Sample.MachineTool
/// <inheritdoc/>
public XElement ToXElement() => new XElement(XName);
#endregion
/// <inheritdoc/>
public CodeXyzabcMachineTool GetXyzabcMachineTool() => MachineTool;
/// <inheritdoc/>
/// <summary>
/// Gets the built machine tool.
/// </summary>
/// <returns>Machine tool.</returns>
public GeneralXyzabcMachineTool GetXyzabcMachineTool() => MachineTool;
/// <summary>
/// Gets the machine tool as a machining chain.
/// </summary>
/// <returns>Machining chain.</returns>
public IMachiningChain GetMachiningChain() => MachineTool;
}
}
@@ -18,12 +18,12 @@ public static class DemoBuildMachineToolWithoutGeometrys
/// Generates an empty machine tool with basic configuration.
/// </summary>
/// <returns>A configured but empty machine tool without solids.</returns>
public static CodeXyzabcMachineTool GenEmptyMachineTool()
public static GeneralXyzabcMachineTool GenEmptyMachineTool()
{
CodeXyzabcChain chain = new CodeXyzabcChain("[O][C][w];[O][X][Y][Z][B][S][t]");
if (chain.ToolBuckleTransformer is StaticTranslation st)
st.Trans = new Vec3d(-200, 200, 400);
CodeXyzabcMachineTool xyzabcMachineTool = new CodeXyzabcMachineTool(chain);
GeneralXyzabcMachineTool xyzabcMachineTool = GeneralXyzabcMachineTool.CreateFromChainCode(
"[O][C][w];[O][X][Y][Z][B][S][t]");
if (xyzabcMachineTool.ToolMountTransformer is StaticTranslation st)
st.Trans = new vec3d_t(-200, 200, 400);
return xyzabcMachineTool;
}
}
+25 -17
View File
@@ -1,4 +1,4 @@
using Hi.Common.XmlUtils;
using Hi.Common.XmlUtils;
using Hi.Geom;
using Hi.MachiningProcs;
using Hi.Mech.Topo;
@@ -14,6 +14,7 @@ using Hi.NcMech.Holders;
using Hi.Machining;
using Hi.HiNcKits;
using Hi.Milling.MillingTools;
using Microsoft.Extensions.Logging;
namespace Sample.Machining;
@@ -42,7 +43,8 @@ public static class DemoBuildGeomOnlyMachiningProject
static void Main()
{
LocalApp.AppBegin();
using var loggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(b => b.AddConsole());
LocalApp.AppBegin(loggerFactory.CreateLogger("Hi.Sample"));
LocalProjectService localProjectService = new LocalProjectService();
var projectPath = "C:/HiNC-Projects/NewProject/Main.hincproj";
@@ -68,28 +70,34 @@ public static class DemoBuildGeomOnlyMachiningProject
},
};
localProjectService.Fixture = new Fixture()
{
Geom = new Box3d(new Vec3d(-40, -40, 0), new Vec3d(40, 40, 10)),
GeomToWorkpieceTransformer = new StaticTranslation(new Vec3d(0, 0, 10)),
};
//The fixture topology is free; the default shape has one branch from the
//geometry anchor to each mount, so the workpiece mount is placed by the
//transformer of the branch to it: on top of the 10 mm thick fixture geom.
Fixture fixture = Fixture.CreateDefault();
fixture.Geom = new Box3d(new vec3d_t(-40, -40, 0), new vec3d_t(40, 40, 10));
Branch.Get(fixture.GeomAnchor, fixture.WorkpieceMount).Transformer
= new StaticTranslation(new vec3d_t(0, 0, 10));
localProjectService.Fixture = fixture;
localProjectService.Workpiece = new Workpiece()
{
InitResolution = 0.25,
InitGeom = new Box3d(0, 0, -50, 70, 50, 0),
IdealGeom = null,
WorkpieceGeomToFixtureBuckleTransformer = new StaticTranslation(new Vec3d(0, 0, 0)),
};
//The default shape already leads from the geometry anchor to the fixture
//mount and to program zero by zero translations.
Workpiece workpiece = Workpiece.CreateDefault();
workpiece.InitResolution = 0.25;
workpiece.InitGeom = new Box3d(0, 0, -50, 70, 50, 0);
workpiece.IdealGeom = null;
localProjectService.Workpiece = workpiece;
IProgress<object> progress = null;
localProjectService.MachiningChain
= XFactory.GenByFile<CodeXyzabcMachineTool>(
"Resource", "MachineTool/PMC-B1/PMC-B1.mt", GenMode.Default);
localProjectService.MachiningChainFile = "PMC-B1/PMC-B1.mt";
= XFactory.GenByFile<GeneralXyzabcMachineTool>(
"Resource", "MachineTool/Table-B1.default/Table-B1.mt", progress);
localProjectService.MachiningChainFile = "Table-B1.default/Table-B1.mt";
localProjectService.SaveProject();
machiningProject.Dispose();
//the service holds the play threads, the strip and the cut workpiece tree: dispose it before AppEnd
localProjectService.Dispose();
LocalApp.AppEnd();
}
+33 -24
View File
@@ -1,4 +1,4 @@
using System;
using System;
using Hi.Milling.Apts;
using Hi.Common.XmlUtils;
using Hi.Geom;
@@ -17,6 +17,7 @@ using Hi.MachiningProcs;
using System.IO;
using Hi.HiNcKits;
using Hi.Milling.MillingTools;
using Microsoft.Extensions.Logging;
namespace Sample.Machining;
@@ -63,11 +64,11 @@ public static class DemoBuildMachiningProject
InnerBeamProfile = new FluteDependentRatioProfile(),
MillingCutterOptLimit = new MillingCutterOptOption(),
};
//build FluteContourTray property
//build Fluting property
double helixAngle_deg = 50;
double radialRakeAngle_deg = 15;
double bottomOuterRadius_mm = diameter_mm / 2 - roundRadius_mm;
millingCutter.FluteContourTray = new UniformContourTray()
millingCutter.Fluting = new UniformFluting()
{
TrackNum = 3,
BaselineOneContour = new FluteContour()
@@ -110,10 +111,10 @@ public static class DemoBuildMachiningProject
MillingCutterOptLimit = new MillingCutterOptOption()
};
//build FluteContourTray property
//build Fluting property
double helixAngle_deg = 50;
double radialRakeAngle_deg = 15;
millingCutter.FluteContourTray = new UniformContourTray()
millingCutter.Fluting = new UniformFluting()
{
TrackNum = 3,
BaselineOneContour = new FluteContour()
@@ -142,7 +143,8 @@ public static class DemoBuildMachiningProject
[STAThread]
static void Main()
{
LocalApp.AppBegin();
using var loggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(b => b.AddConsole());
LocalApp.AppBegin(loggerFactory.CreateLogger("Hi.Sample"));
LocalProjectService localProjectService = new LocalProjectService();
var projectPath = "C:/HiNC-Projects/NewProject/Main.hincproj";
@@ -151,6 +153,8 @@ public static class DemoBuildMachiningProject
localProjectService.LoadProject(projectPath);
MachiningProject machiningProject = localProjectService.MachiningProject;
IProgress<object> progress = null;
#region ConfigureMachiningToolHouse
localProjectService.MachiningToolHouse = new MachiningToolHouse()
{
@@ -179,36 +183,41 @@ public static class DemoBuildMachiningProject
#endregion
#region ConfigureFixture
localProjectService.Fixture = new Fixture()
{
Geom = new Box3d(new Vec3d(-40, -40, 0), new Vec3d(40, 40, 10)),
GeomToWorkpieceTransformer = new StaticTranslation(new Vec3d(0, 0, 10)),
};
//The fixture topology is free; the default shape has one branch from the
//geometry anchor to each mount, so the workpiece mount is placed by the
//transformer of the branch to it: on top of the 10 mm thick fixture geom.
Fixture fixture = Fixture.CreateDefault();
fixture.Geom = new Box3d(new vec3d_t(-40, -40, 0), new vec3d_t(40, 40, 10));
Branch.Get(fixture.GeomAnchor, fixture.WorkpieceMount).Transformer
= new StaticTranslation(new vec3d_t(0, 0, 10));
localProjectService.Fixture = fixture;
#endregion
#region ConfigureWorkpiece
localProjectService.Workpiece = new Workpiece()
{
InitResolution = 0.25,
InitGeom = new Box3d(0, 0, -50, 70, 50, 0),
IdealGeom = null,
WorkpieceGeomToFixtureBuckleTransformer = new StaticTranslation(new Vec3d(0, 0, 0)),
CuttingPara = XFactory.GenByFile<ICuttingPara>(
"Resource/CuttingParameter", "Al6061T6.mp", GenMode.Default),
WorkpieceMaterial = XFactory.GenByFile<WorkpieceMaterial>(
"Resource/WorkpieceMaterial", "Al6061T6.WorkpieceMaterial", GenMode.Default),
};
//The default shape already leads from the geometry anchor to the fixture
//mount and to program zero by zero translations.
Workpiece workpiece = Workpiece.CreateDefault();
workpiece.InitResolution = 0.25;
workpiece.InitGeom = new Box3d(0, 0, -50, 70, 50, 0);
workpiece.IdealGeom = null;
workpiece.CuttingPara = XFactory.GenByFile<ICuttingPara>(
"Resource/CuttingParameter", "Al6061T6.default.mp", progress);
workpiece.WorkpieceMaterial = XFactory.GenByFile<WorkpieceMaterial>(
"Resource/WorkpieceMaterial", "Al6061T6.default.WorkpieceMaterial", progress);
localProjectService.Workpiece = workpiece;
#endregion
#region ConfigureMachineChain
localProjectService.MachiningChain
= XFactory.GenByFile<CodeXyzabcMachineTool>(
"Resource", "MachineTool/PMC-B1/PMC-B1.mt", GenMode.Default);
= XFactory.GenByFile<GeneralXyzabcMachineTool>(
"Resource", "MachineTool/Table-B1.default/Table-B1.mt", progress);
#endregion
machiningProject.MakeXmlSourceToFile(projectPath);
machiningProject.Dispose();
//the service holds the play threads, the strip and the cut workpiece tree: dispose it before AppEnd
localProjectService.Dispose();
LocalApp.AppEnd();
}
#endregion
+28 -18
View File
@@ -2,6 +2,8 @@
using Hi.Common.Messages;
using Hi.HiNcKits;
using Hi.MachiningProcs;
using Hi.NcParsers;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
@@ -21,7 +23,8 @@ public static class DemoUseMachiningProject
{
static void Main()
{
LocalApp.AppBegin();
using var loggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(b => b.AddConsole());
LocalApp.AppBegin(loggerFactory.CreateLogger("Hi.Sample"));
LocalProjectService localProjectService = new LocalProjectService();
#region ProjectLoading
@@ -35,23 +38,28 @@ public static class DemoUseMachiningProject
Console.WriteLine($"Set message event.");
using StreamWriter writer = new StreamWriter("msg.txt");
//show message if something abnormal.
localProjectService.SessionProgress.CollectionItemAdded += pack =>
//show message if something abnormal, from each partitioned message sink:
//shell (session lifecycle), NC diagnostics, and step-anchored diagnostics.
void LogIfAbnormal(IMessage message, ISentenceCarrier sentenceCarrier)
{
if (pack.Tags.Contains(MessageFlag.Warning.ToString()) ||
pack.Tags.Contains(MessageFlag.Error.ToString()) ||
pack.Tags.Contains(MessageFlag.Exception.ToString()))
{
var sourceCommand = pack.SourceCommand;
writer.WriteLine($"{pack.Message} At \"{sourceCommand?.FilePath}\" (Line {sourceCommand?.GetLineNo()}) \"{sourceCommand?.Line}\"");
var severity = message.GetSeverity();
if (severity != Severity.Warning && severity != Severity.Error)
return;
var ncLine = sentenceCarrier?.GetSentence()?.FirstIndexedFileLine;
writer.WriteLine($"{message.GetNotification()} At \"{ncLine?.FilePath}\" (Line {ncLine?.GetLineNo()}) \"{ncLine?.Line}\"");
}
};
localProjectService.OnShellMessageAdded += (index, message)
=> LogIfAbnormal(message, null);
localProjectService.NcDiagnosticProgress.MessageAdded += (index, diagnostic)
=> LogIfAbnormal(diagnostic, diagnostic.SentenceCarrier);
localProjectService.StepDiagnosticProgress.MessageAdded += (index, diagnostic)
=> LogIfAbnormal(diagnostic, diagnostic.SentenceCarrier);
Console.WriteLine($"Set machining step event.");
//show MRR.
localProjectService.RuntimeApi.MachiningStepBuilt += (preStep, curStep) =>
localProjectService.SessionShell.SessionStepBuilt += (preStep, curStep) =>
{
var sourceCommand = curStep.SourceCommand;
var indexedFileLine=sourceCommand?.GetSentence()?.IndexedFileLine;
var indexedFileLine=sourceCommand?.GetSentence()?.FirstIndexedFileLine;
if (curStep.Mrr_mm3ds > 500) //show only the step that contains large MRR.
Console.WriteLine($"MRR = {curStep.Mrr_mm3ds} At \"{indexedFileLine?.FilePath}\" (Line {indexedFileLine?.GetLineNo()}) \"{indexedFileLine?.Line}\"");
};
@@ -63,13 +71,13 @@ public static class DemoUseMachiningProject
Console.WriteLine($"Session begin.");
localProjectService.BeginSession();
localProjectService.RuntimeApi.MachiningResolution_mm = 1;
localProjectService.RuntimeApi.EnableCollisionDetection = true;
localProjectService.RuntimeApi.EnablePauseOnFailure = false;
localProjectService.RuntimeApi.EnablePhysics = false;
localProjectService.SessionShell.MachiningResolution_mm = 1;
localProjectService.SessionShell.EnableCollisionDetection = true;
localProjectService.SessionShell.EnablePauseOnFailure = false;
localProjectService.SessionShell.EnablePhysics = false;
//the path from Shell-API is relative by project directory.
localProjectService.RuntimeApi.PlayNcFile("NC/side.ptp");
localProjectService.RuntimeApi.PlayNcFile("NC/circle.ptp");
localProjectService.SessionShell.PlayNcFile("NC/side.ptp");
localProjectService.SessionShell.PlayNcFile("NC/circle.ptp");
localProjectService.EndSession();
Console.WriteLine($"Session end.");
#endregion
@@ -77,6 +85,8 @@ public static class DemoUseMachiningProject
#region CleanupResources
Console.WriteLine($"Close Project: {projectPath}");
machiningProject.Dispose();
//the service holds the play threads, the strip and the cut workpiece tree: dispose it before AppEnd
localProjectService.Dispose();
LocalApp.AppEnd();
+8 -9
View File
@@ -4,8 +4,8 @@ using Hi.Disp;
using Hi.Geom;
using Hi.Mech.Topo;
namespace Sample.Mech
{
namespace Sample.Mech;
/// <summary>
/// Demonstrates the creation and visualization of mechanical assemblies with kinematic linkages.
/// Shows how to build coordinate systems, establish kinematic relationships, and capture visual output.
@@ -33,10 +33,10 @@ namespace Sample.Mech
Anchor B = new Anchor(asmb, "B");
//build kinematic link
Branch.Attach(O, O1, new StaticTranslation(new Vec3d(0, 0, 80)));
Branch brnX = Branch.Attach(O1, X, new DynamicTranslation(new Vec3d(1, 0, 0)));
Branch brnZ = Branch.Attach(X, Z, new DynamicTranslation(new Vec3d(0, 0, 1)));
Branch brnB = Branch.Attach(Z, B, new DynamicRotation(new Vec3d(0, 1, 0), 0, new Vec3d(-100, 0, 0)));
Branch.Attach(O, O1, new StaticTranslation(new vec3d_t(0, 0, 80)));
Branch brnX = Branch.Attach(O1, X, new DynamicTranslation(new vec3d_t(1, 0, 0)));
Branch brnZ = Branch.Attach(X, Z, new DynamicTranslation(new vec3d_t(0, 0, 1)));
Branch brnB = Branch.Attach(Z, B, new DynamicRotation(new vec3d_t(0, 1, 0), 0, new vec3d_t(-100, 0, 0)));
//drive the dynamic transformation by single value for each branch.
brnX.Step = 200;
@@ -44,9 +44,9 @@ namespace Sample.Mech
brnB.Step = MathUtil.ToRad(-60);
//Get and show the transform matrices relative to O.
Dictionary<Anchor, Mat4d> matMap = asmb.GetMat4dMap(O);
Dictionary<Anchor, mat4d_t> matMap = asmb.GetMat4dMap(O);
Console.WriteLine("Transform Matrix relative to O:");
foreach (KeyValuePair<Anchor, Mat4d> keyValue in matMap)
foreach (KeyValuePair<Anchor, mat4d_t> keyValue in matMap)
Console.WriteLine($"{keyValue.Key.Name} : {keyValue.Value}");
#endregion
@@ -79,4 +79,3 @@ namespace Sample.Mech
SnapshotToFile(GetDemoAsmb());
}
}
}