Skip to main content
Version: 3.4.8 (unreleased)

Grow Planar Patches

Grow Planar Patches extracts the planar surfaces exposed on a triangulated mesh — bedding planes, fracture and fault faces — as patches of triangles, each with a fitted plane, its dip and azimuth, its size and its quality. It measures the mesh first and derives its own parameters, so on most outcrops the defaults are a usable starting point.

It is the newer of VRGS's two patch tools. Auto Structural Mapping grows on orientation similarity alone; this tool fits a plane as it grows and tests candidates against both the plane's normal and their distance from it, which is what tells “the same surface” from “a parallel surface a step away”. Both write the same‑named attribute layers, so results can be compared on one mesh.

The method, stage by stage and with the formulas, is described in Grow Planar Patches — Method.

Typical Workflow

  1. Select the mesh in the Project Tree and open Extract → Grow Planar Patches. On a mesh it has not been run on, the dialog measures the mesh and fills every field; the read‑out says what it found.
  2. If the automatic Feature Radius does not suit the outcrop, set it to about the size of the smallest face you want extracted and press Suggest.
  3. Press Apply. When the run finishes the mesh is coloured by Patch Colour, one colour per patch, and the messages panel summarises the run.
  4. Judge the result on the model. If faces are broken into many small patches, press From Run and Apply again; if distinct faces have run together, lower Angle Tolerance or Distance Tolerance.
  5. When the patches look right, set Cluster into Sets, tick Create Objects if you want one orientation measurement per patch, and press OK.

To extract a single fracture set, see Extracting One Fracture Set.

Grow Planar Patches or Auto Structural Mapping?

Grow Planar PatchesAuto Structural Mapping
Grows onFace normals, smoothed only as much as the measured noise needsPer‑vertex Dip and Azimuth from Tensor Analysis, or face normals
A candidate is tested againstThe patch's plane: its angle and its distance, both suggested from the meshThe seed's, the current triangle's or the running mean orientation, with an optional distance
BoundariesMoved afterwards to where neighbouring planes actually meetWherever growth stopped
ParametersMeasured from the mesh, refined from a run, remembered per meshSet by hand
Sets and filteringClusters the patches into sets; keeps a dip/azimuth range or the planes near one orientationDip and azimuth range filter
WritesThe patch layers, with Patch Set when it clusters; objects per patch or per setThe same patch layers but Patch Set; objects per patch

Start with Grow Planar Patches. Auto Structural Mapping remains useful when you already have tensor Dip and Azimuth layers computed over a neighbourhood you trust, or want its dispersion and resultant‑length acceptance tests.

Prerequisites

  • A selected TriangulatedMesh in the Project Tree. No attribute layers are needed: the tool works from the mesh's own face normals.

Launch

  • Project Tree: select a triangulated mesh, then Extract → Grow Planar Patches.
  • Opening the dialog on a mesh it has not been run on measures the mesh and suggests every field. On a large mesh this takes a few seconds, and longer the first time if the triangle adjacency has to be rebuilt. On a mesh it has been run on, it restores the last parameters instead (see Remembered Parameters).
  • Apply runs without closing; OK runs and closes; Suggest re‑measures the mesh and refills the growth fields; From Run refines them from the last run in the dialog. Neither touches the orientation filter, which is your choice rather than a measurement.

Progress shows in the messages panel as a planegrow progress bar, and each run ends with one summary line: patches, initial regions, merges, boundary moves, rejections, filled holes, absorbed fragments, assigned triangles and the measured normal noise. A filtered run adds a second line with the filter, the patches it kept and refused, and how many triangles face the wanted way.

Dialog Fields

Growth

  • Angle Tolerance (deg): largest angle between a triangle's (smoothed) face normal and the patch normal. Also the merge angle.
  • Distance Tolerance: largest distance, in model units, from any vertex of a candidate triangle to the patch plane. 0 disables the test and growth is angle‑only.
  • Normal Smoothing Passes: crease‑preserving smoothing of the face normals before growth, over the ring of triangles around each vertex. Each pass widens the support by one ring. 0 grows on raw normals.
  • Refinement Passes: boundary relabelling passes after merging, and fragment‑absorbing passes after rejection.
  • Merge Co‑planar Patches: merge adjacent patches whose planes agree in angle and mutual distance.
  • Fill holes up to: absorb unassigned islands enclosed by a single patch up to this many triangles. 0 disables.
  • Feature Radius: the size of face the parameters are tuned for, in model units. It is the radius of the neighbourhoods the measurement samples. 0 lets Suggest choose: the larger of eight times the mesh resolution and half a percent of the model's diagonal.
  • Read‑out: what the measurement found (see below), or after a run, what the run found.

