# Copyright (c) 2025-2026 Gigasoft, Inc. All rights reserved. PE-POINTCOLORS -- Per-DataPoint Color and Type Control (knowledge rev 4.3) POINTCOLORS BASICS: PePlot.PointColors[subset, point] -- 2D Color array, same dimensions as PeData.Y. Must define a color for EVERY [s,p] that should be colored. Undefined entries may render invisible or black depending on RenderEngine. When PointColors is populated, it overrides SubsetColors for data rendering. SubsetColors should still be set separately for legend color swatches. Works with: bars, points, line segments, stick, stacked bar, 3D scatter points, 3D bars, 3D surface polygons (quads). Alpha channel: Color.FromArgb(0, r, g, b) produces fully transparent/hidden content on any RenderEngine (GdiPlus, Direct2D, Direct3D). Can be used to selectively hide individual data points. Non-zero alpha values create translucent blending. SELECTIVE SUBSET GATING -- SubsetForPointColors: PePlot.SubsetForPointColors[index] -- int array listing which subset indices should use PointColors. Unlisted subsets fall back to SubsetColors. If SubsetForPointColors is NOT set (empty): ALL subsets use PointColors and colors must be defined for all [s,p] positions. If set: only the listed subset indices use PointColors. Example: SubsetForPointColors[0]=0; SubsetForPointColors[1]=1; --> subsets 0,1 use PointColors; subsets 2,3+ use SubsetColors. POINTCOLORPOINTS -- What Gets Colored: PeColor.PointColorPoints (also accessible as PePlot.PointColorPoints, same DLL constant, interchangeable). Controls whether PointColors applies to point symbols, line segments, or both when PlottingMethod is PointsPlusLine. PointsAndOrLines enum: PointsAndLinesColored (0) -- color both points and lines PointsColored (1) -- color points only (default) LinesColored (2) -- color lines only Relevant only for line+point methods. For bars/pure points, PointColors always colors the rendered element. PER-DATAPOINT POINT TYPES (parallel system): PePlot.PointTypes[subset, point] -- 2D PointType array, same pattern as PointColors. PePlot.SubsetForPointTypes[index] -- gating array, same logic as SubsetForPointColors. PePlot.SubsetPointTypes[subset] -- per-SUBSET default point types (1D array). SubsetForPointColors and SubsetForPointTypes are fully independent. Can mix: some subsets use PointColors, different subsets use PointTypes, some use both, some use neither. RESOURCE BITMAP SYMBOLS (custom image point types): Standard PointType enum provides geometric shapes (Plus, Cross, Dot, Square, Diamond, Triangle, Arrow variants). For custom image symbols (PNG files), use Resource Bitmaps. Scope: Pego, Pesgo, Pepso. Usable as SubsetPointTypes, per-point PointTypes, and graph/table/legend annotation symbols. The pattern uses WorkingBitmap like WorkingAxis -- set the slot index, configure all properties for that slot, then move on. Setup pattern (repeat for each bitmap, slot 0-150): PePlot.Bitmaps.WorkingBitmap = 0; PePlot.Bitmaps.Filename = "symbol01.png"; PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.Mask; PePlot.Bitmaps.Style = ResourceBitmapStyle.SmallCentered; Assign to a subset via magic-number cast: PePlot.SubsetPointTypes[S] = (PointType)(10001 + bitmapIndex); Standard PointType enum maxes around ~99 (ArrowNW). Values >= 10001 are interpreted as bitmap resource references. Per-point form: PePlot.PointTypes[s, p] = (PointType)10001; COLORIZEMODE (ResourceBitmapColorizeMode enum): None (0) -- bitmap drawn in its native colors. Each color variant requires a separate file. Use for 3D rendered spheres or complex colored icons where recoloring would look wrong. Examples 142, 143. Mask (1) -- all visible pixels swapped to a single new color. Source bitmap is a dark/silhouette shape on transparent background; engine recolors per subset. One file -> unlimited colors. Tint (2) -- White/gray highlights preserved, the rest tinted toward the target color. Use when source artwork has shading (gradients, glints, soft 3D look) you want to keep while recoloring the hue. Mask and Tint demonstrated in examples 015 and 140. COLOR SOURCE -- where Mask/Tint pull their color from: Subset symbol (SubsetPointTypes / PointTypes) -> SubsetColors[s] (or PointColors[s,p] when populated). Graph annotation (PeAnnotation.Graph.Type) -> PeAnnotation.Graph.Color[i]. Table/legend annotation -> inherited from whatever originally registered the bitmap (graph annotation or subset). ORDERING REQUIREMENT (critical): Setting ColorizeMode pre-loads and colorizes the resource using the current color value, AND assigning the bitmap type (SubsetPointTypes / Graph.Type / etc.) re-binds color at that moment. Safest pattern: 1. Set the color source first (SubsetColors[s] or Graph.Color[i]) 2. Configure WorkingBitmap slot (Filename, ColorizeMode, Style) 3. Assign the type (SubsetPointTypes[s] / Graph.Type[i] / etc.) Skipping step 1 leaves the bitmap colorized with whatever was current, which is a common cause of "wrong color" bugs. RENDERENGINE: Set RenderEngine = Direct3D early when configuring resource bitmap features: PeConfigure.RenderEngine = RenderEngine.Direct3D; LEGACY API: PePlot.Bitmaps.Colorize (bool) still compiles but is deprecated. The old Colorize = true mapped to Mask only. New code uses ColorizeMode for access to Tint and explicit None. GRAPH ANNOTATION BITMAPS: Graph annotations can use bitmap symbols the same way subsets do. PeAnnotation.Graph.Color[i] = Color.FromArgb(...); // color FIRST PeAnnotation.Graph.Type[i] = (int)10001; // 10001 + slot index For Mask/Tint, the color source is GraphAnnotationColor[i], not SubsetColors. For None-mode bitmaps the color value is unused. TABLE AND LEGEND ANNOTATION BITMAPS: Same magic-number pattern with type-specific casts: PeAnnotation.Table.Type[r,c] = (LegendAnnotationType)10001; PeLegend.AnnotationType[i] = 10001; PeLegend.AnnotationText[i] = "Tint"; REGISTRATION PREREQUISITE: a bitmap can only be referenced from a table or legend annotation slot if the same bitmap was already "registered" earlier by either: - a graph annotation assignment (PeAnnotation.Graph.Type[i] = 10001+N), or - a SubsetPointTypes / PointTypes assignment using that bitmap. If neither is naturally in play, define a throwaway graph annotation at off-screen coordinates just to register the bitmap. Always set table and legend annotation bitmap types AFTER the graph or subset assignments that register them. Non-colorized (None-mode) table/legend annotation bitmaps do not need a color set. RESOURCEBITMAPSTYLE enum (37 values) organized as Size x Position: Sizes: ActualSize, Small, Medium, Large, DataSized Positions: Centered, N, NE, E, SE, S, SW, W, NW Examples: SmallCentered(19), MediumN(10), LargeSE(35), DataSized(39) LEGEND DISPLAY: Bitmap resource symbols appear automatically in the legend alongside subset labels, properly colorized when Mask or Tint is in use. VECTOR EXPORT LIMITATION: When bitmap resources are used, pure vector export (WMF/EMF) is not possible. Disable these options: PeUserInterface.Dialog.AllowWmfExport = false; PeUserInterface.Dialog.AllowEmfExport = false; Note: WMF is also not ideal for large datasets regardless of bitmaps. See Examples 015, 140 (Mask + Tint), 142, 143 (None / native colors). POINT SIZE CONTROL: PePlot.PointSize -- PointSize enum (Small/Medium/Large/Micro). PePlot.Option.MinimumPointSize -- MinimumPointSize enum, but accepts integer cast for exact pixel sizes: (MinimumPointSize)4 = 4 pixels minimum. PePlot.Option.MaximumPointSize -- same MinimumPointSize type, same cast trick. This extends point sizing beyond the 4 named enum values. CONTOURLEGENDII -- Secondary Color Legend for PointColors: PeLegend.ContourLegendII.* properties create a secondary gradient legend bar. NOT automatically connected to PointColors -- developer must manually sync the colors in PointColors with ContourLegendII.SubsetColors, and set the numeric range via ManualContourMin/Max. Purely a visual legend. Key properties: .ShowContourLegend = ShowContourLegendII.SecondPlusFirst | SecondOnly .ManualContourScaleControl = ManualScaleControl.MinMax .ManualContourMin / .ManualContourMax -- numeric range .ManualContourLine -- label frequency/increment .SubsetColors[i] -- color array for the legend gradient .ContourLegendTitle -- title text .ContourLegendPrecision -- decimal places FASTCOPYFROM WITH INT[] -- BGR FORMAT: When using FastCopyFrom(int[] source) to bulk-load PointColors, the native DLL expects colors in BGR order, not the standard RGB order used by System.Drawing.Color. Use the static helper to convert: Color[] myColors = { ... }; var bgr = TwoDimensionalColorArray.ColorArrayToPeColor32(myColors); Pesgo1.PeColor.PointColors.FastCopyFrom(bgr); The peColor32 type is the native DLL color format. For spoon-fed indexer assignments (PointColors[s,p] = Color.FromArgb(...)), no conversion is needed -- the .NET wrapper handles the conversion automatically. 3D SURFACE POINTCOLORS (Pe3do): PointColors[s,p] maps to individual surface grid polygons/quads. Can paint arbitrary patterns on the surface (regions, targets, zones). Color.FromArgb(0,0,0,0) creates transparent areas; combine with NullDataValue + SurfaceNullDataGaps=true for actual surface holes. After changing colors in Direct3D mode: PeFunction.Force3dxNewColors = true; PeFunction.Force3dxVerticeRebuild = true; Force3dxNewColors is for any runtime color change in Direct3D, not just initial setup (though some examples set it during init for safety). CODE PATTERNS: // Pego bar gradient ramp (example 008): Pego1.PePlot.PointColors[s, p] = Color.FromArgb(55, (byte)(15+((p+1)*20)), 0, 0); Pego1.PeColor.SubsetColors[0] = someColor; // legend still needs SubsetColors // Selective gating (example 133): Pesgo1.PePlot.SubsetForPointColors[0] = 0; // subset 0 uses PointColors Pesgo1.PePlot.SubsetForPointColors[1] = 1; // subset 1 uses PointColors // subsets 2,3 fall back to SubsetColors // Color lines not points (example 141): Pesgo1.PeColor.PointColorPoints = PointsAndOrLines.LinesColored; // 3D surface polygon coloring (example 403): Pe3do1.PePlot.PointColors[s, p] = Color.FromArgb(102, 178, 178, 0); // Mask-mode bitmap (silhouette recolored by SubsetColor) -- example 140: Pesgo1.PeColor.SubsetColors[0] = Color.Red; // color FIRST Pesgo1.PePlot.Bitmaps.WorkingBitmap = 0; Pesgo1.PePlot.Bitmaps.Filename = "symbol01.png"; Pesgo1.PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.Mask; Pesgo1.PePlot.Bitmaps.Style = ResourceBitmapStyle.SmallCentered; Pesgo1.PePlot.SubsetPointTypes[0] = (PointType)10001; // Tint-mode bitmap (shading preserved, hue retinted) -- example 140: Pesgo1.PeColor.SubsetColors[1] = Color.Green; Pesgo1.PePlot.Bitmaps.WorkingBitmap = 1; Pesgo1.PePlot.Bitmaps.Filename = "tint.png"; Pesgo1.PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.Tint; Pesgo1.PePlot.Bitmaps.Style = ResourceBitmapStyle.SmallCentered; Pesgo1.PePlot.SubsetPointTypes[1] = (PointType)10002; // None-mode bitmap (native colors, no recoloring) -- examples 142, 143: Pesgo1.PePlot.Bitmaps.WorkingBitmap = 2; Pesgo1.PePlot.Bitmaps.Filename = "symbolBlueDot.png"; Pesgo1.PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.None; Pesgo1.PePlot.Bitmaps.Style = ResourceBitmapStyle.SmallCentered; Pesgo1.PePlot.SubsetPointTypes[2] = (PointType)10003; // Graph annotation as bitmap symbol -- example 140: Pego1.PePlot.Bitmaps.WorkingBitmap = 0; Pego1.PePlot.Bitmaps.Filename = "tint.png"; Pego1.PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.Tint; Pego1.PePlot.Bitmaps.Style = ResourceBitmapStyle.LargeCentered; Pego1.PeAnnotation.Graph.Color[22] = Color.FromArgb(255, 215, 0, 215); // FIRST Pego1.PeAnnotation.Graph.Type[22] = (int)10001; Pego1.PeAnnotation.Graph.X[22] = 3.5; Pego1.PeAnnotation.Graph.Y[22] = 1390; // Table / legend annotation reusing the registered bitmap -- example 140: // (Graph annotation above already registered slot 0; now reuse.) Pego1.PeAnnotation.Table.Type[0, 1] = (LegendAnnotationType)10001; Pego1.PeLegend.AnnotationType[0] = 10001; Pego1.PeLegend.AnnotationText[0] = "Tint";