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>
This commit is contained in:
@@ -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(Box3d dst)
|
||||
{
|
||||
//Console.WriteLine($"dst.A: {dst}");
|
||||
LocalProjectService?.MachiningEquipment?.GetAsmb()?.ExpandToBox3d(dst,
|
||||
GetAnchor(),
|
||||
GetAnchoredDisplayeeList().ToArray());
|
||||
//Console.WriteLine($"dst.B: {dst}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user