Acceptance

  • Minimum Triangles: patches with fewer triangles are rejected and their triangles left unassigned. 0 disables.
  • Minimum Area: patches smaller than this area (squared model units) are rejected. 0 disables.

Orientation Filter

Limits a run to the planes you are interested in — one fracture set, only the steep faces, only bedding. Two tests, each with its own tick box; with both ticked a patch must pass both. Dips and azimuths are the ones the tool reports (the Patch Dip / Patch Azimuth layers, the per‑set lines in the messages panel, and orientation objects): azimuth is the dip direction.

  • Keep only patches in a dip and azimuth range: Dip from … to … and Azimuth from … to …. The azimuth window runs clockwise from the first value to the second and may pass through north (340 to 20). Leave the azimuths at 0 to 360 for a dip‑only filter such as “everything steeper than 60”.
  • Keep only patches near one orientation (a fracture set): Within (deg) of dip / azimuth. The angle is measured between the poles as axes, so a steep set keeps the planes leaning either way: 88° towards 090 and 88° towards 270 are four degrees apart, and both are within 15° of 90/090. A dip and azimuth range cannot express that in one window, so use this test for steep sets.
  • From Set: fills the second test from set n of the last run in the dialog that clustered sets — the set's mean dip and azimuth, and a cone sized to hold about 95% of a set with that much scatter (between 5° and 45°).

See Extracting One Fracture Set.

Outputs

  • Cluster into Sets: number of orientation sets to cluster the patch poles into. 0 disables.
  • Create Objects: one strike/dip orientation object per patch, in a “Plane Growing” group, or one group per set when clustering ran.

Suggested Parameters

Suggest measures the mesh and fills every field. The read‑out shows the measurements:

  • Resolution: sqrt(mean triangle area), and the triangle count.
  • Adjacent‑normal noise: the median angle between the normals of edge‑adjacent triangles, raw and after the suggested smoothing. This is how rough the mesh is at the triangle scale.
  • Within r = Feature Radius: 256 evenly spaced neighbourhoods of that radius, each fitted with a plane. The read‑out gives, for the flatter quarter of them (where a face will actually be grown): the 90th‑percentile scatter of the face normals about the fitted plane, the 90th‑percentile node offset from it, the RMS residual, and the triangle‑scale step.

From those:

  • Smoothing passes = one per 6° of raw noise (1–6); the smoothing sigma is 1.5 × the raw noise, clamped to 5–45° and never below the tolerance. On a clean mesh this is one pass; on a rough photogrammetric surface several.
  • Angle Tolerance = the larger of twice the smoothed noise and 1.2 × the neighbourhood normal scatter (5–30°). The first keeps a flat, noisy area from fragmenting by its own noise; the second keeps a clean but undulating face, whose adjacent normals differ by a few degrees while the face wanders tens of degrees end to end, from fragmenting into micro‑facets.
  • Distance Tolerance = 1.5 × the neighbourhood node offset, never below twice the triangle‑scale step.
  • Minimum Area = a quarter of the feature radius squared; Minimum Triangles 20; merge on; refinement 3; holes up to 10.
tip

The Feature Radius is the main knob. Faces smaller than about half of it are treated as noise at that scale; faces much larger than it may still be split where they undulate. Set it to the size of the smallest surface you want extracted, press Suggest, and adjust from there.

Refining From a Run

After every run the read‑out shows what the run measured inside its patches — the median angle between adjacent smoothed normals within a patch, and the area‑weighted median RMS residual — together with the fraction of triangles assigned and what From Run would set. These measurements come from the mesh's confirmed planar areas, so unlike the sampled neighbourhoods they never straddle a crease.

From Run applies the rule:

  • If less than half of the mesh was assigned, the run is taken as too tight: the angle tolerance is raised by a quarter and the distance tolerance by a half.
  • Otherwise the angle becomes twice the intra‑patch noise and the distance three times the patch roughness, each damped so one step never tightens by more than a quarter.

Everything else is kept as it was. Run, look at the read‑out, press From Run, run again.

With an orientation filter the “fraction assigned” is counted against the triangles that face the wanted way rather than against the whole mesh, so extracting a set that covers a tenth of the outcrop is not mistaken for a run that was too tight.

Extracting One Fracture Set

  1. Run once with the filter off and Cluster into Sets set to the number of sets you expect. The messages panel lists each set's mean dip and azimuth, its area and its concentration, and the Patch Set layer shows where each one is.
  2. Type the number of the set you want beside From Set and press it. The second filter test is ticked and filled with that set's orientation and a cone sized from its scatter. Or type a dip, an azimuth and an angle of your own — from a stereonet, or from an orientation you measured.
  3. Set Cluster into Sets back to 0, or leave it to cluster the sets again within what is kept, and press Apply. Only the patches of that set are produced; the rest of the mesh is left unassigned. With clustering off, the run removes the Patch Set layer from step 1, whose set numbers described step 1's patches.
  4. Widen or narrow Within (deg) and run again. Filtered runs are quicker than full ones, because surfaces that face the wrong way are never grown.

