diff --git a/Disp/DemoCylindroid.cs b/Disp/DemoCylindroid.cs new file mode 100644 index 0000000..8d843b3 --- /dev/null +++ b/Disp/DemoCylindroid.cs @@ -0,0 +1,53 @@ +using Hi.Disp; +using Hi.Geom; +using System; + +namespace Sample.Disp +{ + /// + /// Demonstrates the creation and visualization of objects. + /// Includes examples of building a programmatically with + /// points and serializing/deserializing via XML. + /// + /// + /// ### Source Code + /// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoCylindroid.cs)] + /// + 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(); + } + } +} diff --git a/Disp/DemoDiscreteRgb.cs b/Disp/DemoDiscreteRgb.cs new file mode 100644 index 0000000..7ed8b02 --- /dev/null +++ b/Disp/DemoDiscreteRgb.cs @@ -0,0 +1,45 @@ +using Hi.Disp; +using Hi.Disp.Flag; +using Hi.Geom; +using Hi.Coloring; + +namespace Sample.Disp +{ + /// + /// Demonstrates the use of discrete RGB colors for rendering multiple objects. + /// Shows how to apply different colors to similar geometric shapes using the + /// method from class. + /// + /// + /// ### Source Code + /// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoDiscreteRgb.cs)] + /// + public class DemoDiscreteRgb : IDisplayee + { + /// + public void Display(Bind bind) + { + bind.Rgb = ColorUtil.GetDiscreteRGB_Env(); + new Box3d(0, 0, 0, 1, 1, 1).ToDraw_Face().Display(bind); + + bind.Rgb = ColorUtil.GetDiscreteRGB_Env(); + new Box3d(1, 0, 0, 2, 1, 1).ToDraw_Face().Display(bind); + + bind.Rgb = ColorUtil.GetDiscreteRGB_Env(); + new Box3d(2, 0, 0, 3, 1, 1).ToDraw_Face().Display(bind); + } + /// + public void ExpandToBox3d(Box3d dst) + { + dst.Expand(new Vec3d(0, 0, 0)); + dst.Expand(new Vec3d(3, 1, 1)); + } + + static void Main() + { + DemoUtil.Present("Demo Discrete I", + new DispList(new CoordinateDrawing(), new DemoDiscreteRgb())); + } + + } +} diff --git a/Disp/DemoDrawing.cs b/Disp/DemoDrawing.cs new file mode 100644 index 0000000..e2f1f34 --- /dev/null +++ b/Disp/DemoDrawing.cs @@ -0,0 +1,201 @@ +using Hi.Geom; +using Hi.Disp; +using System.Collections.Generic; +using Hi.Disp.Treat; +using Hi.Coloring; + +namespace Sample.Disp +{ + /// + /// 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. + /// + /// + /// ### Source Code + /// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoDrawing.cs)] + /// + public static class DemoDrawing + { + /// + /// Demonstrates simple line drawing using raw vertex coordinates. + /// Creates a basic line strip from three vertices and displays it using DemoUtil. + /// + 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 + } + + /// + /// 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. + /// + public static void DrawLines() + { + List ps; + double[] vs; + int n = 10; //vertex num + + ////create drawPoints + ps = new List(n); + for (int i = 0; i < n; i++) + ps.Add(new Vec3d(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)); + } + + /// + /// 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. + /// + 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 rgb = ColorUtil.GetDiscreteRgb(i); + Tri3d tri = new Tri3d(new Vec3d(i, 0, 0), new Vec3d(i + 1, 0, 0), new Vec3d(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.ps[j].x; + vs[k++] = tri.ps[j].y; + vs[k++] = tri.ps[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 rgb = ColorUtil.GetDiscreteRgb(i); + Tri3d tri = new Tri3d(new Vec3d(i, 0, 3), new Vec3d(i + 1, 0, 3), new Vec3d(i + 0.5, 0, 4)); + Vec3d 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.ps[j].x; + vs[k++] = tri.ps[j].y; + vs[k++] = tri.ps[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)); + } + + /// + /// Demonstrates drawing 3D triangles using the Tri3d 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. + /// + public static void DrawTri3d() + { + int n = 10; + List tris = new List(n); + for (int i = 0; i < n; i++) + tris.Add(new Tri3d(new Vec3d(i, 0, 0), new Vec3d(i + 1, 0, 0), new Vec3d(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(); + } + } +} diff --git a/Disp/DemoPick1.cs b/Disp/DemoPick1.cs new file mode 100644 index 0000000..daa5789 --- /dev/null +++ b/Disp/DemoPick1.cs @@ -0,0 +1,52 @@ +using Hi.Geom; +using Hi.Disp; +using Hi.Native; + +namespace Sample.Disp +{ + /// + /// 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. + /// + /// + /// ### Source Code + /// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoPick1.cs)] + /// + public class DemoPick1 : Pickable, IDisplayee + { + bool isMouseOver = false; + /// + public void Display(Bind bind) + { + bind.PickID = PickingID; + bind.Rgb = new Vec3d(isMouseOver ? 0 : 1, 1, 1); + new Box3d(0, 0, 0, 1, 1, 1).DisplayFace(bind); + bind.PickID = 0; + } + /// + public void ExpandToBox3d(Box3d dst) + { + dst.Expand(new Vec3d(0, 0, 0)); + dst.Expand(new Vec3d(1, 1, 1)); + } + /// + public override void OnMouseEnter(ui_event_type e, DispEngine dispEngine) + { + isMouseOver = true; + } + /// + public override void OnMouseLeave(ui_event_type e, DispEngine dispEngine) + { + isMouseOver = false; + } + /// + /// Entry point for the DemoPick1 example. + /// Creates and displays a simple pickable object that changes color on mouse hover. + /// + static void Main() + { + DemoUtil.Present("DemoPick1", new DemoPick1()); + } + } +} diff --git a/Disp/DemoPick2.cs b/Disp/DemoPick2.cs new file mode 100644 index 0000000..f969a8d --- /dev/null +++ b/Disp/DemoPick2.cs @@ -0,0 +1,78 @@ +using Hi.Geom; +using Hi.Disp; +using System; +using Hi.Coloring; + +namespace Sample.Disp +{ + /// + /// 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. + /// + /// + /// ### Source Code + /// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoPick2.cs)] + /// + 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" }; + /// + public void Display(Bind bind) + { + bind.PickID = pickableA.PickingID; + bind.Rgb = ColorUtil.GetDiscreteRgb(1); + new Box3d(0, 0, 0, 1, 1, 1).DisplayFace(bind); + + bind.PickID = pickableB.PickingID; + bind.Rgb = ColorUtil.GetDiscreteRgb(2); + new Box3d(0, 0, 1, 1, 1, 2).DisplayFace(bind); + + bind.PickID = pickableC.PickingID; + bind.Rgb = ColorUtil.GetDiscreteRgb(3); + new Box3d(0, 0, 2, 1, 1, 3).DisplayFace(bind); + + bind.PickID = 0; + } + /// + public void ExpandToBox3d(Box3d dst) + { + dst.Expand(new Vec3d(0, 0, 0)); + dst.Expand(new Vec3d(1, 1, 3)); + } + #region IDisposable Support + private bool disposedValue = false; // To detect redundant calls + /// + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + pickableA.Dispose(); + pickableB.Dispose(); + pickableC.Dispose(); + } + disposedValue = true; + } + } + /// + public void Dispose() + { + Dispose(true); + } + #endregion + + /// + /// 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. + /// + static void Main() + { + DemoUtil.Present("DemoPick2", new DemoPick2()); + } + } +} diff --git a/Disp/DemoPickable.cs b/Disp/DemoPickable.cs new file mode 100644 index 0000000..8f70df4 --- /dev/null +++ b/Disp/DemoPickable.cs @@ -0,0 +1,58 @@ +using Hi.Disp; +using Hi.Geom; +using System; + +namespace Sample.Disp; + +/// +/// 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. +/// +/// +/// ### Source Code +/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoPickable.cs)] +/// +public class DemoPickable : IDisplayee +{ + private readonly Drawing draw; + private readonly ShowEventPickable pickable; + + /// + /// Initializes a new instance of DemoPickable. + /// Creates a pickable triangle with a specific picking ID for user interaction. + /// + 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); + } + /// + public void Display(Bind bind) + { + draw.Display(bind); + } + /// + public void ExpandToBox3d(Box3d dst) + { + draw.ExpandToBox3d(dst); + } + + /// + /// 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. + /// + [STAThread] + public static void Main() + { + DemoUtil.Present("DemoPickable", new DemoPickable()); + } +} diff --git a/Disp/DemoSatellite.cs b/Disp/DemoSatellite.cs new file mode 100644 index 0000000..e72b7a1 --- /dev/null +++ b/Disp/DemoSatellite.cs @@ -0,0 +1,55 @@ +using Hi.Geom; +using Hi.Disp; + +namespace Sample.Disp +{ + /// + /// Demonstrates a simple solar system animation using interface. + /// Shows how to create a hierarchical transform structure with sun, earth and moon using + /// matrices and model matrix stack transformations. + /// + /// + /// ### Source Code + /// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoSatellite.cs)] + /// + public class DemoSatellite : IDisplayee + { + Drawing sun; + Drawing earth; + Drawing moon; + double angle_earth; + double angle_moon; + DemoSatellite() + { + sun = Box3d.CenterUnitBox.ScaleFromCenter(4).ToDraw_Face(); + earth = Box3d.CenterUnitBox.ScaleFromCenter(2).ToDraw_Face(); + moon = Box3d.CenterUnitBox.ToDraw_Face(); + } + /// + public void Display(Bind bind) + { + sun.Display(bind); + bind.ModelMatStack.Push(); + bind.ModelMatStack.Mul(new Mat4d(new AxisAngle4d(new Vec3d(0, 0, 1), angle_earth += 0.03))); + bind.ModelMatStack.Mul(new Mat4d(new Vec3d(12, 0, 0))); + earth.Display(bind); + bind.ModelMatStack.Push(); + bind.ModelMatStack.Mul(new Mat4d(new AxisAngle4d(new Vec3d(0, 0, 1), angle_moon += 0.02))); + bind.ModelMatStack.Mul(new Mat4d(new Vec3d(4, 0, 0))); + moon.Display(bind); + bind.ModelMatStack.Pop(); + bind.ModelMatStack.Pop(); + } + /// + public void ExpandToBox3d(Box3d dst) + { + dst.Expand(new Vec3d(-14, -14, -2)); + dst.Expand(new Vec3d(14, 14, 2)); + } + + static void Main() + { + DemoUtil.Present("DemoSatellite", new DemoSatellite()); + } + } +} diff --git a/Disp/DemoUtil.cs b/Disp/DemoUtil.cs new file mode 100644 index 0000000..46c23c4 --- /dev/null +++ b/Disp/DemoUtil.cs @@ -0,0 +1,45 @@ +using Hi.Disp; +using Hi.Geom; +using Hi.HiNcKits; +using Microsoft.Extensions.Logging; +using System; + +namespace Sample.Disp; + +/// +/// Runs a display sample to the point where its 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. +/// +/// +/// ### Source Code +/// [!code-csharp[SampleCode](~/../Hi.Sample/Disp/DemoUtil.cs)] +/// +public static class DemoUtil +{ + /// + /// Initializes the application, reports the displayee's extent, and shuts down again — + /// the headless equivalent of opening a window on it. + /// + /// A name for the sample, used in the console output. + /// The object a rendering canvas would display. + 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 box = new Box3d(); + displayee.ExpandToBox3d(box); + Console.WriteLine($"{title}: {displayee.GetType().Name} bounding {box}"); + Console.WriteLine("Assign it to your canvas' DispEngine.Displayee to see it."); + } + finally + { + LocalApp.AppEnd(); + } + } +} diff --git a/Disp/HeidenhainCoordinateEntryDisplayee.cs b/Disp/HeidenhainCoordinateEntryDisplayee.cs new file mode 100644 index 0000000..7e747b1 --- /dev/null +++ b/Disp/HeidenhainCoordinateEntryDisplayee.cs @@ -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 +{ + /// + /// Displayee for Heidenhain coordinate entry visualization. + /// + public class HeidenhainCoordinateEntryDisplayee : IAnchoredDisplayee + { + /// + /// Gets or sets whether to show Heidenhain datum preset information. + /// + public bool ShowHeidenhainDatumPreset { get; set; } = true; + /// + /// Gets or sets whether to show Heidenhain datum shift information. + /// + public bool ShowHeidenhainDatumShift { get; set; } = true; + /// + /// Gets or sets the function that provides the NcEnv instance. + /// + public Func NcEnvFunc { get; set; } + /// + /// Gets or sets the function that provides the machining equipment. + /// + public Func MillingEquipmentFunc { get; set; } + HardNcEnv NcEnv => NcEnvFunc?.Invoke(); + /// + /// Gets or sets the Heidenhain Cycle Def 247 Q339 value. + /// + public int HeidenhainCycleDef247Q339 { get; set; } + /// + /// Gets or sets the Heidenhain Cycle Def 7 arguments. + /// + public HeidenhainCycleDef7Arg HeidenhainCycleDef7Arg { get; set; } + + /// + /// Initializes a new instance. + /// + /// The function that provides the NcEnv instance. + /// The function that provides the machining equipment. + public HeidenhainCoordinateEntryDisplayee(Func ncEnvFunc, Func millingEquipmentSource) + { + NcEnvFunc = ncEnvFunc; + MillingEquipmentFunc = millingEquipmentSource; + } + /// + public void Display(Bind bind) + { + HardNcEnv ncEnv = NcEnv; + if (ncEnv == null || NcEnv.CncBrand != CncBrand.Heidenhain) + return; + + ////Console.WriteLine($"B: {CoordinateIndex}; {coordinateMove}"); + Vec3d mcXyz_AttacherAtTableBuckleZero = MillingEquipmentFunc?.Invoke() + ?.GetMachinePositionAtTableBuckleZero(); + if (mcXyz_AttacherAtTableBuckleZero == null) + return; + + Vec3d 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_AttacherAtTableBuckleZero); + CoordinateDrawing.Display(bind, text); + bind.ModelMatStack.Pop(); + } + /// + public void ExpandToBox3d(Box3d dst) + { + HardNcEnv ncEnv = NcEnv; + if (ncEnv == null || NcEnv.CncBrand != CncBrand.Heidenhain) + return; + + Vec3d mcXyz_AttacherAtTableBuckleZero = MillingEquipmentFunc?.Invoke() + ?.GetMachinePositionAtTableBuckleZero(); + if (mcXyz_AttacherAtTableBuckleZero == null) + return; + Vec3d coordinateMove; + if (HeidenhainCycleDef247Q339 == 0 && HeidenhainCycleDef7Arg == null) + return; + coordinateMove = NcFlagUtil.GetHeidenhainCoordinateOffset( + HeidenhainCycleDef247Q339, HeidenhainCycleDef7Arg, ncEnv); + + + dst.Expand(-mcXyz_AttacherAtTableBuckleZero + coordinateMove); + } + /// + public Anchor GetAnchor() + { + return MillingEquipmentFunc?.Invoke()?.GetMachiningChain() + ?.GetTableBuckle()?.GetAnchor(); + } + } +} diff --git a/Disp/IsoCoordinateEntryDisplayee.cs b/Disp/IsoCoordinateEntryDisplayee.cs new file mode 100644 index 0000000..b1d6bf4 --- /dev/null +++ b/Disp/IsoCoordinateEntryDisplayee.cs @@ -0,0 +1,90 @@ +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; + +/// +/// Displayee for ISO coordinate entry visualization. +/// +public class IsoCoordinateEntryDisplayee : IAnchoredDisplayee +{ + /// + /// Gets or sets the ISO coordinate key (e.g. "G54", "G59.2"). + /// + public string IsoCoordinateId { get; set; } = "G54"; + /// + /// Gets or sets the function that provides the NcEnv instance. + /// + public Func NcEnvFunc { get; set; } + + /// + /// Gets or sets the function that provides the machining equipment. + /// + public Func MillingEquipmentFunc { get; set; } + HardNcEnv NcEnv => NcEnvFunc?.Invoke(); + /// + /// Initializes a new instance of the class. + /// + /// The function that provides the NcEnv instance. + /// The function that provides the machining equipment. + public IsoCoordinateEntryDisplayee(Func ncEnvFunc, + Func millingEquipmentSource) + { + NcEnvFunc = ncEnvFunc; + MillingEquipmentFunc = millingEquipmentSource; + } + /// + public void Display(Bind bind) + { + HardNcEnv ncEnv = NcEnv; + if (ncEnv == null) + return; + + Vec3d coordinateMove; + string text; + + if (ncEnv.IsoCoordinateTable?.TryGetValue( + IsoCoordinateId, out coordinateMove) != true + || coordinateMove == null) + return; + if (coordinateMove == null) + return; + text = IsoCoordinateId ?? ""; + + Vec3d attacherPos = MillingEquipmentFunc?.Invoke() + ?.GetIsoCoordinatePosition(coordinateMove); + + bind.ModelMatStack.Push(); + bind.ModelMatStack.Trans(attacherPos); + CoordinateDrawing.Display(bind, text); + bind.ModelMatStack.Pop(); + } + /// + public void ExpandToBox3d(Box3d dst) + { + HardNcEnv ncEnv = NcEnv; + if (ncEnv == null) + return; + Vec3d coordinateMove; + if (ncEnv.IsoCoordinateTable?.TryGetValue(IsoCoordinateId, out coordinateMove) != true + || coordinateMove == null) + return; + + Vec3d attacherPos = MillingEquipmentFunc?.Invoke() + ?.GetIsoCoordinatePosition(coordinateMove); + if (attacherPos == null) + return; + dst.Expand(attacherPos); + } + /// + /// Table Buckle if existed; otherwise, return null. + public Anchor GetAnchor() + { + return MillingEquipmentFunc?.Invoke()?.GetMachiningChain()?.GetAnchor(); + } +} diff --git a/Disp/MachiningProjectDisplayee.cs b/Disp/MachiningProjectDisplayee.cs new file mode 100644 index 0000000..a5805a2 --- /dev/null +++ b/Disp/MachiningProjectDisplayee.cs @@ -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; + +/// +/// Represents a displayable wrapper for a machining project. +/// +public class MachiningProjectDisplayee : IDisplayee, IGetAnchor +{ + /// + /// Gets the current milling course from the host function. + /// + public MachiningProject MachiningProject => LocalProjectService.MachiningProject; + /// + /// Gets or sets the function that provides the machining project. + /// + public LocalProjectService LocalProjectService { get; set; } + + ///// + ///// Initializes a new instance of the class. + ///// + ///// The machining project to display. + ///// The bit array controlling rendering flags. + //public MachiningProjectDisplayee(MachiningProject machiningProject, + // BitArray renderingFlagBitArray) + // { + // RenderingFlagBitArray = renderingFlagBitArray; + // } + + /// + /// Initializes a new instance of the class with default rendering flags. + /// + public MachiningProjectDisplayee(LocalProjectService localProjectService) + { LocalProjectService = localProjectService; } + + /// + /// Gets or sets the bit array that controls which elements are rendered. + /// + public BitArray RenderingFlagBitArray { get; set; } = new BitArray(EnumUtil.GetEnumBitArrayCap()) + { + [(int)RenderingFlag.DimensionBar] = true, + [(int)RenderingFlag.WorkpieceGeom] = true, + [(int)RenderingFlag.Fixture] = true, + [(int)RenderingFlag.ClStrip] = true, + //[(int)RenderingFlag.Mech] = true, + }; + IsoCoordinateEntryDisplayee isoCoordinateEntryDisplayee; + /// + /// Gets the ISO coordinate entry displayee for ISO-based coordinate systems. + /// + public IsoCoordinateEntryDisplayee IsoCoordinateEntryDisplayee => + isoCoordinateEntryDisplayee ??= new IsoCoordinateEntryDisplayee( + () => MachiningProject.NcEnv, + () => LocalProjectService.MachiningEquipment); + HeidenhainCoordinateEntryDisplayee heidenhainCoordinateEntryDisplayee; + /// + /// Gets the Heidenhain coordinate entry displayee for Heidenhain-based coordinate systems. + /// + public HeidenhainCoordinateEntryDisplayee HeidenhainCoordinateEntryDisplayee => + heidenhainCoordinateEntryDisplayee ??= new HeidenhainCoordinateEntryDisplayee( + () => MachiningProject.NcEnv, + () => LocalProjectService.MachiningEquipment); + + /// + /// Gets a list of anchored displayees based on current rendering flags. + /// + /// A list of anchored displayees for rendering + List GetAnchoredDisplayeeList() + { + List dst = new List(); + 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 machAncDisplayees = + machiningEquipment.GetAnchoredDisplayeeList() ?? []; + HashSet 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; + } + /// + /// Gets the root anchor for the display hierarchy based on current rendering flags. + /// + /// The root anchor to use for rendering + 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; + } + /// + public Anchor GetAnchor() => GetRootAnchor(LocalProjectService, RenderingFlagBitArray); + /// + 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(); + } + /// + public void ExpandToBox3d(Box3d dst) + { + //Console.WriteLine($"dst.A: {dst}"); + LocalProjectService?.MachiningEquipment?.GetAsmb()?.ExpandToBox3d(dst, + GetAnchor(), + GetAnchoredDisplayeeList().ToArray()); + //Console.WriteLine($"dst.B: {dst}"); + } +}