Rendering Hints

The Rendering Hints tutorial shows how to customize schematics components appearance.
The customization can be done either at geotoolkit/schematics/scene/WellBoreNode level or at geotoolkit/schematics/widgets/SchematicsWidget level.

To set needed hints on a "WellBoreNode" instance "setRenderingHints" method has to be called.
If a widget is used for schematics visualization then "setOptions" with "wellborenode" -> "renderinghints" specifiers is the method to call.

# Object approach

JSON-object as a parameter for 'renderinghints' property is traditional way for customizing schematics components appearance.
Every section of the JSON-object must be named the same way as the component's name to customize.
Since the approach is dependent on specific component's implementation, it can not be used for arbitrary kind of a component.

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { WellBoreData } from "@int/geotoolkit/schematics/data/WellBoreData.ts";
import { CompositeSchematicsWidget } from "@int/geotoolkit/schematics/widgets/CompositeSchematicsWidget.ts";
import data from "/src/assets/data/wellBoreData.json?import";
function createScene(canvas) {
  function createWellBoreData() {
    return new WellBoreData(data);
  }
  const widget = new CompositeSchematicsWidget({
    "annotationssizes": {
      "south": 0
    },
    "gap": {
      "left": {
        "size": "30"
      },
      "right": {
        "visible": false
      }
    },
    "data": {
      "elements": createWellBoreData()
    }
  });
  widget.setOptions({
    "wellborenode": {
      "renderinghints": {
        "perforation": {
          "height": 15,
          "cutoff": true,
          "fillstyle": "#326b99"
        },
        "casing": {
          "shoe": {
            "fillstyle": "red"
          }
        }
      }
    }
  });
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Custom "RenderingHints" class implementation

Using geotoolkit/schematics/utils/RenderingHints concept is the way to customize appearance of vurtially any kind of schematics component.
The new (starting with GeoToolkit 3.3) approach is of a great importance especially when SVG-based schematics components is utilized.

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { WellBoreData } from "@int/geotoolkit/schematics/data/WellBoreData.ts";
import { ComponentNodeFactoryRegistry } from "@int/geotoolkit/schematics/factory/ComponentNodeFactoryRegistry.ts";
import { CompositeSchematicsWidget } from "@int/geotoolkit/schematics/widgets/CompositeSchematicsWidget.ts";
import { CustomRenderingHints } from "/src/code/Schematics/RenderingHints/customRenderingHints.ts";
import { LabelsFilter } from "@int/geotoolkit/schematics/labeling/LabelsFilter.ts";
import { obfuscate } from "@int/geotoolkit/lib.js";
import { ComponentUtils } from "@int/geotoolkit/schematics/utils/ComponentUtils.ts";
import data from "/src/assets/data/wellBoreData.json?import";
let hintsAll, hintsWellArchitecture, hintsWellCompletion;
let currentMode;
function showAll(widget) {
  currentMode = hintsAll;
  widget.setOptions({
    "wellborenode": {
      "renderinghints": {
        "*": hintsAll
      }
    }
  });
}
function showWellArchitecture(widget) {
  currentMode = hintsWellArchitecture;
  widget.setOptions({
    "wellborenode": {
      "renderinghints": {
        "*": hintsWellArchitecture
      }
    }
  });
}
function showWellCompletion(widget) {
  currentMode = hintsWellCompletion;
  widget.setOptions({
    "wellborenode": {
      "renderinghints": {
        "*": hintsWellCompletion
      }
    }
  });
}
export class CustomLabelsFilter extends LabelsFilter {
  constructor() {
    super();
  }
  labelInfo(componentNode) {
    if (!currentMode || !currentMode.isActiveComponent(componentNode))
      return null;
    let txt;
    if (componentNode.getName() === "perforation") {
      const geom = componentNode.getGeometryData();
      txt = "perforation (" + ComponentUtils.getDepthFrom(geom) + " - " + ComponentUtils.getDepthTo(geom) + ")";
    } else {
      txt = componentNode.getDescription();
    }
    if (!txt)
      return null;
    return " " + txt + " ";
  }
}
obfuscate(CustomLabelsFilter);
function createScene(canvas) {
  function createWellBoreData() {
    return new WellBoreData(data);
  }
  const registry = new ComponentNodeFactoryRegistry();
  const aliases = registry.getAliases();
  hintsAll = new CustomRenderingHints("All", aliases);
  hintsWellArchitecture = new CustomRenderingHints("WellArchitecture", aliases);
  hintsWellCompletion = new CustomRenderingHints("WellCompletion", aliases);
  const options = {
    "registry": registry,
    "labeling": {
      "labelsfilter": new CustomLabelsFilter()
    },
    "data": {
      "elements": createWellBoreData()
    },
    "annotationssizes": {
      "south": 0
    },
    "gap": {
      "left": {
        "size": "30"
      },
      "right": {
        "visible": false
      }
    }
  };
  return new Plot({
    "canvaselement": canvas,
    "root": new CompositeSchematicsWidget(options)
  });
}
export { createScene, showAll, showWellArchitecture, showWellCompletion };

createScene(document.querySelector('[ref="plot"]'));

# Using built-in "StylesRenderingHints" class

Using geotoolkit/schematics/utils/StylesRenderingHints helps user easily customize schematics components rendering via fine tune-up of any component's underlying shape's fill and line styles.

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { LineStyle } from "@int/geotoolkit/attributes/LineStyle.ts";
import { WellBoreData } from "@int/geotoolkit/schematics/data/WellBoreData.ts";
import { ComponentNode } from "@int/geotoolkit/schematics/scene/ComponentNode.ts";
import { StyleUtils } from "@int/geotoolkit/schematics/utils/StyleUtils.ts";
import { StylesRenderingHints } from "@int/geotoolkit/schematics/utils/StylesRenderingHints.ts";
import { CompositeSchematicsWidget } from "@int/geotoolkit/schematics/widgets/CompositeSchematicsWidget.ts";
import data from "/src/assets/data/wellBoreData.json?import";
function createScene(canvas) {
  function createWellBoreData() {
    return new WellBoreData(data);
  }
  const widget = new CompositeSchematicsWidget({
    "data": {
      "elements": createWellBoreData()
    },
    "annotationssizes": {
      "south": 0
    }
  });
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
}
function setGreyScale(widget) {
  widget.setOptions({
    "wellborenode": {
      "renderinghints": {
        "perforation": {
          "height": 15,
          "cutoff": true,
          "fillstyle": "rgb(96, 96, 96)"
        },
        "casing": {
          "inner": {
            "fillstyle": null
          },
          "outer": {
            "fillstyle": "black",
            "linestyle": "black"
          },
          "shoe": {
            "fillstyle": "black"
          }
        },
        "*": new StylesRenderingHints({
          "getfillstyle": (args) => StyleUtils.getGrayScaleFillStyle(args["shape"].getFillStyle()),
          "getlinestyle": (args) => StyleUtils.getGrayScaleLineStyle(args["shape"].getLineStyle())
        })
      }
    },
    "gap": {
      "left": {
        "size": "30"
      },
      "right": {
        "visible": false
      }
    }
  });
}
function setOutline(widget) {
  const myNullLineStyle = new LineStyle("gray");
  widget.setOptions({
    "wellborenode": {
      "renderinghints": {
        "perforation": {
          "height": 15,
          "cutoff": true,
          "fillstyle": "rgb(96, 96, 96)"
        },
        "casing": {
          "inner": {
            "fillstyle": null
          },
          "outer": {
            "fillstyle": "black",
            "linestyle": "black"
          },
          "shoe": {
            "fillstyle": "black"
          }
        },
        "*": new StylesRenderingHints({
          "filternode": (node) => {
            if (node instanceof ComponentNode)
              return false;
            if (node instanceof Group)
              return false;
            return true;
          },
          "getfillstyle": (args) => null,
          "getlinestyle": (args) => {
            const dstLineStyle = StyleUtils.getGrayScaleLineStyle(args["shape"].getLineStyle());
            return dstLineStyle ? dstLineStyle : myNullLineStyle;
          }
        })
      }
    }
  });
}
export { createScene, setGreyScale, setOutline };

createScene(document.querySelector('[ref="plot"]'));