The filter decides which patches are kept; it does not change how a patch grows. A kept patch has the same members the tolerances would give it in an unfiltered run, give or take the triangles along its edge that a neighbouring, now absent, patch would have claimed. The final decision is made on the fitted plane, so every value in Patch Dip and Patch Azimuth satisfies the filter exactly.

Remembered Parameters

The last‑used parameters, the orientation filter included, are remembered per mesh: for the session by the mesh itself, and across sessions in the application profile by mesh name. Opening the dialog on a mesh you have run before restores them and says so in the read‑out; Suggest re‑measures the mesh on demand and leaves the filter as it is.

What It Writes

Triangle attribute layers, 0 on unassigned triangles except where noted:

  • Patches (int): patch id, largest patch first.
  • Patch Colour (float): the id scrambled onto the colour ramp so neighbouring patches contrast. This layer is left active after a run.
  • Patch Size (int) and Patch Area (float).
  • Patch Difference (float, degrees): angle between the triangle's raw face normal and its patch plane.
  • Patch Similarity (float, 0 to 1): the cosine of Patch Difference, 1 for a triangle lying in its patch's plane and 0 for one at right angles to it. It is Auto Structural Mapping's measure, written here too so that both tools write the same layers.
  • Patch CoPlanarity (float): Fernandez's M of the patch's node set, on the same scale as the per‑vertex CoPlanarity attribute (0 below four nodes).
  • Patch RMS Residual (float): RMS node distance to the patch plane, model units.
  • Patch Length / Patch Width (float): in‑plane extents of the fitted plane.
  • Patch Dip / Patch Azimuth (float, degrees): of the fitted plane; azimuth is the dip direction. Unassigned triangles have no value in these two, rather than a 0 that would read as a horizontal plane.
  • Patch Set (int): orientation set, when clustering ran.

Auto Structural Mapping writes all of these but Patch Set, which only a run of this tool with Cluster into Sets above 0 writes. Each run replaces the layers, and removes a patch layer it did not write rather than leave it describing an earlier run's patches: a run without clustering, or an Auto Structural Mapping run, removes the Patch Set left by a clustered run. The messages panel names any layer removed. If the stereonet's Colour by attribute was Patch Set, the mesh poles take the flat colour while the layer is gone.

Objects (optional): Plane_<id> (<triangles>), built from an even sample of at most 256 of the patch's nodes so a large patch does not drag thousands of vertices into the project. Groups are “Plane Growing”, or “Plane Growing Set k (dip/azimuth)” per set, and the messages panel lists each set's mean pole, area and concentration.

Patches on the Stereonet

There are two ways to get the patches onto a stereonet, depending on what one point on the net should stand for.

  • One pole per patch. Tick Create Objects. Each patch becomes an orientation object, in one group per set when Cluster into Sets is on, and the stereonet plots them like any other orientation measurements. Contouring, selection on the net and the k‑means clustering in Orientations and fracture sets all apply. A small patch counts as much as a large one, so raise Minimum Area first if the small ones should not count.
  • One pole per triangle, straight from the mesh. In the Stereonet window's Contour Properties, pick Patch Dip as the Dip Attribute and Patch Azimuth as the Azimuth Attribute, then set Data Source to Mesh Attributes to contour them, or switch the mesh Poles on to plot them (see Plotting a mesh's dip and azimuth). Every triangle plots with its patch's fitted plane, so a patch counts in proportion to its number of triangles, and no objects are created.
Unassigned triangles stay off the net

Unassigned triangles have no value in Patch Dip and Patch Azimuth, so the stereonet leaves them out: only the patches are plotted, however much of the mesh a filtered run leaves unassigned, and the Attribute Status row counts only the triangles in patches.

Picking a Patch as an Orientation Measurement

Once a mesh carries a Patches layer, the ribbon's Dip / azimuth → Attributes tool turns any patch into an orientation measurement with one click: pick the tool, click the patch on the mesh, and an orientation object named Patch_<id> is created in the active orientation group, its plane fitted through the patch's nodes (an even sample of at most 256 of them). The messages panel reports the patch id, its size and the dip and azimuth.

  • Any layer can be displayed while you click; the tool reads the mesh's Patches layer, so Patch Colour is the convenient one to have on screen.
  • Clicking an unassigned (black) triangle creates nothing and says so.
  • On a mesh without a Patches layer the tool falls back to its original behaviour: an orientation at the clicked point carrying the Dip and Azimuth vertex attribute values there, when those layers exist.

