OHL-Design, the line application#
OHL-Design (the program ohl-design, formerly ols-cad), the line application of OpenOHL — sag-tension, clearances, line layout — opens a line file or a project and shows it in dockable views that share the selection and the weather case.
Your settings, the files opened recently and the plugins installed for you stay where they were before the project was renamed: the application's data folder still carries the name "OLS CAD" (the structure application's: "OLS Structure"), so nothing is lost. The old program name ols-cad still starts ohl-design for a while (it says so on the terminal).
cargo run --release -p ohl-app -- examples/synthetic-line/synthetic-line.ohl.json \
--terrain examples/synthetic-line/synthetic-survey.csv \
--weather examples/synthetic-line/weather-cases.ohlwc
cargo run --release -p ohl-app -- project.ohl # with the project's point cloud
cargo run --release -p ohl-app # the start page: File › New project, Open
On macOS, double-click Start OHL-Design.command at the top of the source tree: it builds and starts the app on its start page (new project, open, the files opened recently). New to OpenOHL? The start page offers New project from the starter template… and Open the example (copy)…, and Help › Start from scratch will open the tutorial, which is not written yet (the entry is greyed out until it is; see Starting from nothing). Libraries given on the command line apply to the file given there only; files opened from the File menu use their own (a project's are kept in it).
| Option | Meaning |
|---|---|
--library |
Wire library (file or directory); default: the *.ohlw files next to the model, else libraries/cables. |
--structures |
Pylon files; default: the Structures/ folder next to the model. |
--insulators |
Insulator library directory. |
--weather |
Weather cases (.ohlwc); default: still air at 15 °C. All cases are solved. |
--terrain |
Survey points for the ground. |
--pointcloud |
Point cloud in a project (FILE.ohl or FILE.ohl#name) or a COPC file (FILE.copc.laz, streamed by node, see Point budget); default: the project's own. |
--points |
About how many LiDAR points are shown (default 2 000 000). Points of every class of the whole cloud are shown, ground classes and noise included: a class of up to 20 000 points whole, the larger classes thinned alike to the budget. The ground surface is built from all points of the ground classes (lowest per 1 m cell) in the corridor. |
--corridor |
Half width of the corridor around the spans the ground surface is built in (default 60 m). |
--user |
The user editing the project (default: the login name), see Editing. |
--rules |
Clearance rules (.ohlr) for the Clearances tab; default: the only .ohlr of the project (next to a line file). |
--load-cases |
Load cases (.ohllc) for the structure loads; default: the project's own, else the first .ohllc next to the file. |
--class-scheme |
LiDAR class scheme (.ohlc: class names, roles, colours) used instead of the point cloud's own. |
--controls |
Navigation scheme: orbit or minecraft (default: the one used last). |
--screenshot FILE.png (--focus ID, --distance M) |
Load, render the 3D view to an image and exit (with --focus, looking at that structure's first wire point, from --distance, default 250 m). |
Menus, quick bar and pages#
The menu bar holds what needs no view:
| Menu | (no heading) |
|---|---|
| File | the file open (its path); New project… (⌘N / Ctrl+N: what it starts from — an Empty project or the Starter template (for learning) —, the line's name, its coordinate system — local coordinates (metres, no geographic reference) or one from the searchable EPSG list (by code or name), a proj4 string or a .prj file, checked and named before it is created —, units SI; then where to save the .ohl file; you are its admin. An empty project has an empty line and libraries of its own, empty — wire library, structure types, insulators — unless library files lie next to it or are given at start (--library…): add files from the library pages (Browse…, which starts at the examples shipped with OpenOHL while a library is empty); the starter template's are described in Starting from nothing), New project from the starter template… (the same window, the starter chosen), Open the example (copy)… (a copy of examples/synthetic-line in a folder you choose, opened with its ground and weather cases), Open… (⌘O / Ctrl+O: a project .ohl or a line file .ohl.json), Open recent, New project from another program… (a project plugin's format, see Projects from other programs), Join a server…; the start page also has Plugins… (the plugin manager, to install or update a project plugin before creating the project with it); for the file open: Save all (⌘S / Ctrl+S); every import and export: Import › Into the line… (the built-in formats and those of the plugins turned on — see Import and export; one command, undoable), LiDAR points (LAS/LAZ)… (files or a folder into the project's point cloud or a new one — coordinate system, chunk size, class scheme — in the background with a progress bar; the project is opened again to show them; see Point clouds), Terrain surface (TIN)… (opens Terrain surfaces, where it is imported); Export › The line…, Drawings… (plan and profile sheets and profile exports as SVG, DXF, PDF, PNG, CSV, XML, in the background — see Drawings and profile exports), LiDAR points (LAS/LAZ)… (every class or the classes shown, the whole survey or around the line; LAS 1.4 / LAZ with the class scheme next to it), Terrain surfaces (TIN)…, Libraries…; Bill of materials › Cables… (the wire lengths of each cable and their stringing, priced with a cost file — see Bill of materials; structures, insulators and hardware are not built yet); Host this project… (with the web client if ticked) / Leave the server / Stop hosting (see Server mode), Close (the project is written through; back to the start page), Quit. Opening or closing with library pages not saved or table changes not applied asks first |
| Edit | Undo, Redo, Delete selected, Clear selection, Go to structure… (G); Snap: what can be clicked |
| View | Fit views; the pages to show (tick to open, untick to close): Next steps (see Starting from nothing), 3D, Plan, Profile, Properties, Clearances and People (who works on the project, see Server mode); Advanced › Model (the model's numbers) and Level of detail (the levels of every layer and the LiDAR point budget, see Level of detail); Work on route (see Routes and alignments); Display weather cases… (the cases drawn); Profile aspect ratio (stations : heights in the profile view — fitted to what is shown, or 1:1, 1:2, 1:5, 1:10, 1:20, 1:50 or one of your own — tick "1:" or type in its field, any value, also one of the list's; kept when zooming; yours only); Layers (the only place where a layer is shown or hidden: ground, other surfaces, LiDAR points, alignments, structures, wires, …); Customize the quick bar… |
| Terrain | Routes, Alignments and Alignment points (tables, see Routes and alignments); (What you show — the ground surface, others shown, LiDAR classes hidden, the share of points — is yours: remembered on this computer for each project, never written to the project nor sent to a server.) Terrain surfaces (TIN)… (the surfaces kept in the project: import, build from LiDAR, the active one = the ground, others shown in their colour, export, delete — see Terrain surfaces); Backgrounds: Import orthophotos…, Import DXF drawing…, Remove backgrounds…, and ticks for the orthophotos (plan view) and drawings (plan and 3D), each layer and drawing on its own (see Backgrounds); Coordinate system: Define…, Coordinate system calculator…, Reproject project… (see Coordinate systems); Survey data (imported and exported from File): Survey data display options… — a window that stays open: every LiDAR class of the point cloud with its points, in a list that scrolls; a click shows or hides a class, press and drag up or down to give every class passed the same state; All, None, Invert, by kind (ground, vegetation, buildings, wires and structures, traffic, noise), a filter by name or role; Points shown near the camera, 0.1–100 % of the survey (default 25 %) — farther away the Level of detail table's shares and render distance reduce them; changes wait for Apply (the points are read again once; Revert goes back to what is shown, closing the window drops what is not applied); a hidden class is neither drawn nor clicked; noise is drawn magenta; Class colours… — every class of the point cloud (number, name, roles, points) with its display colour: pick one per class (↺: back to the colour of its roles); the colours and names come from a class scheme file (.ohlc, with color = "#rrggbb" per class): Open a scheme…, Save, Save as…, Use for every project, Back to the cloud's own — your choice, remembered on this computer (ohl-design --class-scheme FILE gives one at start); a new import stores it with the point cloud |
| Structures | libraries: the structure library (every structure the model uses, each a file to import or export), insulators (see Library editors); tables: structures, strings, string library (see Tables); Display options — labels in the plan and 3D views, ticked for each: the structures' ids, their structure points, the strings' library labels ([I-3.500m-900N], below each string's middle), the insulators' tops (each string's own attachment, written a little down the string as "string top → the point it hangs from": a separate thing from the structure point at the same place), strings and wire points (with the set), the alignment points' names, and every label with the object's description (yours only); New pylon from a template… (a pylon template's face — its dimensions typed and drawn — built into a structure type of level 1 for suspension or strain, sets from the template's slots: see Pylon templates; a type built before is built again — only the template's points, strings and wire points are replaced, joints, members and everything added by hand are kept, and what refers to something no longer built is listed — its structures follow); Place on alignment points… (an alignment, a type for all its free points and another for some rows, e.g. the angle points: one command, each tied to its point and turned along the line; then they stay as placed); Add structure… (the structure window, on the first free alignment point — the Add structure tool opens it where the ground was clicked, else there too; with no structure type in the library it says so (a structure without a type holds no wire until strings are added by hand) and offers New pylon from a template…; for a structure placed before, Put it on the line again puts it back on its alignment point, turned along the line there); Spot structures… (the least-cost structures along a route, saved as a new line: Spotting); Angles around structures… — which angle means ahead along the line, for the whole project: angles in plan around a structure (a string's direction, the compass of the structure window) turn clockwise seen from above, ahead at the angle chosen (default 0°: right 90°; e.g. 270°: right 0°, ahead 270°) |
| Sections | library: wires; tables: sections, jumpers, span points and loads, point and spread load types, spacers, electrical systems, electrical circuits; Display options — how the wires are drawn: Wire colours by Circuits (each section's colour — the Sections table's colour column gives one to every section of a circuit — else its phase's) or by Systems, phases by line code (each system's colour from the Systems table; its first phase solid, the second ·–·–, the third ·––·––, then again; earth wires grey); and what is drawn and written next to the wires, ticked for the plan, profile and 3D views each: the Direction of each section and jumper in its circuit (an arrow head at its middle, pointing away from the circuit's starts), the section's label (once per section, at its middle span) and each span's sag (at mid-span, or in the 3D view on the part of the wire in sight when you are close; in the section's colour; spans too short on screen, and notes that would overlap, are left out — the nearest first in 3D). The menu stays open while you tick. Your choice only, remembered with the project on this computer |
| Criteria | Weather cases — every case in one table, one row each, the columns of a criteria table (name above, unit below, a grid; every row the same widths): name, description, tags, air density factor Q, wind velocity, wind pressure (P = Q·V²: typing the velocity or Q sets the pressure), ice thickness, density and load, wire and ambient temperature (see Tables); the Weather cases library and Load cases library editors (.ohlwc, .ohllc; see Load cases); Creep-Stretch… — the weather case for the final after creep and the weather case(s) for the final after load (the one stretching each wire most is used); one command, undoable; every section is solved again; Bimetallic conductor model… — bird cage or compression (with the largest virtual compressive stress) for the line's bimetallic cables that do not give their own in the wire library; lists which cables follow it; one command, undoable; every section is solved again; Calculation options… — how the whole line is calculated: what of the jumpers the sections carry at their clamps, an estimate (default: weight, ice and wind) or the jumper's own pull (the sections and jumpers solved in turn; see Jumpers); and for jumpers on taps (starting from a clamp on a span or another jumper) the full loop (default: the jumper's own force on the wire it hangs on, solved in turn until the tap settles) or one calculation (its estimate, no loop); one command, undoable; Default values… — kept with the project: what new objects start with and what the calculations take where an object, a cable, a weather or ambient case or a rule file gives no value of its own — a spacer's compression limit (10 000 N), a jumper's exit angle (30°) and stiffness factor (0.2), a new jumper clamp's length (0.1 m), an insulator's stiffness EA (5·10⁷ N), the air density factor Q (0.613), the thermal emissivity, absorptivity, roughness, albedo and time step, the clearances' wind step, vertical band and search margin, a new clearance window's zone width and depth (each with the program's value beside it; display settings stay yours); Export… and Import… write and read them as a .ohldef file (Import fills the window; OK keeps them); Program's values goes back to OpenOHL's; one command, undoable; Design code… — weather and load cases from a design-code plugin and your parameter file (see Design codes); Loads for structures — the load cases and weather cases the line sends to its placed structures (a tick menu, see Loads for structures) |
| Checks | calculations run on demand — they never change the model: Performed checks… (the library of the checks saved on this project line, see The library of performed checks); Compute structure loads (the loads at every point of the structures in each load case, see Structure loads); Thermal rating… (ampacity per section and ambient case, clearance-limited temperature, see Thermal rating); Clearances: Ground clearances › Vertical clearances… and Radial clearances… (to the ground and the LiDAR points, rules typed in each window, see Vertical and radial clearances), and Wire clearances › a rule file's checks — between wires and with exclusion zones; rules to other lines are left to ohl line --other-line (Check wire clearances, also after every edit, Rule file, Add a rule file…, Show results; the submenu stays open while you tick); Analyses: Galloping ellipses…, the checks of the check plugins in use, in the submenus they define (none without them) — e.g. a code's Distance between conductors… (the distance between the conductors of each span, see Distance between conductors), Vegetation…, As-built wires… (see Galloping, blowout, vegetation and as-built wires). Tension limits and Insulator swing are listed greyed: still to come |
| Tools | Tool inventory (E); hold any tool (each with its icon) |
| Versions | The project lines — the main line and its phases or alternatives, each edited on its own: Working on: the line your edits go to; Project lines › Project lines… (choose the line you work on and those shown next to it; rename, delete) and Working tree… (the lines through time, left to right: when each started, which exist, merges; admins roll a line back); Description of … (what the line is for; its creator or an admin edits it); New line from …; Bring in changes from another line…; Submit this line for review into the main line…; ticks to show lines next to yours (the menu stays open). Then History… (the operation log; admins reverse entries) and Revisions and branches… (revisions, branches, tags, diff, merge, reviews, edit rights — see Versions). See Project lines and phases. |
| Plugins | Plugin manager… (see Plugins), Python console (see Python console) |
| Help | User guide… (this manual) and Start from scratch (tutorial)… — the manual on this computer: the book built by mdbook build (target/book or book), else its Markdown sources in docs/, opened with the system's program for the file; nothing is fetched from the internet; greyed out, with where to build it, when neither is there (Start from scratch stays greyed out until the tutorial is written: it is planned); About OHL-Design (version, build, licence); Next steps (the page); Controls › 3D (navigation scheme, speed, look sensitivity, every key and mouse action), Plan, Profile (their mouse actions). The start page has File and Help (User guide, Start from scratch, About) |
Weather cases are solved when needed: opening a model solves only the weather case shown first. Another case is solved in the background the first time it is shown (Display weather cases, a section's own display case); the status bar says which are being solved. A check or a script that needs a case solves it first. Edits re-solve the cases already solved; the others are solved from the line as it is when they are first shown. The Model page lists the cases not solved yet.
Opening a menu stops what was going on, as Escape would: a captured mouse is freed, a wire being strung or an alignment being laid out is given up, so the menu's commands work on the first click.
Right of the menus, the quick bar: the commands chosen for it (default Undo, Redo, Save all, Fit views, Check wire clearances — Undo, Redo and Save in the same place as in OHL-Structure); under the menus, the line's name and the selection. ⚙ (or View › Customize the quick bar) adds any command of the menus — commands, library editors, tools — removes and orders them; the bar is remembered (a bar customized before keeps its commands).
Pages work like browser tabs: each has a tab with a close button; drag a tab to rearrange, or out of the window to make a floating, resizable window with its own row of tabs (drop more pages on it). A right-click on a tab: Dock on the left (with Model, Clearances, Next steps), Dock on the right (with Properties), Float in a window of its own. Closed pages come back from View. Library editors and tables open together in a floating window — dock them like any page.
Tool windows as panels. The windows a tool or a command opens and closes again — the editor windows (structure, string, section, jumper, span point…), New pylon from a template, Place on alignment points, Replace structure's mapping, the Vertical and Radial clearances windows, Display weather cases — come up floating where they always did. 📌 Dock as a panel (top right of the window) makes one a tab of the main window (with Properties, on the right): drag it anywhere there or out again, or slide it aside behind another page; ⬈ Float makes it a window again. It still closes when its tool is done (Apply, Cancel, the tool finished), and its tab with it; closing its tab closes the tool (as Cancel). Docked once, it comes up docked the next time (in this session).
Starting from nothing#
The starter template. File › New project… › Starter template (for learning) (or the start page's New project from the starter template…) makes a project in local coordinates (metres) whose libraries hold a small set of examples — every value invented or typical, clearly marked, nothing for design: a wire library (ACSR conductors), two structure types of level 1 (a suspension and a strain tower, built from the pylon template delta-1c), insulator assemblies, weather cases, load cases and a clearance rule file; beside the project, the pylon templates delta-1c and barrel-2c (in its Pylon templates folder) and starter-survey.csv, survey points of invented ground to import with Terrain › Terrain surfaces (TIN). It has no route, alignment, structure or wire: the planned tutorial (Help › Start from scratch, greyed out until it is written) will walk through making them — the route, the alignment, the first structures, the strings on them, the cable and the stringing, the jumpers; until then, A new line, step by step and Next steps show the way. The files are examples/starter/ of the source tree (its README lists them); the tutorial will use the same.
Next steps (a page, View › Next steps, Help › Next steps; in front when a line has no structure yet) lists what the line still needs, in the order of the work, worked out from the project each time it is drawn: a route, an alignment, the ground, structure types, structures on the line, strings on them, cables, wires strung, jumpers (where a line needs them), weather cases, load cases, clearance rules. Each step says what the project has, or how it is done, and is a link to where it is done — the first steps window, a tool held (New alignment, Add structure, Add string, String wire, Add jumper), Terrain surfaces, New pylon from a template, Place on alignment points, a library page, Vertical clearances. The next step is in bold.
When the first point of a new alignment is typed or clicked on an empty line, the views go to it; the first structures of an empty line fit the plan and the 3D view.
Views#
- 3D — ground (shaded), LiDAR points coloured by class role (vegetation green, buildings red, water blue, wires yellow…), structures, insulator strings, wires in their phase colours (bundles as their subconductors,
bundle_spacingapart — one section, solved and selected as one — held at every clamp by a yoke: a bar for two, a triangle for three, a polygon for more; the back and ahead spans and the jumpers end on its corners), alignments. Navigation: see Controls. Height exaggeration in the Model panel. - Plan — alignments, wires and structures from above, north up, with a scale bar. Drag, scroll at the pointer, double-click to centre.
- Profile — per route, or All alignments, in order (the first, then the second… each starting where the one before ends, its name at the start): ground along the centreline, structures and wires by station: the spans between the structures following each other along the alignment, and those to a structure of the route away from the alignment (more than 5 m beside it and not tied to one of its points — a connection or termination beside the line, on the route because it gives it): projected at its station, fainter, its distance from the alignment written after its name (C1 (80 m right)); the spans along the alignment go on past it. The same holds for the drawings, and the line angles and spans ahead (stationing, structure loads) are taken along the alignment's structures, without those away. corridor ± (m, yours only) shows what lies that far left and right of the alignment: the ground at both edges (thin, darker), the survey points of the ground surface (dots) and the 3D lines and points of the drawings (DXF, in their colours; flat 2D drawings have no heights and are left out; hidden drawings are not drawn), projected on the profile; 0 shows the centreline only; heights fit the visible stretch, or keep the ratio chosen in View › Profile aspect ratio (written at the top left). Scroll zooms at the pointer (at a fixed ratio the height under the pointer stays under it), drag moves (also up and down at a fixed ratio), double-click shows the whole route.
- Properties — the selected structure (position, type, attachments, spans through it) or span (cable, circuit, electrical system and voltage, bundle, horizontal and maximum tension, sag and lowest point in every weather case). Links select related objects.
- Model — layers, sections or jumpers that failed to solve, by weather case (click one: that case is shown, the object selected and the views brought to it), what was loaded and how long it took (folded: Loaded; library files of the project are named by their name, not by their working copy's temporary path).
- Next steps — see Starting from nothing.
- Sections not solved are drawn in each weather case they fail in, in the 3D and plan views, as a dashed red line where they were: their last solved shape in that case (an edit made them fail: the shape before it), else their shape in another weather case, else the straight chords between their wire points. Hovering one in the plan says why; a click on any drawn copy selects the span (all copies highlighted), and its properties say why it did not solve in that case and where the drawn shape comes from.
- Structures by usage — on the Structure loads page (Checks › Compute structure loads), view Usage, Colour structures by usage colours the structures in the 3D and plan views by their usage (green, orange from 90 %, red over 100 %; a neutral grey-blue for those not checked because a section or jumper at them did not solve; dark grey without capacity), with a legend at the bottom right; see Structure usage.
- Clearances — clearance violations of the shown weather case (see Clearances).
- Properties of the other kinds: a wire point with a set (its strings — top, wire point, length, weight, insulator, compression —, spans and jumpers there), an alignment point (position, tied structure), a LiDAR point (position, class and roles).
Level of detail#
The 3D view draws the large layers — terrain, LiDAR points, structures, wires, other weather cases, other project lines, DXF drawings — in chunks: the 256 m tiles of the project grid (the grid of the project file's spatial index). Every frame, each chunk in view is drawn at a level of detail from its distance to the eye; chunks outside the view or beyond the layer's render distance are not drawn, and those far beyond (1.5 × the render distance) leave the GPU. Missing chunks are built nearest first, a few milliseconds per frame, so the view never freezes: until a chunk's level is built, a level already built is drawn. An edit rebuilds the layers of the line, not the terrain and the LiDAR points.
View › Advanced › Level of detail (a page) is the table of these settings, a row per layer, every value typed in, remembered with the window layout:
| Layer | Level 0 | Level 1 (default from) | Level 2 (default from) | Render distance |
|---|---|---|---|---|
| Terrain | every TIN triangle | the surface on an 8 m grid (1.5 km) | a 32 m grid (5 km) | 30 km |
| LiDAR points held in memory | the share of the survey chosen in Survey data display options (default 25 %; 100 %: every point) | 25 % of that (500 m) | 5 % of that (1.5 km) | 3 km |
| Structures | lattice, arms, strings | mast, arms and strings (2 km) | the mast line (8 km) | 50 km |
| Wires, other cases, project lines | every point; bundles as subconductors with their yokes; clamps, marker balls and other bodies to their shape, bare span points' marks, jumpers' support clamps | 16 points per span, one line per bundle; line codes' dashes 4 × longer; bodies as dots, clamps and marks left out (1.5 km) | 5 points per span; dashes 16 × longer; spreads, spacers and arrows left out (6 km) | 50 km |
| Drawings (DXF) | every vertex and point | lines simplified to 0.5 m, lines and points smaller left out (1 km) | simplified to 2 m (4 km) | 10 km |
Sections not solved in a weather case are drawn dashed red at every level, their dashes longer farther like the line codes'. Labels: in 3D, the section labels, sags and the labels of points and strings are written within the label distance of the eye (Display options, default 1.5 km); the structures' names (when ticked) at any distance — they are placed first, the other labels give way to them, and where names would overlap the nearest is written. In the plan the structures' names are always written, at every zoom, first in line order where they would overlap (the selected one always); sags and section labels only for the spans in view long enough on the screen. The plan draws what is in view only, a far view's points crowded into one pixel once; the profile draws one survey point per pixel and keeps what it drew while the view does not move. The 3D image is drawn again only when the camera or what is on the GPU changes (a frame for another panel shows the same image).
The last column of the table shows what was drawn in the last frame: the chunks at each level, of how many, and how many are still loading. On a 25 km line seen from 1.5 km, 5 million terrain triangles became 280 000 drawn, 1.5 million LiDAR points 24 000, and 190 000 wire segments 14 000; every chunk builds in under 2 ms.
Point budget#
A survey stored in the project — or a COPC file opened as the point cloud (--pointcloud survey.copc.laz) — is not drawn by the table's levels but streamed by node under a point budget. Its nodes are, for a stored survey, each 256 m square at four levels (about 1/64, 1/16, 1/4 of its points, then every point: the levels of detail stored in the project), and for a COPC file its octree. Every frame:
- the nodes in view and within the LiDAR row's render distance are taken, the coarsest first;
- a node whose points lie farther apart on the screen than the error allowed (default 1.5 px) is refined — its finer level, or its octree children — the one with the largest error (the nearest) first;
- until the next node would exceed the point budget (default 5 million points; the share of Survey data display options thins every node further and counts in the budget).
The missing nodes are read on background threads (half the cores, at most four), each with its own reader of the project file, in that order; the queue is replaced every frame, so it never lags behind the camera. Until a node is read, a coarser (or finer) level of its square already read is drawn. Nodes read stay on the GPU while they are in view; beyond 1.5 × the budget the least recently used are dropped. Classes of up to 20 000 points are read whole at every level (wires, towers); hidden classes are not read.
View › Advanced › Level of detail sets the budget (0.1–200 million points) and the error (0.1–50 px), remembered per user, and shows what the last frame did: nodes drawn of how many, points drawn and wanted, whether the budget was reached, what is on the GPU and still loading.
Measured on an Apple M1 Max (synthetic survey of 25 million points on 2.5 km × 2.5 km, 1600 × 1000 view, error 0.3 px so that the budget limits the view; point_budget_frame_times, release build, GPU time included):
| Budget | Points drawn | Read in | Frame while turning (median / slowest) |
|---|---|---|---|
| 2 million | 1.97 million | 0.07 s | 7.7 ms / 9.8 ms |
| 5 million | 4.97 million | 0.13 s | 16.5 ms / 19 ms |
| 10 million | 9.9 million | 0.23 s | 32 ms / 35 ms |
The frame time grows with the points drawn (about 3.3 ns a point on this GPU), not with the size of the survey: what a frame touches is bounded by the budget and the nodes in view (choosing them takes microseconds). For 60 frames a second, keep the budget near 5 million on such a machine. A survey of 10⁹ points on disk has more nodes (a few thousand for a 100 km corridor), read the same way: the index of its blocks once when the view opens (about 0.4 s per 10⁵ blocks; 10⁹ points are some 10⁵), then each node as it comes in view. Not measured at that size here (only synthetic data is used for performance, and the largest run is 25 million points). The synthetic grids also compress to almost nothing: real surveys decode several times slower than the 25–45 million points a second measured above, so expect nodes to arrive a few times slower — the frame rate does not depend on it.
The level of detail changes what is drawn only: calculations, checks, the profile, the plan and picking always use the full model.
Weather cases shown#
Display weather cases (View menu) chooses how the wires are shown:
- The same weather cases for every section: tick one or several (the list scrolls in a box of fixed height); every section is drawn in each case ticked. Display only — the Sections table's display cases are kept (not used while this is chosen).
- Each section's display weather case (Sections table): every section in its own display cases; sections without one in the cases ticked above. Setting display cases in the Sections table chooses this too.
- Wind: from the right, from the left, or both sides (each case with wind solved and drawn twice; the wind from the right is the one checked). The side the wind comes from is a display choice, not part of the weather case.
Wires are drawn with their jumpers, yokes and insulator strings, to their clamp as solved in each case (swung by the wind, moved with the temperature). Labels (section labels, sags, structure labels) are written once per section, in its first case: the other cases show their wires only. In 3D, labels are written only within a distance of the eye — 1500 m unless set otherwise in either Display options menu ("3D labels within … m of the eye") — and are not even built beyond it, so a long line stays fluid. Every copy drawn can be clicked — anything that moves with the weather case — a span, jumper, string, wire point, span point or spacer — in any of the cases shown (either wind side) — and selects the object (Edit opens it as usual). The selection is highlighted in every case it is drawn in, the copy clicked the strongest, and its properties mark the case of that copy (▶, coloured) in their list of weather cases. The first case is the one checked for clearances. These choices are yours, remembered with the project on this computer. In the properties, a span's or jumper's results in every weather case are listed in a box of fixed height, scrolled.
The model's weather case file is remembered with the project (--weather, or Use for the model in the Weather cases library editor, Criteria menu): opened again without --weather, the project uses the file it used last.
Project lines#
A project holds several designs of the line — the main line and, for example, the phases of the project — each edited on its own. You work on one at a time (Versions › Project lines…, or the Versions menu): your edits and Undo apply to it; others are shown next to it in their colour. A new line is a copy that then lives its own life; Bring in changes updates it from another line, and a phase goes back into the main line through a review. On a server each user chooses their own line. Everything is described in Project lines and phases.
Saving#
Every edit is stored in the project file as it is made (the operation log), so nothing is lost when the app stops. ⌘S (Ctrl+S on Windows and Linux, or File › Save all) writes the project file through, saves the library pages with changes that read (the model reads them again) and says which table changes are still pending (Apply makes them). ⌘Z / Shift+⌘Z (Ctrl+Z / Shift+Ctrl+Z) undo and redo, outside text fields.
Editing#
A project (.ohl) opened by a user with the designer or admin role (--user, default the login name) can be edited; every edit is a command in the project's log, undoable per user (ADR-0005). A line file, or a user without a role, opens read-only — the status bar says why.
| Action | How |
|---|---|
| Move a structure | M (or the Move tool in the hotbar), then right-click a structure in any view: the Move structure window shows E, N, z (or "base on the ground"); the change is previewed live (the shown weather case re-solves the sections through it); Apply (Enter) makes one command, Cancel (Escape) puts it back. |
| Delete | The Delete tool and a right-click on a structure, a string (its insulator or wire point), a span (deletes its section) or a jumper — or Delete / Backspace for the selected one. When it takes other objects with it (a string: the sections through it and their jumpers; a structure: its sections, jumpers, routes…), a window lists them; Delete all applies it as one command. A string of a structure type is left out of that structure (omit in the line file). |
| Edit | The Edit tool and a right-click: on a structure, its structure screen — as Strings and points… in Properties: the tables of its attachment points, strings, wire points and sets beside its pylon in 3D (a typed structure: its type, every structure of the type follows when saved; a structure without a type: the structure editor); its body and design: Open this type in OHL-Structure… there, or Open in OHL-Structure… in Properties. Its placement window (type and extension from the structure library, orientation, position or base on the ground, Put it on the line again; explicit strings turn and move with it) is Placement… in Properties. On a string, its window — every string of its assembly (a jumper's helping strings too). Each string: from the library (an insulator assembly: its length, weight, wind area and stiffness; a tension assembly makes a strain clamp), what it hangs from (a list of the structure's points, or the bottom of another string, to move it), what it ends at — its own wire point, which the string makes: placed from its top by down/up (0° straight down, 90° level, 180° up), a direction in plan in the structure's axes (0° ahead along the line, 90° to the right, 180° back, 270° to the left) and its length, where it is before stringing (once strung it is drawn as solved) — or any other wire point of the structure (one of another set is taken into the window): the string keeps its length; where one string ends there already the two make a V, the point going where both lengths meet, where none does the point goes to the string's end, what hangs below moves along; refused, with the reason, where the legs cannot meet, where two strings meet there already, where it would hang below itself or where the wire point it leaves and the new one both have a set; the wire point it alone held goes, what hung from it hangs from the new end (lengths kept) and its set goes along where the new end has none — so strings chain (a V under a V: four strings); weight, wind area, whether it may push. Its wire point: a label, a set (a wire is clamped there; without one, other strings may hang from it), its clamp — suspension (the wire runs through, the string hangs) or strain (a dead end, tension strings lined up with their conductor) — and a counterweight. + string adds one with its own wire point 3 m straight down; × takes a string away with the wire point it makes and what hangs from it. New points on the structure where none fits; short explanations in the window. On a typed structure the change overrides the type's string, and Back to the type's string removes the override; on a span, its section's window (cable from the wire library, circuit, phase, electrical system — these three for its whole circuit: the first Apply lists the circuit's other sections that change with it, a second applies to them all —, bundle and spacing, status in the blocks (rolling: one tension in all spans in every weather case; default) or clipped in (each span keeps its unstressed length; switching computes them from the condition), sagged to a horizontal tension or to a sag in the ruling span or in a chosen span, at a temperature — see Stringing and status —, and Pick points again); on a jumper, its window (cable; given by its length, its sag or as rigid; temperature; bending stiffness estimated with its factor or given; the angles it leaves its clamps at; its own bundle or its section's; its helping strings — each on a structure at one of the jumper's ends, a wire point without a set held by an I or a V (the list offers only those), where its middle is along the jumper (a share of its length from its first end) and its length; Add helping string (a jumper given by its length, without a support string), Remove… asks before it removes one; nothing else goes with it, and the change is applied as one command with the rest); on a span point or a jumper point, its own window (as Add on span: its place, label, description, bare or with its object). |
| Add a structure | The Add structure tool and a right-click on an alignment point without a structure (it stands on it, tied to it) or on the ground (3D view, under the crosshair in first person; or the plan view), or Structures › Add structure…: the structure window — id, type (a button showing the type chosen, or none: its points given here; it opens the structure picker, where the extension can be chosen too), extension and height adjustment of a type, a description; where it stands: at coordinates (E, N, z or the base on the ground) or on an alignment point chosen in the list of the alignments' points (each named as the views name it — PX — main #3 — E …, N …) (one near the right-click is chosen for you; it stands there and the point is tied to it, so the alignment follows it); its orientation along the line (ahead along the alignment, the cross-arms — right to left — on the bisector of the line angle there; untick to type it); for a structure without a type, its points where strings hang, in its axes (across, along, up); and a 3D preview in its own axes with a compass on the ground at 0;0 — the angles as the project counts them (ahead, right, back, left), ahead (green) and right (red), north (blue): drag turns it, right-drag pans, the wheel zooms, a double-click fits it. Then hang strings on its points with Add string. |
| Add a string | The Add string tool and a right-click on a point of a structure (while the tool is held, its points and wire points can be right-clicked): an I-string hanging from that point, its wire point 3 m straight down, at the next free set; on a wire point: its strings' window with a new string hanging below it, at the next free set (a TAK). A right-click elsewhere on a structure hangs it from one of the structure's points (the first no string hangs from yet). New strings hang from the points the structure has; a new point on the structure is only made when asked (+ point in the window) or where a preset's shape needs one. The window lists the structure's points, the wire points and the strings (in the structure's axes): add, remove and edit them, or replace them with a preset — I-string, V-string, V + string below, TAK (two sets). Each string goes from a point or another string's wire point to a wire point (choosing another hangs from keeps its length and angles: its wire point, and what hangs below it, moves along; a V's leg keeps both legs' lengths, its tip going where they meet, and where they cannot meet the change is refused with the reason), and a string's length typed is kept with every other string's: an I's wire point moves along it, a V's legs each have their own length (their angles shown, from where they meet) and the point where they meet moves, what hangs below (a string under the V) keeps its length and moves along — a length the legs cannot meet with (together shorter than their tops are apart, or too different) is refused with the reason, in red; may take compression up to a value, may be a strain string; its limits (max load, max swing, across, along — each ticked and given, or not given; kept for plugins and reports, not checked by OpenOHL). Edit on a string opens the same window for its set. |
| String a wire | The String wire tool: right-click the strings in line order (a yellow line joins them), Enter opens the new section's window — like the selected span's section, or the one through the first string, in the blocks with its condition (or its tension as solved) —, Backspace takes the last point back, Escape gives the wire up (also from its section's window): String wire stays held and, in first person, the mouse stays captured — a second Escape frees it. Pick points again in a section's window strings it again through new points (a clipped section with a different number of spans goes back to the blocks). |
| Add a point, an object or a spread | The Add on span tool: right-click a span or a jumper — a window opens placing the point where the wire was clicked (3D and plan views; the profile: mid-span): a bare point (a spacer's or a spread's end), a point with its object (one per point) — a template of the point and spread load types (marker balls, an obstruction light, a bird diverter, a weight, a tap clamp, a spacer clamp; typical values, to check) or its own values; advanced settings: body or clamp, its shape and sizes (point, sphere, cylinder along / across / vertical, box, given wind and ice areas), drag, a clamp's length — or, on a span, a spread (N per metre between two new points; spread templates), its load on the whole bundle (shared by its subconductors, as before) or on each subconductor (each cable of the bundle carries it: the bundle carries the load × the bundle, shown beside). Places on a span by fraction, distance from its back structure or station; on a jumper by fraction, length along it or distance from its from clamp; regular spacing repeats points from a first place to a last one. They are listed in Sections › Span points and loads, drawn on the wires by their shape (bodies to size and oriented along the wire; clamps in steel, as a short cylinder along the wire, or their own shape when given — a clamp's cylinder across the line on a bundle is drawn joining its subconductors, a bar between two, a ring of bars around three or more, so it looks clamped on all of them; drawn only: its wind and ice come from its shape's sizes as given; bare points as a small blue cross — a mark, not a body —; spreads as an orange stretch), clickable in every weather case drawn (a spread anywhere along its stretch: its points, load, what it is on and its type in Properties), changed with the Edit tool (a right-click on the point opens its own window: place, label — what names it follows —, description, bare or its object), and deleted with the Delete tool, Delete selected or in the table (a point takes the spacers clamped and the jumpers hanging on it). Deleting a spread asks: Spread only (its points stay), Spread and its points (those of its points that are bare and used by nothing else — a point holding an object, ending another spread, a spacer's end or a tap stays; each listed with what keeps it) or Cancel; deleting a point a spread ends on asks whether to delete it with its whole spread(s) — Delete the point and its spreads (their other points stay) or Cancel. Either is one log entry. |
| Add a spacer | The Add string tool: right-click a span point, then a span point of another conductor of the same span — the spacer's window (insulator from the library or its own values, length given or as strung, weight, wind area, EA, compression limit from the project's default values); a bare end point gets the spacer clamp template (one clamp object for spacers and jumpers). Both sections must be solved by finite elements (not the ruling span). The spacer is solved with the sections it joins, drawn between its ends (red beyond its compression limit), listed in Sections › Spacers (with its force and state in the case shown); Edit opens its window. The first span point again, or Escape, cancels. |
| Add a jumper | The Add jumper tool: right-click a structure — the jumpers missing there are added, between two section ends (first or last points) of the same circuit and phase that no jumper joins yet (sag 15 % of the distance, at 15 °C; ends that cannot be paired are named); or right-click its first end, then the suspension strings of the structure it passes through, in order (strings to a wire point without a set; a wire point whose set a section uses is the jumper's other end, one whose set no section uses is refused, with the reason — the Add string tool gives a new string's wire point a set: untick it in the string window to hang a jumper clamp there), then its other end: a jumper with a clamp on each of those strings, given by the lengths between its clamps (each first 3 % over the straight distance), its window opened to type them (the jumper's length is their sum; the clamps' places follow). Without strings in between: a jumper between the two ends (sag 15 % of the distance). The first end again, or Escape, cancels. Edit on a jumper opens its row in the Jumpers table. A jumper may also start from a tap: right-click a point holding a clamp (on a span or on another jumper), then its other end (a string or another tap): a jumper on the tap, given by its length (3 % over the distance between its ends; its window opened); the tap is a hinge (forces only), solved as Criteria › Calculation options says (the full loop by default). Joining two circuits: a jumper between conductors of two different circuits (another circuit name, phase or electrical system) is not added at once: a window says you are trying to connect 2 different circuits — Continue or Cancel (nothing changes; Escape too). Continue shows both circuits side by side — name, phase, system with its voltage and phases, the structures each runs between, its sections and length, differences highlighted — and asks which one stays; Join into … adds the jumper and gives the other circuit's sections the name, phase and system of the one kept, as one change (one undo takes both back); Back returns to the first question. |
| Replace a structure | The Replace structure tool (⬌) and a right-click on a structure — or Replace… in its Properties, or a right-click on a row's ⤴ in the Structures table: the structure picker (its current type selected) chooses the new type; the structure keeps its id, place, orientation and height adjustment, and its extension when the new type has one of the same name (else it is placed without one, and the window or the status bar says so). When every wire point (set) where something ends is also on the new type and nothing else goes, it is replaced at once and the status bar says how many wires were rewired. Otherwise a mapping window lists the old wire points — set, label, side (left / right looking ahead), height, what ends there (sections, jumpers, circuit starts) — each with a choice of the new type's wire points (proposed: the same set, else the one on the same side in the same height order; none: what ends there is removed), and under them, in a scroll box, everything that would be removed or dropped: sections, the jumpers at them or hanging on taps on them, their spacers, the old structure's own points, strings and wire points (overrides of its type), jumper support clamps on wire points the new type lacks — the sections and jumpers removed drawn red in the 3D view while the window is open. Replace applies it as one log entry (undo brings everything back); Cancel, Escape or closing the window changes nothing. Two old wire points to one new one, or a set the new type lacks, is refused with the reason. |
| Undo / redo | ⌘Z / Shift+⌘Z (Ctrl on Windows and Linux), the Edit menu or the quick bar. |
Every window applies one command (Apply or Enter; Cancel or Escape); when the session refuses it (an id taken, a line that would not be valid…), the window stays open with the reason. While Delete, Edit, Add string or String wire is held, strings can be right-clicked whatever Edit › Snap says. A right-click on nothing says so in the status bar, with what the tool works on.
After an edit only the sections it touched are re-solved, in every weather case (incremental solving); the status bar reports what was re-solved and how long it took (about 0.1 s on the 25 km line), and the Clearances tab checks again.
Loads for structures#
What the line sends to its placed structures (Open in OHL-Structure… on a placed structure starts the structure application with that place's loads) is set up in three places of the Criteria menu:
- Weather cases: the wind, ice and temperatures. Each one can be sent on its own.
- Load cases (a
.ohllcfile) or Design code (a plugin writes the load cases): a weather case with a wire condition and factors on the vertical, transverse and longitudinal loads. They add factors and combinations on top of the weather cases. - Loads for structures: a tick menu (it stays open while ticking)
with two lists. Load cases: those sent (all by default, also those
added later; all / none). Weather cases (all factors 1):
those sent on their own, each as a case
weather: <name>with every factor 1 and the wires as strung (none by default; none). A ticked case no longer in the line stays listed, marked, to be unticked. Each tick is one edit of the project line's settings (undoable, thestructure_loadsrow), so every project line keeps its own choice.
The structure application gets the load cases sent, then the weather cases sent, each marked with its source. A line with no load case and no weather case ticked sends nothing: the structure application says so and suggests ticking weather cases here.
Tools: hotbar and inventory#
As in Minecraft, the bottom of the 3D view holds a hotbar (it goes with the 3D view when another page is in front; the inventory shows it to arrange it) of nine tool slots. Choosing a slot — 1–9, a click on it, or the wheel while the mouse is captured in first person, one slot per wheel notch (a trackpad steps at a steady pace; Ctrl + wheel stays the speed) — only holds its tool; a right-click on an object uses it (in first person, on what is under the crosshair): Select, Move structure (M), Delete, Go to structure (G), Edit, Add structure, Add string, String wire, Add alignment point, New alignment, Edit alignment, Add jumper, Add on span, Replace structure (see Editing and Routes and alignments). A new user's hotbar holds Select, Move structure, Delete, Go to structure, Edit, Add structure, Add string, String wire and New alignment; the others wait in the inventory. Holding a tool that is not in the hotbar (from the Tools menu, a key, a link of Next steps) puts it into an empty slot — the active one if it is empty — else into the last slot: never over the first slot (Select) nor over the tool held. A left click always selects; a right-drag still pans. A window opened by a tool (Move, an editor, the confirmation of a deletion, Go to) frees a captured mouse and opens at the crosshair (or at the mouse outside first person), also when it replaces a window already open for another object; it can be dragged anywhere, also partly off the screen. E opens the inventory with every tool (E or Escape closes it); only while it is open can the hotbar be arranged: drag a tool onto a slot, drag slots to swap them, drag a slot back to the inventory (or right-click the slot) to empty it. The arrangement is remembered. New tools are added to the inventory as they come. Each tool has its icon (the drawings of assets/icons/tools/) in its slot, in the inventory, in the Tools menu and on the quick bar; in the menus it takes the text colour of the theme (light or dark). The window and the start page show the OpenOHL mark and OHL-Design's icon; Help › About shows the mark with the version.
Clearances#
There are three ways to check clearances, each for its own targets: Ground clearances (Checks menu) — Vertical clearances… and Radial clearances…, to the ground and the LiDAR points, with rules typed in each window (below); Wire clearances — between the wires of this line and with exclusion zones, by the rules of a rule file (its rules to other lines are not run here: the results list them as skipped, for ohl line --other-line), run by Check wire clearances (Checks › Wire clearances, or the quick bar), results on the Clearances page. The menu and the page say which is which.
The Clearances tab checks the shown weather case with a rule file (.ohlr, the format of ohl line --rules; see Clearance rules): the wires against the ground surface, against the LiDAR points of the rules' classes, and against the line's other wires, with the requirements by voltage of each section's electrical system. Rule files are listed from --rules FILE and the project's .ohlr files (next to a line file); the one given or the only one found is chosen at start. Without one, the page says so and offers Add a rule file… (a .ohlr file chosen on the computer, checked, kept in the project — examples/starter/rules has one with invented values to learn with) and the two ground clearance windows.
Checks run on demand: Check wire clearances (Checks › Wire clearances, or the quick bar) or Check now in the tab; tick "after every edit" to check again after each edit and change of weather case. The check runs in the background. LiDAR points are read again from the project's point cloud each time, only those of the rules' classes in a corridor around the spans, so nothing more is kept in memory: on the 25 km line with 18.8 million such points a check takes a few seconds. The list shows each violation, worst first: wire (span or jumper, and the other wire for wire rules), rule, vertical or radial clearance against the requirement, the LiDAR class, how many points are too close. Clicking one selects the wire and brings the views to it. The violations are drawn in red in the 3D view (a line from the wire to the point too close; layer "Clearance violations") and circled in the plan.
Rules for other lines and rules across pairs of weather cases are run by ohl line only; the tab says so.
The Analyses entries of the Checks menu open windows that compute on demand in the background, each with a results table (click a span to go to it) and CSV export — see Galloping, blowout, vegetation and as-built wires: Galloping ellipses (a .ohlg parameter file and a weather case), Vegetation (the point cloud's vegetation classes near the wires of a case, growth, trees falling in), As-built wires (catenaries fitted to the wire points, the temperature at the survey).
Vertical and radial clearances#
Checks › Ground clearances opens two windows: Vertical clearances… and Radial clearances…. Each checks the spans and jumpers against its own list of rules. The window can be closed at any time; closing it stops a check that runs.
The zone.
- Vertical: an area of points straight under (and over) the wire: width on each side (default 1 m) across the line, in plan, and depth (default 0.2 m) along it. The clearance is the shortest vertical distance between the wire and a point of the area: a point is compared with the wire's lowest point within the depth around it (its highest for a point above the wire — rare, but measured the same way). Bundles: the lowest (highest) subconductor. A rule may have its own width (the rules' width m column: click the window's width, shown in brackets, to give the rule its own; × goes back to the window's).
- Radial: the direct 3D distance from the wire, to each subconductor of a bundle.
- Ignore LiDAR points farther than … m from the wires (both windows; unticked: as far as the rules reach): only the points within that distance of the wires are read and compared.
What is solved. Circuits: the circuits checked, ticked by circuit name (none ticked: every circuit). Solved by: each section's own calculation (the default), or every section by finite elements or by ruling span for this check (each keeps its cable condition).
The rules. One row per rule: a name, the voltage of the wires (any, or one of the line's systems; earthed wires are 0 kV), the weather cases (ticked; none ticked: every case), the distance to keep (m), the vertical window's width (the rule's own, or the window's), the wires checked (the sections' spans, the jumpers, or both — the default) and the targets: LiDAR classes ticked from the point cloud's classes (the class scheme's when no cloud is open), and the ground surface. You never type a class number. Add rule (a blank row), Duplicate and Remove (it asks first) edit the list.
A window always has a rule. Opened without rules (a new project), it starts with one: Ground — the ground surface, any voltage, every weather case — its distance to set (0 m, marked "set the distance": no value is given for you; take it from the regulation you work to). Run is greyed out, with the reason beside it ("Before Run: …"), while a rule's distance is not set or a rule has no target; the last rule cannot be removed (change it instead). A rule whose distance is not set is not written to the rule file. Add a rule (open while the first rule is still to set) asks for one rule in plain fields — its name, what (the ground or LiDAR classes, ticked), the voltage, the distance and the weather cases — with what they mean; Add this rule takes it into the list, in place of the first rule while that one is untouched.
Load preset… lists the clearance presets of the project — given by a design-code plugin when it generates (Criteria › Design code, see Design codes): a rule file and a weather case file of the same name among the project's libraries, with rules of the window's kind. Choosing one replaces the rules listed with its rules, and takes its wind, circuits, calculation method and search distance; its weather cases missing from the model are added to the model's weather case file (the model's cases of the same name are kept). Everything can be changed afterwards — the classes, the cases, the distances — and is kept as the window's rules.
Import… and Export… read and write rule files (.ohlr, see Clearance rules). A row is written as one [[rule]] per target kind (classes, ground), with voltages, wires, cases, vertical_band (the width: the rule's own or the window's), vertical_depth, a [wind] table and a [check] table (the circuits, the method and the search distance, when set), so ohl line --rules reads the file too (it ignores [wind] and [check]). Importing keeps the ground and point rules with a clearance of the window's kind; a requirement by voltage gives one row per voltage of the line; roles become their classes; the first rule's vertical_band becomes the window's width, another one a rule's own. The window says what it left out (rules between wires, exclusion zones).
Without the window. ohl zones --rules FILE runs the same check from the command line on a window's rule file or a preset, with the project's point cloud and ground (see ohl zones).
Where they are kept. Like the Clearances tab's rule files, in the project: <model>.vertical-clearances.ohlr and <model>.radial-clearances.ohlr among its clearance rules (next to a line file). Every change is kept when the mouse is released. The Clearances tab lists these files too; File › Export › Libraries… writes them out (folder rules) for ohl line --rules.
Wind. A weather case with wind is solved with the wind from the left and the right (default), the left only or the right only — looking ahead along the line. Untick Step the wind to check only the case's own pressure. Tick it to solve every pressure from 0 up to the case's, in steps of step Pa (default 50 Pa, at most 200 steps per case and side). The wires at all these positions form the surface the wire sweeps as the wind rises; each span's clearance is the lowest over all of it.
Run solves the wind positions on all cores and checks them in the background, with progress (Stop ends it; the time budget is 15 minutes). LiDAR points are read again from the point cloud, only those of the rules' classes near the wires (within the search distance when one is set). The results list the spans below a rule, worst first: span, rule, required and found distance, the wind pressure and side, the target (class or ground) and how many points are too close (each counted once over all wind positions; for the ground, wire pieces at the worst position). Click a span to select it and bring the views to it. The violations are drawn in red in the 3D view (layer "Clearance violations") and circled in the plan. On the synthetic example, 121 wind positions (600 Pa in 10 Pa steps, both sides) are solved and checked in under 0.1 s.
Tables#
Descriptions: structures, their points, strings and wire points, sections, jumpers, electrical systems and alignment points each have a description (free text): typed in their windows and in the tables' last column, shown in italics under the heading of their properties, and next to their labels when Display options say so.
Tables shows the line one object per row (headers with the unit below the name, a grid, every row the same column widths), in a floating window (each table a page): structures, strings, string library, sections, jumpers, span points and loads, point and spread load types, spacers, electrical systems, electrical circuits, routes, alignments, alignment points, weather cases. Every value shown can be typed in, except counts derived from other rows (shown dimmed) and what a string or an alignment point belongs to (typed in new rows). Where an object leaves a value to its default, the value used is shown, dimmed (hover: "default"): a jumper's bundle and spacing (its section's), bending stiffness (estimated from its cable) and clamp exit angles (30°); a section's electrical system (from its conductor path; "earthed") and the weather cases it is drawn in (those shown); a strain string's weight estimated from its position (strings given without a weight). Applying other changes leaves defaults unset; typing over one sets it on the object:
| Table | Columns |
|---|---|
| Structures | id, type, extension, orientation, E, N, z · strings, sections · routes (empty: from the alignments), description |
| Sections | id, cable, circuit, phase, system, bundle, spacing, bundle angle ° (counter-clockwise looking ahead; 0, shown dimmed: the two highest subconductors level — a triple bundle two side by side above one), status (in the blocks / clipped in), condition (tension · sag, ruling span · sag, span N), value (kN or m), temperature, points (T1 1:1, T2 1:1, …), display cases, H kN, max sag m, calculation (Initial, Creep, Load, Max Sag × RS, FE — also in the section's Edit window; see Calculations), colour, description |
| Strings | structure (new rows), string, from (its top), to (its wire point), sets, length, weight, library label (its entry in the string library), compression, clamp — suspension or strain (shown dimmed when it follows from where the string is: a section ends at its set), wind area (empty: its insulator's), the limits max load, max swing, max across, max along (kept, not checked by OpenOHL; empty: not given; its insulator's shown dimmed) · sections (points and wire points: the string window) |
| String library | label (new rows), name, kind (suspension, strain, v_string), length m, weight N, wind area m², stiffness N, half width m (a V), the limits max load, max swing, max across, max along, source, used (strings with this label); edited: every string with the label follows (a new length moves their wire points), rows added, a used row deleted after confirmation (its strings keep its values under a matching or new label) — see Library labels |
| Jumpers | id, from, to (T3 2:1), cable, length or sag, temperature, bundle and spacing (empty: its section's), bending stiffness EI (empty: estimated from the cable; 0: hinged ends), EI factor, the angles at which it leaves its clamps at from and to, below the conductor (empty: 30°), rigid; its helping strings (structure, wire point, where along, clamp length; edited in its Edit window) — see Jumpers |
| Span points and loads | one row per point of the sections' spans and of the jumpers, and per spread: on (section or jumper), span, kind (point; body or clamp with its library type; spread), label (a point's: typed, it relabels the point, and its spreads, spacers and taps follow), at (a span point: 0.25, 120 m, st. 1520 m; a jumper point: 0.25, 3 m along, 2.5 m from its from clamp; a spread: its first point), end (a spread's last point), load (an object's weight N; a spread's N/m), shape and its sizes (sphere and cylinder: diameter; cylinder: length; box: along, across, height; areas: wind and ice m²), axis, drag — the advanced geometry, typed in (an object changed from its type has its own values) —, load on (a spread: bundle, its load on the whole bundle, or each, on each subconductor). A spread's row selects the spread. Added with the Add on span tool; deleting a point deletes the spacers clamped and the jumpers hanging on it, and the spreads ending on it |
| Point and spread load types | the templates shipped with OpenOHL and the project's own types: id, source (template or project), name, kind (body, clamp, spread), weight, shape and sizes, axis, drag, clamp length, a spread's N/m, description, load on (a spread type: bundle or each subconductor). A template changed (or a type added) is kept as the project's own, in the project (its library file); the project's copy deleted brings the template back; a template stays. The Add on span tool offers them |
| Spacers | id, its ends (section, span point), insulator, length (empty: as strung), weight, wind area, EA, compression limit (empty: tension only), the force and state (ok, slack, over its compression limit) in the case shown, description. Added with Add string between two span points |
| Electrical systems | id, name, AC/DC, kV, Hz, phases (L1 L2 L3; angles kept by position), line codes — how each phase is drawn when wires are coloured by system, in the phases' order separated by spaces: - solid, else its dots and dashes repeated, e.g. - .- .-- (the default) or - --. ..-; fewer: the rest by place —, colour (#rrggbb; default by the system's place) · sections |
| Electrical circuits | one row per circuit, made from the connections (sections joined by jumpers or a shared attachment; none added or deleted here): circuit (C1…); name, phase, system for all its sections ("mixed: …" when its sections differ — one value puts them right); starts — tick which of its ends are starts (power flows in; several possible, at least one start and one end) — and ends, the others along it (a circuit with taps has several); sections and jumpers in order from its starts; colour for the whole circuit at once (all its sections, and its jumpers that have a colour of their own; listed to confirm). ⇄ on a row reverses it: its starts become its ends and back (on Apply); its jumpers turn to point along it. Nothing physical changes. |
| Routes (Terrain menu) | route, name, alignments, structures, sections, description — see Routes and alignments |
| Alignments (Terrain menu) | alignment, name, route, #, points, description |
| Alignment points (Terrain menu) | alignment (another name moves the point there, a new name makes a new alignment), #, point, E, N, z, structure (tied under it, following it; empty: free), also on, description |
| Weather cases | #, name, description, tags, air density factor (Pa/(m/s)², empty: 0.613), wind velocity (m/s; typed in, the pressure becomes Q·V²), wind pressure (Pa), ice thickness (mm), ice density (kg/m³), ice load (N/m), wire temperature, ambient temperature (°C) — Criteria › Weather cases |
- Plugin columns: plugins may add columns after a table's own (e.g. a check plugin's insulation level, low or high, in Electrical circuits — read by its distance between conductors; not set: its default, shown dimmed). The values are kept with the objects and saved with the project; opened where the plugin is not installed, the column still shows, marked "(unused)", its values kept and typed as text. See Writing plugins.
- A structure's type cell is a button showing its type: it opens the structure picker; Choose writes the type and the extension ticked there in the row (pending until Apply, one change with the rest).
- Cells with a known set of values are dropdowns: cables, systems, insulators, status, condition, AC/DC, strain, tied structure; display cases lists the model's weather cases to tick, several at once.
- Colour cells (sections, electrical systems, electrical circuits) are drawn in their colour, the text dark or light to stay readable. A default colour is shown dimmed. Text that is not a colour has no colour behind it. You can still type
#rrggbb. The small striped button at the left of the cell opens the colour tool; its OK writes the colour in the cell as a change (pending until Apply). A colour picked for a default sets it, even the same colour. - A changed cell turns yellow and stays pending; + Add row adds an object typed in a green row (🗑 removes it); 🗑 on a row marks it for deletion (struck through; click again to keep it). Apply N changes makes one command for all of them (one undo, ⌘Z), with the same checks as the editor windows — a cell that does not read is named and nothing is applied; Revert drops them. When the changes reach further than the rows changed, everything they also change is listed first and Apply all that confirms:
- deletions that take other objects with them (a structure's sections and jumpers, a string's sections…);
- a section's circuit name, phase or system, which also go on the other sections of its circuit.
- Renaming a structure, section, jumper or system, or renumbering a string, keeps its place, and what refers to it follows (section points, jumper ends, routes, tied alignment points, sections' system).
- Sections: changing the condition needs its value; status clipped in computes the lengths of its condition (as the section window does); points restring it. Display cases draws the section in each weather case listed, separated by
;(e.g.max temperature; glaze ice), in every view; the first one is the one picked and reported in the properties (empty: the case shown) — sections can be shown each in their own cases. H kN and max sag m give one value per display case (12.31 / 9.87); typing one number is a target in the first display case: the section's condition (tension or sag) is found that gives it (a section clipped in must go back to the blocks for that). - # orders alignment points and weather cases:
3.5goes between 3 and 4. - Weather cases are not part of the project but the model's case file: Apply writes it (comments and layout kept, values with their units) and the model is solved again; not undone with ⌘Z. Without a case file (the default 15 °C case), a project takes new cases in the table: + Add row, then Apply writes its first case file (the 15 °C case and those added) and keeps it in the project. A line file without one: make one in the Weather cases library editor (Criteria menu) and choose Use for the model.
- Click a column title to sort (again: descending, again: unsorted). Numbers sort by value, and names in natural order, the numbers in them counted as numbers: sec2, sec10, sec100 (not sec10, sec100, sec2), whatever their leading zeros. the filter keeps rows with the text in any cell. ⤴ selects the row's object and brings the views to it (a weather case: shows it). A page with pending changes shows * on its tab and does not close.
Structure picker#
A window to choose a structure type, opened from the type button of the structure window (Add structure, Edit) and from the type cells of the Structures table. On the left, a table of the library's types, one row each: id, name, kind (lattice, pole, portal, other), level (1 stick figure, 2 outline, 3 full design: from what the file holds), sets / wires (sets of wire points, wire points), height (of the highest point above the feet), extensions, description (the notes at the top of the type's file, else where it comes from; hover for all of it) and used (structures of the line with this type). A click on a column title sorts by it (again: the other way). The filter at the top keeps the types with every word typed in their id, name, kind or description (any case); it has the keyboard when the window opens, and is remembered until OpenOHL closes. The type in use is selected and in bold; the first row is no type (the structure's points given in its window).
On the right, the selected type drawn: its front (across the line) and side (along it) views at one scale, the feet on the ground — members and body lines, strings (blue lines), points where strings hang (orange), wire points (blue) — or, with a GPU, 3D (drag turns it, the wheel zooms, a double-click fits it). Under it its full name, id and kind, description and source, sets, wire points, height and how often the line uses it, its level and what it lacks for the next one (e.g. For level 3: 12 member(s) without a section), and its extension: tick the base or one of them.
Choose (or Enter, or a double-click on a row) takes the type and the extension; Cancel (or Escape, or closing the window) changes nothing. A table of many types scrolls; the buttons stay in view.
Colour tool#
A small window to choose a colour. At the top, Wheel or Sliders (your choice is remembered):
- Wheel: click or drag on the wheel. Round it is the hue (red to the right, green up left, blue down left). Outwards is the saturation (grey at the centre). The slider below is the brightness.
- Sliders: red, green and blue (0–255), and hue (°), saturation and brightness (%).
Below, the old and the new colour side by side, and the new one as #rrggbb (type one there too).
The palette is your list of colours, in a box that scrolls. Each has a name, its colour and what it is used for (e.g. "380 kV circuits", "earth wires"). A click takes a colour; a double click takes it and closes the tool. Type a name and a use and press + Add to add the new colour. ⏶ ⏷ move a colour, ✏ edits its name, use and colour, 🗑 deletes it (asked first). Defaults adds the program's own colours (phases, wires without a phase number, electrical systems) that are missing.
Export… writes the palette to a file to share. Import… reads one: replace your palette, or add the colours not in it yet. A file that does not read is refused, with what is wrong. The file is TOML (.ohlcolors):
format = "ohl-colors"
version = 1
[[color]]
name = "Phase 1"
color = "#e4572e"
description = "380 kV circuits"
The palette is yours: remembered on this computer, not in the project. OK uses the new colour; Cancel (or closing the window) changes nothing.
Routes and alignments#
A line is laid out in three steps, kept as three kinds of record in the project: a route (a path of the line), its alignments (each on exactly one route, in their order along it) and the alignment points (PIs) of each alignment, in order. An alignment cannot exist without its route. A point is an object of its own: it may be on no alignment yet, on one, or on several — with its own place (order number) in each. Where alignments of different routes meet they share the point, so the point — and a structure tied to it — is on all their routes. Structures, sections, jumpers and what hangs on structures are put on routes from the alignments, nothing to keep by hand:
- a structure tied to an alignment point, or within 5 m of an alignment, is on that alignment's route;
- a structure away from every alignment (a crossing line) is on no route until you give its route(s) — in its window (Edit, or when placing it) or the Structures table's routes column; it is said in yellow after an edit, and in its properties;
- a section is on the routes of its structures (one running from a route into another is on both), a jumper on those of its two ends.
A new project starts with these steps (its first window): 1. the route — its name and description; 2. its alignment — the New alignment tool is then held.
The points are drawn in the 3D view (cyan, on the ground) and in the plan — those on no alignment too — and can be clicked (Edit › Snap, alignment points). The profile follows every change at once.
-
Terrain › Routes: one row per route — its id (renaming: its alignments and structures follow), name, description, its alignments in order, how many structures and sections are on it. + Add row makes a route; deleting one asks first and lists its alignments (they go with it; their points stay).
-
Terrain › Alignments: one row per alignment — its id, name, route (a dropdown of the routes; required), its order # (3.5 goes between 3 and 4), how many points, description. + Add row makes an alignment (without points yet); with no route yet, + New route… / Create the route above the table makes one. Deleting an alignment keeps its points.
-
Terrain › Alignment points: a row per point and alignment it is on — its alignment (a dropdown), its place # there, the point's id, E, N, z, the structure it is tied to, the other alignments it is on with its place there (also on), description. A point on two alignments has two rows, each with its own #; a point on none has one row without alignment. A row deleted takes its point off that alignment only (the others keep their order); the point itself is deleted with the last of its rows. (The Delete tool on a point on several alignments asks: Delete from all — the point goes — or Take it off the ticked ones, its alignments listed with their routes and ticked in a scrolling list; a point on one alignment is deleted as before.) Alignment ▾ above shows one alignment (or the points on none).
- # orders the points of an alignment (3.5 goes between 3 and 4); another alignment moves the row's point there; none takes it off that alignment (it stays).
- + Add row with an existing point's id puts that point on the alignment too (shared); a new id makes a new point.
- Deleting a row deletes the point: it comes off every alignment it is on (asked first when on several), the other points keep their order.
-
New alignment (tool) lays out an alignment point by point. Each right-click adds a point:
- on an alignment point: that point, shared (a junction);
- on a structure: a new point tied under it;
- on a survey point or LiDAR point shown (within 12 pixels): a new point at its exact E, N and height;
- on nothing of these: a window asks for the point's E, N and height (all required; where you clicked is offered).
Enter asks for its route (one: the route worked on, or that of the points it shares, is chosen; + New route makes one — with no route yet, it offers to create one), then makes it (alignment 1, alignment 2…). Backspace takes the last point back, Escape gives it up (the tool stays held).
-
Add alignment point (tool): a right-click on a survey or LiDAR point, a structure (tied under it) or the ground opens its window — its E, N and height (given by what was clicked), and connect it to the nearest alignment: ticked, it goes between the two closest points of the nearest alignment; unticked (the default), it is on no alignment yet — New alignment then picks such points one after another, like the String wire tool picks strings.
-
Edit alignment (tool) changes the course of an alignment. Right-click one of its points, then the new points (snapped as for New alignment; an existing point is shared), then:
- another point of the same alignment: the points between the two are replaced by the new ones (those taken off stay, on no alignment unless on another);
- Enter, from its first or last point: the new points are added there, before its first or after its last;
- Enter, from a point in its middle: an alignment has two ends only, so it branches — a new alignment from that point through the new ones is offered, its route asked as for New alignment.
Backspace takes the last point back, Escape gives it up.
-
Edit (tool) on a point opens its window: E, N, z or on the ground, tied to a structure, and the alignments it is on with its place (#) in each — ✕ takes it off one, + on another alignment… puts it where it fits along that one. A shared point is one point: moved, it moves on all its alignments.
-
Delete (tool) deletes a point: off every alignment it is on (asked first when on several); the other points keep their order. An alignment may be left without points.
-
View › Work on route (yours only): the profile shows that route, the checks (clearances) and the structure loads keep to it, and everything else is drawn faded in the 3D view and the plan.
Files and projects of older versions are read into this form once (see line file): each alignment's points become points of their own, shared where alignments met; an alignment on several routes becomes one per route.
Library editors#
A project keeps its libraries. The wire library, the structure types, the insulator assemblies, the weather and load case files, the structure models (.ohlfe) and poles (.ohlp), the section library (.ohlsec, the profiles the structure models' members refer to: see Section library), the clearance rules (.ohlr), galloping parameters (.ohlg), thermal ambient cases (.ohlta) and unit costs (.ohlcost) are stored in the project file (.ohl), so the project alone is everything needed to open it elsewhere. Opened the first time, each kind the project does not hold yet is copied into it from where it was read (the files given, next to the project, or the default folders; structure models and poles from the structure folder, the section library from the Sections/ folder next to the project, else the .ohlsec files next to it — never the shipped example; the others from next to the project); the line's structure checks (fe) use the project's section library; a library given on the command line (--library, --structures, --insulators; --weather adds its file) replaces the project's. Every save of a library page or of the weather case table goes into the project. File › Export › Libraries… writes them all as files into a folder (a folder per kind), and Export… on a page writes the file open: to share them, or to compare them with other data. A user who may not change the project (a viewer) reads the libraries from their files as before. (The model reads working copies in a temporary folder; the project is what is kept.)
The Structures, Sections and Criteria menus open an editor for the wire library (.ohlw), insulator assemblies (.ohli), structure types (.ohls) or weather cases (.ohlwc) — first the files the model reads: the wire library given or next to the model, Structures/ next to it, the insulator directory, the weather case file. Choose one of them, Browse… for a file anywhere on the computer (in a project: copied into the project; while the library is empty it starts at the examples shipped with OpenOHL — libraries/cables, libraries/insulators, the starter template's structure types, weather and load cases: invented or typical values, not for design), or New file… to create one from a template (in a project: in the project, under the name chosen). An empty library says so on its page. Where a cable is chosen (a section's or a jumper's window) and the wire library is empty, the window says so with Open the wires library; the Structure loads page without a load case file says so with Open the Load cases library. For wires and weather cases the list on the left holds the items (Add, Duplicate, Delete).
Use for the model makes the model read the file open: the wire library or the weather case file itself; the folder of an insulator or structure type file. The model is solved again; a wire library without every cable the line uses is refused (the cables missing are named) and the model keeps its own.
A cable starts with its model — a list of the three cable models (non-linear; linear with creep proportional to the creep case tension; linear with a temperature increase) — and the Bimetallic conductor tick (a core with its own data; unticked, the core goes): choosing a model adds the fields it needs (the outer and core curves with their creep curves, or the creep temperature shift, and its tension) with example values, fields it does not use are hidden (kept in the file), and the fields a cable or its model needs cannot be removed (their 🗑 is greyed). A bimetallic cable has its own behaviour above the transition temperature, below the tick: its outer strands go into compression up to its maximum virtual compressive stress, or take none (bird cage). Sections written as [cable.outer] tables are edited like inline ones.
Every field is shown as written in the file, with its units ("28.1 mm", "55 GPa", "-5 °C"); numbers and lists as TOML (23e-6, ["clearance", "loads"]). add a field… offers the fields of that kind not yet given, with an example and their meaning; 🗑 removes one. A structure type's points, wire points and strings (and version 1 attachments) are listed below its fields (add, duplicate, remove); its body and design — joints, members, materials, sections, generators, the pole, extensions, load cases — are named there and edited in the structure application (Open this type in OHL-Structure…). Comments and layout of the file are kept.
The structure screen#
The Edit tool on a structure (or a right-click with it), and Strings and points… in a structure's properties, open its structure screen: for a typed structure, its type on the Structure library page (Pylon, next to Fields); for a structure without a type, the Structure editor. The screen is split: the tables on the left, the pylon in 3D on the right — drag the divider between them (it starts at about 45/55 and keeps its place while the program runs).
Only the basics are edited here: the attachment points, the strings (insulator, length, weight, compression, strain) and the wire points with their sets; with the structure's name, type, extension and height adjustment in its properties and its Placement… window. The body — joints, members, sections, materials, supports, generators, the pole, extensions — and the design (load cases, analysis) are drawn in the view for context and edited in the structure application: Open this type in OHL-Structure… at the top of the screen.
-
The top line gives the level worked out from the file (detail levels), the counts of attachment points, strings, wire points and sets, how many structures of the line use the type (they follow when it is saved) and Open this type in OHL-Structure…; below it, how many joints and members the body has.
-
In the view (x to the right of the line red, y ahead green, z up blue, 0;0 at the centre, the ground grid at the level of its feet): drag to turn, right-drag to pan, the wheel to zoom, Fit to see it whole. A click picks an attachment point (orange) or a wire point (blue, with its set); Shift + click picks another. Joints and members are not picked: members with a section are steel grey, without one (sticks) sand-coloured; supported joints green.
-
Drag an attachment point or a wire point to move it, in the plane facing you; it snaps to the snap grid (default 5 cm; 0: none) or onto a joint near the pointer. A point on a joint or along a member moves with the body: the screen says so (move it in the structure application).
-
+ Attachment point adds a free one (mirrored across from the point picked, else at the top of the centre); the I and V presets hang an insulator of the length given from the point picked (or a V from the two picked) to a new wire point — its set is put by hand in Set points (only pylon templates number sets themselves); Delete… lists everything that goes with what is picked (a point: its strings) and asks.
-
Tables, what hangs on the structure:
- Attachment points — where insulators hang on the structure: a position, or the joint or member they sit on; free ones moved here (dragged, or typed); how many insulators hang from each. Moving one takes its insulators' wire points along.
- Insulators — each string: what it hangs from (an attachment point, or another insulator's wire point: a TAK), its wire point (where it ends; another insulator's makes a V), its kind (suspension: the wire runs through its set; strain: the wire ends there), an assembly of the insulator library (its length, weight, wind area; a strain assembly makes it strain) or none and a length, its angle from straight down (0° hanging, 90° level) and direction in plan (in the project's angles), weight, wind area, the compression it may take, a description. The length and the angles place its wire point; a V's legs show their directions (they follow where their lengths meet). There is no "ahead" or "back": the angles alone say where it points. + New insulator hangs one from the point picked (the length given) to a new wire point; From the library… hangs an assembly of the library there; Save to library (on a row) writes that insulator as an assembly of the insulator library (a V's leg as a V-string assembly); 🗑 deletes it (its wire point with it when nothing else is on it); Insulator library… opens the library to import, export, edit or delete assemblies.
- Wire points — where an insulator ends: their position, placed by their insulator(s) (typed only for one no insulator reaches: fixed), the insulators holding each and those hanging from it, its set, a counterweight.
- Set points — where a wire is strung: the set number (typed by you; unique on the structure), the wire point it is on (moved to another with this list), its kind from its insulator (suspension or strain; fixed without one), 🗑 to take it off; + Set on wire point… puts one (the next free number) on a wire point without a set. On a structure (Apply), a set renumbered takes the sections and jumpers strung there along — two sets swapped too.
The file's other fields are in Fields. Hover a column title for what it means.
A structure without a type opens on the same screen, the Structure editor, in a window of its own (drag its tab into the main window to dock it), with its points, wire points, strings and stick drawing in its own axes. Nothing changes on the line until Apply (one command, one undo); Revert goes back to the structure as it is. Make it a type… saves it as a structure type of the project (in its structure types folder, else a Structures folder next to the line), gives the structure that type — its points and strings then come from the type — and opens the type. It has no file of its own, so the structure application has nothing to open: its Edit… (in Properties, or Open this type in OHL-Structure… in the Structures table) opens this screen with Make it a structure file and edit it… asked — type the new type's id and press Save, use and edit: the type is made as with Make it a type…, and the structure application opens on its file.
Open in OHL-Structure… — the structure application. Open in OHL-Structure… in a structure's properties, Open this type in OHL-Structure… on the structure screen, on the Structure library page (with Fields) and in the Structures table (right-click a row's ⤴) open the structure in the structure application, a window of its own, on the structure's file — in a project, the project's working copy of it. With unsaved changes on the page it asks to save or discard them first (the structure application edits the file as saved). When it is saved there, the line application takes the file back into the project and reads the structure libraries again, as when the Structure library page is saved: every structure of the type follows, and the page shows the saved text (if it has unsaved changes of its own, it says so and keeps them).
ohl-structure is looked for in the program the OHL_STRUCTURE_APP
environment variable names (its former name OLS_STRUCTURE_APP is read
too), then next to ohl-design (and the folder above it), then on the
PATH; where it is not found, under its former name ols-structure. What goes wrong is shown in a window of its own
(the text in a box that scrolls, closed with Close), and written to
the log:
- not found — the folders it looked in and how to build it:
cargo build --release -p ohl-structure-app(in the OpenOHL folder; it lands next toohl-designintarget/release). Start OHL-Design.command builds both; - another build — before it starts it, the line application asks
ohl-structure --versionand compares the build with its own; when they differ it starts it anyway and warns: rebuild both,cargo build --release -p ohl-app -p ohl-structure-app; - it stops with an error — its error output (what it wrote before it stopped), e.g. a file an older build cannot read.
Open in OHL-Structure… on a placed structure (its properties) also hands over that
place's loads (Started for a placed
structure): the line
application computes the loads of the line's load cases (Criteria › Load
cases) at that structure in the background and writes them beside the
structure file (<name>.<structure>.line-values.json); while the
structure application is open, a change of the line (once it has stayed
unchanged for a second) computes and writes them again, and the window
follows. Values typed over its load table there are saved as
<name>.<structure>.loads.csv; in a project the line application keeps
them in the project with that structure (library kind loads, per
project line) as soon as they are saved, and the status line says so.
The project's section library goes along for the members' areas. One
structure application runs per structure file: Open in OHL-Structure… on another
structure of the same type while one is open says so.
A structure type on its own: ohl-design pylon.ohls, File › Open (choose a .ohls) or the start page's recent files open a structure type file without a line: its editor is the whole window — the structure screen and the file's fields (Fields), Save (⌘S), the other types of its folder in the list, Open this type in OHL-Structure… for its body. The insulator assemblies of its folder (and of an Insulators folder there) are those its strings may take. Which angle means ahead is yours for files opened alone (at the top, remembered on this computer); a project has its own (Structures › Angles around structures). Unsaved changes are asked about before another file opens. In a project, the same editor is the Structure library page, and Strings and points… opens a structure's type in it; what the type gives — its points, strings and wire points, with their descriptions — comes into the line with every structure of that type.
Everything changes the file as edited: Save writes it (the line follows), Discard drops the changes.
The file is checked as you type with the library's own reader; the error is shown and Save waits until it reads. After saving, the model reads its libraries again, resolves the structure types and solves every weather case; a page with unsaved changes shows * and does not close.
Controls#
The 3D view is navigated with the mouse and, while the pointer is over it, the keyboard — like Minecraft in creative mode:
| Input | Action |
|---|---|
| W / S | forward / back along the ground, in the direction of view |
| A / D | left / right |
| Space / Shift | up / down |
| Ctrl (held) | four times faster |
| scroll | zoom |
| right or middle drag | pan |
| double-click | fly to the object |
| G | go to a structure: a window with every structure in a list; Enter goes (selects it, brings the 3D view within 150 m and centres the plan), Escape closes |
Two schemes, chosen in Help › Controls › 3D (with the speed, the look sensitivity and every key and mouse action; the 3D view shows no help text over it, only "Esc: free the mouse" in first person). Help › Controls › Plan and Profile list how those views are moved and used (more settings will come there):
- Orbit — left drag turns the view around the point looked at.
- Minecraft creative — first person, as in the game: clicking the 3D view captures the mouse (locked and hidden); moving it looks around (mouse down: look down); a crosshair marks the centre and a click selects what is under it (double-click flies to it); Ctrl + wheel sets the speed (the wheel alone scrolls the hotbar). Escape frees the mouse to use the panels (switching to another application frees it too; while a wire is strung or an alignment laid out, the first Escape gives that up and the second frees the mouse).
The speed (m/s) and, for the first-person scheme, the look sensitivity are set there too, and the list shows every key of the scheme. The scheme, speed and sensitivity are remembered for the next start; --controls orbit or --controls minecraft chooses one at start. Schemes are data (controls.rs: actions bound to keys and mouse buttons), so schemes familiar from other software can be added as presets, and later edited and saved.
Edit › Snap: what can be clicked chooses what can be clicked: structures, spans, jumpers, wire points and string tops (selecting their set), alignment points, LiDAR points (more kinds will be added); by default structures, spans and jumpers. At about the same distance, a point wins over the line it sits on and a structure over a wire. The choice is remembered.
Clicking an object in any view selects it everywhere: a structure anywhere along the lines it is drawn with (mast or stick drawing, arms), a string anywhere along it where it is drawn (as solved in the case shown — with the wind from both sides, each of the two; a jumper's helping strings too; its properties give where it hangs, its wire point, set, length, weight, wind area, dead end and its force in the case shown), attachment points (Snap) where the clamps are drawn, a span anywhere along its wire, a jumper anywhere along it (drawn as a bundle like its section). The properties of a jumper show its cable, section, bundle (and whether it is its own or its section's), length or sag, support string or helping strings, results in every weather case, and the force in each string holding a support clamp in the case shown ("slack" when it is), in a box of fixed height. In the 3D view the strings holding a jumper's clamps are drawn to the clamps as solved, and each clamp as a short bar along the jumper. Tabs can be dragged to rearrange the window.
Loading runs in the background. On a real 25 km line with 99.6 million LiDAR points stored in its project, the window is ready in about 8 s (release build): the whole cloud decoded (every one of its 31 classes shown, 2.1 million points), a 5-million-triangle ground surface.
Plugins#
Plugins › Plugin manager… lists the plugins found: those installed for you (in the application's data folder, plugins/) and those of the folders you added (used where they are — handy while writing one). For each: its version, kind (WebAssembly or Python), what it provides (a file-format plugin's formats), and why it cannot be used if it cannot (another interface version, permissions asked for that cannot be granted, its entry file missing — e.g. not built). The tick turns a plugin on or off. The folders added and the plugins turned off are kept in settings.toml in your plugin folder, shared with OHL-Structure (its Plugins › Plugin manager lists the same plugins): changed in one application, the other reads it when its manager opens (here: Reload); before that file exists, what this application remembered itself is taken. Install from a folder… copies a plugin into your plugins (a WebAssembly plugin's manifest and .wasm; a Python plugin's folder); Remove deletes an installed copy (after a confirmation). A plugin name found twice is used from the first place (your plugins, then the folders in order).
File-format plugins add their formats to File › Import › Into the line / Export › The line, next to the built-in ones. They run on a worker thread, sandboxed, with time and memory limits (Writing plugins).
Python console#
Plugins › Python console opens a page with a Python interpreter in the application (Python 3.10+, the one OpenOHL was built with). Type code and press Enter (Shift+Enter: a new line; ↑ ↓: history); the value of a last expression is printed. Run a file… runs a script as __main__; Plugin scripts lists the Python plugins turned on. Stop interrupts a script (KeyboardInterrupt); a script running longer than the time limit (default 300 s) is stopped.
The ohl module drives the open project:
| Call | (no heading) |
|---|---|
ohl.line() |
the working line, as in a line file (a dict) |
ohl.cases(), ohl.case() |
the weather cases, the one shown |
ohl.results(case=None) |
the solved sections of a case: per span sag, horizontal and largest tension, mid and low points; what failed |
ohl.selection() |
the selection, in words |
ohl.apply(command, what=None) |
a session command (as in the operation log, e.g. {"op": "move_structure", "id": "T2", "position": [x, y, z]}): validated, logged, undoable; what it touches is solved again. A refused command raises |
ohl.batch(commands, what=None) |
several commands as one (all or none, one undo) |
ohl.undo(), ohl.redo() |
your last command |
ohl.status(text) |
text in the status bar |
ohl.convert(kind, value, unit) |
unit conversion, as in the ohl package |
import ohl
for s in ohl.results("everyday")["sections"]:
print(s["section"], max(p["sag"] for p in s["spans"]))
Each call is answered by the application at its next frame, so a script always sees the line as it is now; many edits go faster (and undo at once) in one ohl.batch. A read-only project refuses edits.