# Copyright (c) 2025-2026 Gigasoft, Inc. All rights reserved. === ProEssentials Pe3do (knowledge rev 4.1) 3D Graph Annotations === 3D graph annotations extend the 2D annotation system (see pe-graph-annotations) with Z coordinates and 3D geometric shapes. All 2D graph annotation features (text prefixes, Pointer, connected lines, text dodging) work in Pe3do with the addition of Graph.Z[i] for depth positioning. BASIC 3D ANNOTATIONS (same as 2D but with Z): Graph.X[i], Graph.Y[i], Graph.Z[i] -- position in 3D data coordinates. Standard patterns work: symbol + Pointer pairs, ThickSolidLine -> ArrowLarge, ThickSolidLine -> LineContinue polylines, StartPoly -> AddPolyPoint -> EndPolylineThick polylines. All render in 3D space. See Examples 404, 407. STATE MACHINE: AxisDirection and MajorMinorRadii are SEQUENTIAL STATE that persists across subsequent annotations until changed. They are NOT per- annotation -- set them once, and all following shapes use them until reset. AXISDIRECTION -- ORIENTATION VECTOR: Graph.Type[i] = (int)GraphAnnotationType.AxisDirection; Graph.X[i], Y[i], Z[i] = unit vector defining the shape's primary axis. Examples: (0,1,0) = Y-axis vertical, (1,0,0) = X-axis, (0,0,1) = Z-axis. For cylinders/cones: the axis the shape spans along. For 2D ellipses: the normal (face direction) of the flat disc. ALTERNATIVE ORIENTATION METHODS (priority order): 1. MajorDirection + MinorDirection -- direct low-level vectors (highest) 2. AxisDirection -- single vector, system computes perpendicular plane 3. AxisAngles -- X = horizontal rotation, Y = vertical rotation (lowest) If multiple are defined, higher priority wins. See Example 416. MAJORMINORRADII -- CROSS-SECTION SIZE: Graph.Type[i] = (int)GraphAnnotationType.MajorMinorRadii; Graph.X[i] = major radius, Graph.Y[i] = minor radius, Graph.Z[i] = ignored. These define the cross-section in the plane perpendicular to AxisDirection. Equal X,Y = circular cross-section. Unequal = elliptical. Units are DATA COORDINATES -- affected by GridAspectX/Y/Z and ManualScale. If GridAspectX != GridAspectZ, compensate radii for true visual circles. CYLINDER AND CONE ANNOTATIONS: Full pattern: AxisDirection -> MajorMinorRadii (start) -> CylinderStart -> [optional MajorMinorRadii (end)] -> Cylinder. - CylinderStart X,Y,Z = start location, Color = start color (use alpha). - Cylinder X,Y,Z = end location, Color = end color. - CONE: Use different MajorMinorRadii before CylinderStart vs Cylinder. Example: start radii (5,5) -> CylinderStart -> end radii (20,20) -> Cylinder creates a cone wider at the end. See Example 416. - For translucent shapes, use alpha < 255 in Color AND enable PeColor.DxTransparencyMode = TransparencyMode.OIT. Note: OIT does not support GeometricShaders, so use PePlot.LinesOrTubes = LinesOrTubes.AllLines (not tubes) with OIT. SPHERE ANNOTATIONS: Pattern: MajorMinorRadii -> Sphere (or SphereSmall / SphereLarge). MajorMinorRadii X,Y define the sphere's radii (equal = true sphere). Sphere X,Y,Z = center location in data coordinates. PePlot.Option.DxSphereComplexity = 2-20 (default 6) controls polygon count. BOX ANNOTATIONS: Pattern: AxisDirection -> MajorMinorRadii -> BoxStart -> Box. - BoxStart X,Y,Z = start corner, Box X,Y,Z = end corner. Color on Box. - MajorMinorRadii defines cross-section perpendicular to AxisDirection. - For 3D bar charts (PolyMode.ThreeDBar), position at bar centers: X = 1.5 + pointIndex, Z = 1.5 + subsetIndex, Y = data value. STACKING: Chain BoxStart+Box pairs. Second BoxStart.Y = first Box.Y. TOP CAP: RectFill at the top Y of a box stack caps it visually. See Example 405. 3D ELLIPSEFILL -- FLAT DISC IN 3D: Pattern: AxisDirection -> MajorMinorRadii -> EllipseFill. In 3D, EllipseFill draws a planar disc oriented perpendicular to the AxisDirection vector (NOT TopLeft+BottomRight like 2D). The face of the disc points in the AxisDirection. X,Y,Z = disc center location. See Example 416. WIREFRAME VS SOLID RENDERING MODE: Complex shapes (Sphere, Cylinder, Box) inherit their rendering mode from a sequential state determined by the last "simple" annotation type: - After a LINE type (ThinSolidLine, etc.) -> shapes render as WIREFRAME. - After a SOLID FILL type (SquareSolid, etc.) -> shapes render as SOLID. To explicitly set mode without drawing anything visible, place an invisible annotation at extreme out-of-view coordinates: // Force SOLID mode Graph.X[i] = 200000000; Graph.Y[i] = 200000000; Graph.Z[i] = 200000000; Graph.Type[i] = (int)GraphAnnotationType.SquareSolid; Graph.Color[i] = Color.FromArgb(0, 0, 0, 0); // invisible // Force WIREFRAME mode (use ThinSolidLine instead of SquareSolid) This works because the rendering pipeline carries forward the fill-mode from the last annotation regardless of position. The extreme coordinates ensure the mode-setting annotation is invisible. If you draw a visible arrow line before a shape, the shape will render wireframe unless you insert a SquareSolid mode-reset between them. See Example 416. GRAPHANNOTATION POLYDATA (second surface workaround): Pe3do supports only one surface plotting method at a time. To overlay a second independent surface or geometry layer, use GraphAnnotationPolyData. This renders annotation-layer polygons separately from the main surface. Example 415 uses this to show two surfaces: the main surface colored by WData (4th dimension moisture), and an annotation surface below showing the WData as actual topology in a simpler color scheme. COORDINATE SYSTEM: PolyData uses a normalized -10 to 10 logical space that maps to the main surface plot's data range. GridAspect multiplies this: GridAspectX = 2.5 stretches the X range to -25 to 25. To place the annotation surface in only the bottom portion, use a Y range subset like -10 to -5 (bottom quarter of the logical space). AXIS SCALING: The chart does NOT auto-scale axes to fit annotation PolyData. You must manually extend the axis to make room: PeGrid.Configure.ManualScaleControlY = ManualScaleControl.Min; PeGrid.Configure.ManualMinY = 750; // extend below main data range MECHANISM (not a normal .NET property -- requires PEvset/PEnset): PolygonData[] polys = CreatePolyData(...); PEvsetW(Pe3do1.PeSpecial.HObject, DllProperties.GraphAnnotationPolyData, polys, polys.Length); PEnset(Pe3do1.PeSpecial.HObject, 1607, 1); // enable polygon coloring Requires: Force3dxAnnotPolyDataVerticeRebuild = true (separate from Force3dxAnnotVerticeRebuild). Uses PolygonData struct same as PolyMode PolygonData. See Examples 406 (struct), 415 (dual surface). 3D-SPECIFIC ANNOTATION PROPERTIES: PeAnnotation.InFront = true/false -- controls depth priority between annotations and surface/plot data. true = annotations render in front of surface (default, good for labels). false = surface renders in front of annotations (use for highlight polygons that should appear behind/within the surface, e.g., subset highlight slices in examples 400, 407). PeAnnotation.Graph.HighLightAnnotationIndex = N -- draws a special colored highlight sphere at annotation index N. Set to -1 to clear. Useful for interactive highlighting during MouseMove or for animating a highlighted marker moving along a path of annotation coordinates (example 403). PeAnnotation.Graph.LeftJustificationOutside = true -- left-justified text always faces outside the 3D scene, preventing criss-crossing pointers. PeAnnotation.Graph.AnnotationTextFixedSize = true -- text stays same size regardless of 3D depth. False = text scales with perspective distance. PeAnnotation.Graph.SizeCntl = 1.2 -- multiplier for all annotation symbol sizes (0.8 = smaller, 1.5 = larger). PeAnnotation.Graph.AllDodging = true -- enables limited dodging for non- Pointer annotations (symbol types). AllDodgingOffset controls pixel offset. PeFunction.SetViewingAt(x, y, z) -- focus camera rotation on a specific annotation/data point in 3D space. PeColor.DxTransparencyMode = TransparencyMode.OIT -- required when using alpha < 255 on 3D shapes for correct depth-sorted transparency. FINALIZATION (always required after 3D annotation changes): Pe3do1.PeFunction.Force3dxAnnotVerticeRebuild = true; Pe3do1.PeFunction.Force3dxAnnotPolyDataVerticeRebuild = true; // if PolyData Pe3do1.PeFunction.ReinitializeResetImage(); Pe3do1.Invalidate(); Pe3do1.Refresh(); KEY EXAMPLES: 404 -- 3D Scatter: basic 3D Pointer annotations, 3D arrow lines, SetViewingAt 405 -- 3D Bar: Box annotations with stacking and top caps, 3D polyline 407 -- Waterfall: StartPoly->EndPolylineThick, SizeCntl, AnnotationTextFixedSize 415 -- 4D Surface: GraphAnnotationPolyData via PEvset, WData annotations 416 -- Complex: Cylinder, Cone, Sphere, EllipseFill, wireframe/solid toggle, OIT transparency, AxisDirection/MajorMinorRadii comprehensive demo