How It Works (Summary)

  1. Signal. Face normals and areas from the geometry, then bilateral (crease‑preserving) smoothing over the vertex‑ring neighbourhood, with the smoothing sigma derived from the measured noise. Normals are treated axially, so inconsistent winding does not matter.
  2. Growth. Seeds in order of local planarity. Best‑first growth against an area‑weighted proxy plane that refits with every accepted triangle. A candidate must be within the angle tolerance of the patch normal and, when a distance is set, have every vertex within that distance of the plane. A candidate rejected against a young plane is tested again when another of its neighbours is accepted. Every eligible triangle lands in exactly one initial patch.
  3. Refinement. Adjacent agreeing patches are merged; boundary triangles move to the neighbouring plane that fits them best; anything disconnected is split; patches below the size limits are rejected; enclosed holes are filled; leftover triangles that fit an adjacent patch join it.
  4. Outputs. A plane is fitted through each patch's distinct nodes for its statistics, patches are numbered largest first, and the layers and objects are written.
  5. Classification. Optionally, the patch poles are clustered into orientation sets by an area‑weighted axial k‑means.

The orientation filter, when on, acts three times, each stricter than the last. Triangles further from every passing orientation than the angle and merge tolerances together never seed a patch, which is where a filtered run saves its time. Patches whose growth plane settles outside the window are rejected along with the undersized ones, before holes are filled and fragments absorbed. And after the final plane fit a patch is kept only if the dip and azimuth it reports pass the filter literally.

Grow Planar Patches — Method gives every stage in full, with the formulas, the suggestion rules and the references.

For developers: CPlaneGrowerDlg drives CMeshPlaneGrower; the algorithm lives in PlaneGrowerCore.h, with a developer note in VRGS2020/MeshPlaneGrower.md.

Tips

  • Compare with Auto Structural Mapping on the same mesh: both write the same layers (all but Patch Set), so the same layers and the same stereonet picks show either tool's patches. Each run replaces the layers of the run before.
  • Display Patch Colour to see patches, Patches to read ids, Patch RMS Residual or Patch CoPlanarity to judge how planar each surface really is.
  • To see the patches over the outcrop image, tick Use Filter on the displayed layer. On Patch Dip and Patch Azimuth that is all it takes: unassigned triangles have no value in those two, and a part of the mesh with no value never takes the colour ramp while the filter is on (inverted or not), so they show the mesh's texture while the patches keep their colours. (Unfiltered, those two layers paint unassigned triangles in the ramp's first colour, the colour of their lowest values.) Every other patch layer holds 0 on unassigned triangles, so on those also raise Filter Minimum just above 0 — 0.04 on Patch Colour, 1 on Patches. This is the natural way to look at a filtered run, where most of the mesh is unassigned on purpose. Narrow the window further (drag the histogram handles in the Charts panel) to pick out particular patches, or a band of dips on Patch Dip.
  • On a mesh of several million triangles a run takes a minute or two; the progress bar shows which stage it is in.
  • Hidden triangles are excluded from growth and never assigned. While the mesh's Use Attribute Filters is on, so are filtered triangles: those outside the window of an attribute with Use Filter ticked. Filters on the patch layers do not count, because a run replaces those layers. A Patch Colour window left on from the tip above therefore cannot confine the next run to the old patches. To grow on part of the mesh, hide the rest, or filter it by another attribute, such as a Dip window for the steep faces.

Troubleshooting

  • Everything fragments into tiny patches: the tolerances are too tight for the surface's undulation. Raise the Feature Radius and press Suggest, or run once and press From Run (it loosens when under half the mesh was assigned). More smoothing passes also help on rough meshes.
  • Distinct faces merge into one: lower the angle tolerance, set or lower the distance tolerance, or turn Merge Co‑planar Patches off.
  • Large unassigned areas: those triangles were in patches below Minimum Triangles / Minimum Area; lower the limits or raise Fill holes up to.
  • Sets look wrong: clustering is area‑weighted axial k‑means with the number of sets you give it; try one more or one fewer set, and check the per‑set lines in the messages panel.
  • A filtered run produces nothing: check the second summary line in the messages panel. If no triangles face the wanted way, the dip or azimuth is wrong for this mesh (remember the azimuth is the dip direction); if triangles do but no patches were kept, the patches there are below the size limits or the window is narrower than the set's scatter.
  • Half of a steep set is missing: a dip and azimuth range keeps only the planes leaning one way. Use Keep only patches near one orientation instead, which treats the two sides of vertical as the neighbours they are.
  • From Set does nothing: it reads the sets of the last run made in this dialog session. Run once with Cluster into Sets above 0 first.