GeometryHelper 13.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package GeometryHelper --version 13.0.0
                    
NuGet\Install-Package GeometryHelper -Version 13.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GeometryHelper" Version="13.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GeometryHelper" Version="13.0.0" />
                    
Directory.Packages.props
<PackageReference Include="GeometryHelper" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GeometryHelper --version 13.0.0
                    
#r "nuget: GeometryHelper, 13.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GeometryHelper@13.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GeometryHelper&version=13.0.0
                    
Install as a Cake Addin
#tool nuget:?package=GeometryHelper&version=13.0.0
                    
Install as a Cake Tool

GeometryHelper

NuGet Version License: MIT

Geometry for engineering drawings and models, in two dimensions and in three, with the label placement that runs on the 2D half. Written in C# and targeting netstandard2.0, so it loads into the .NET Framework hosts that Tekla Structures and AutoCAD provide as well as into modern .NET.

Every comparison that floating point error can affect takes a Tolerance, because coordinates that come out of a BIM model are never exact.

Use the default tolerance. The overloads without a tolerance read Tolerance.Global, which starts as Tolerance.Default: a thousandth of a millimetre for points and for flatness, in a model in millimetres. That is as exact as the corners of a modelled part are: two parts a hundredth apart are apart, and a thin overlap holds what it holds. A finer tolerance cuts as slivers the few ten-thousandths a modeller's rounding leaves faces off flat and parts apart, many times slower; a coarser one, passed to the call that needs it, takes what touches within it for touching. Never new Tolerance(): made so, every threshold is 0. For parts drawn against each other, as a model's are, cut with a SolidBooleanOptions whose Contact takes faces a hundredth apart for touching, and take a part's net body with TrySubtractAll: within a thousandth alone, a part keeps a skin of itself where a cutter's face stood a few thousandths inside it. A body read open, by copies of an edge a hair apart or by a face left out, is closed by TryClose within a gap of its own, a hole filled only where asked, with a report of what it changed or why it would not.

Installation

dotnet add package GeometryHelper

Quick start

using GeometryHelper;            // Tolerance, Angle, OffsetOptions
using GeometryHelper.Enums;      // LineEnd, OffsetJoin, PointLocation
using GeometryHelper.Geometry;   // every Geo type, 2D and 3D
using GeometryHelper.Core;       // every operation

// In the plane: grow a slab, then cut an opening out of it.
var slab = new GeoPolygon2(new GeoPoint2(0, 0), new GeoPoint2(4000, 0),
                           new GeoPoint2(4000, 2000), new GeoPoint2(0, 2000));
var duct = new GeoPolygon2(new GeoPoint2(1000, 500), new GeoPoint2(1400, 500),
                           new GeoPoint2(1400, 900), new GeoPoint2(1000, 900));

GeoPolygon2 grown = slab.Offset(50.0)[0];                 // 4100 x 2100
GeoFace2 pierced = Boolean2.Subtract(grown, duct)[0];     // one face, one hole

// In space: a beam trimmed where it runs into a wall.
var beam = new GeoLine3(new GeoPoint3(0, 0, 0), new GeoPoint3(3000, 0, 0));
var wall = new GeoPlane3(new GeoPoint3(2500, 0, 0), GeoVector3.XAxis);
beam.TryTrimTo(wall, LineEnd.End, out GeoLine3 cut);      // (0,0,0) -> (2500,0,0)

What is inside

Namespace Holds
GeometryHelper Tolerance, Angle, OffsetOptions, GeometryHelperLog, MassProperties3, MeasureComparison3
GeometryHelper.Enums PointLocation, PlaneSide, LineSide, LineEnd, LineExtension, OffsetJoin, VolumeMethod, AreaMethod
GeometryHelper.Geometry 30 immutable shapes: GeoPoint2 … GeoFace2 in the plane, GeoPoint3 … GeoSolid3 in space, arcs and the chains that carry them, and a transformation and a local coordinate system for each dimension
GeometryHelper.Core 35 operation classes, each dimension mirroring the other: Boolean2/Boolean3, Offset2/Offset3, Distance2/Distance3, … plus Arc2, Corner2 for chamfering and rounding, PlanarMap, which carries flat shapes between the two, and Measure3, a body's volume, mass and area read more than one way
GeometryHelper.Spatial GeoBvh2 and GeoBvh3, the bounding volume hierarchies for large chains and meshes
GeometryHelper.Extension turning raw point lists into geometry
GeometryHelper.Arranging label placement: Arranger, ArrangeItem, ArrangeResult, ArrangeOptions, one greedy placement
GeometryHelper.Meshing closed shapes of the plane and flat shapes of space broken into triangles, grids, strips or convex pieces, and bodies cut into the cells of a grid: GeoMesh2, Mesh2, GeoMesh3, Mesh3, MeshKind, MeshOptions, MeshPlacement3, GeoCellGrid3, GeoCell3, CellOptions3, CellAxis, GridAlignment
GeometryHelper.Packing boxes onto sheets of paper: SheetPacker, Sheet, PackOptions, PackResult
GeometryHelper.Export shapes written as OBJ, SVG and WKT: ObjWriter, SvgWriter, Wkt
GeometryHelper.Dxf DXF files read into shapes (DxfReader, DxfDocument, DxfShape), shapes written (DxfWriter), and a drawing edited with AutoCAD's classes and members, Dxf in front: DxfDatabase, its tables and records, DxfBlockTableRecord, DxfEntity and every entity class

Every operation is reachable both ways: the static form names the larger shape first, and the instance form sits on whichever of the two reads better where you are calling from.

Because both dimensions are one assembly, a flat shape in space can be laid out in its own plane, worked on with the whole 2D half of the library, and put back:

GeoCoordinateSystem3 frame = plate.GetFrame();
GeoFace2 flat = plate.ProjectToFace2(frame);
GeoFace3 back = flat.Subtract(openings)[0].ToFace3(frame);

Guides

The whole of it, searchable, with every type and member: https://nguyenthanguth.github.io/GeometryHelper/.

Guide Covers
Shared types Tolerance, Angle, the enumerations, OffsetOptions, GeometryHelperLog; reading, writing and editing DXF files, the editing with AutoCAD's classes and members; a drawing edited step by step and the points to check in AutoCAD
Geometry in the plane points to polygons and faces; extending, trimming, offsetting, combining regions
Meshing the plane triangles, grids of panels or tiles with joints and alignment, strips and convex pieces, edge to edge
Geometry in space points to solids; splitting, boolean bodies, meshes, local frames
Meshing in space flat shapes of space in panels, tiles, strips and triangles; bodies and boxes cut into blocks, bays and lifts; the cases, drawn and checked
Label placement labels placed greedily, clear of each other and of blocked regions
Packing boxes onto sheets drawing views onto A0 to A4 sheets or sheets of a size of their own, a new sheet when one is full

Coverage

dotnet test tests/GeometryHelper.UnitTest --collect:"XPlat Code Coverage"

writes a Cobertura file under TestResults. Only this library is counted.

Build and Test

dotnet build src/GeometryHelper/GeometryHelper.csproj
dotnet test  tests/GeometryHelper.UnitTest/GeometryHelper.UnitTest.csproj

Warnings are errors in CI, and every public member is documented, so a missing XML comment or a stale cref fails the build rather than landing quietly. Every example printed in the guides is also a test.

Licence

MIT. The clipping engine of Clipper2, by Angus Johnson, which is compiled into this package and resolves regions in the plane, is under the Boost Software License 1.0; THIRD-PARTY-NOTICES.md in the package holds its notice.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on GeometryHelper:

Package Downloads
GeometryHelper.IfcConvert

Converts geometry between IFC (via xBIM) and GeometryHelper: points, vectors, matrices, faces, and solids.

GeometryHelper.CadConvert

Converts geometry between AutoCAD and GeometryHelper: points, vectors, lines, polylines, polygons, circles, and bounding boxes.

GeometryHelper.TeklaConvert.2026

Converts geometry between Tekla Structures 2026 and GeometryHelper: points, vectors, segments, planes, coordinate systems, bounding boxes, transformation matrices, and the faces and loops of a Tekla solid. Also reads the objects of IFC reference models into solids placed where Tekla shows them, through GeometryHelper.IfcConvert. Built for Tekla Structures 2026; install the package whose year matches your Tekla.

GeometryHelper.TeklaConvert.2020

Converts geometry between Tekla Structures 2020 and GeometryHelper: points, vectors, segments, planes, coordinate systems, bounding boxes, transformation matrices, and the faces and loops of a Tekla solid. Also reads the objects of IFC reference models into solids placed where Tekla shows them, through GeometryHelper.IfcConvert. Built for Tekla Structures 2020; install the package whose year matches your Tekla.

GeometryHelper.TeklaConvert.2025

Converts geometry between Tekla Structures 2025 and GeometryHelper: points, vectors, segments, planes, coordinate systems, bounding boxes, transformation matrices, and the faces and loops of a Tekla solid. Also reads the objects of IFC reference models into solids placed where Tekla shows them, through GeometryHelper.IfcConvert. Built for Tekla Structures 2025; install the package whose year matches your Tekla.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
13.2.0 0 11/1/2026
13.1.0 71 10/29/2026
13.0.0 96 10/28/2026
12.3.0 260 10/23/2026
12.2.0 263 10/14/2026
12.1.0 238 10/12/2026
12.0.0 258 10/7/2026
11.2.0 240 10/6/2026
11.1.0 255 10/6/2026
11.0.1 259 10/5/2026
11.0.0 274 10/5/2026
10.0.0 269 10/3/2026
9.0.2 268 10/1/2026
9.0.1 257 10/1/2026
9.0.0 264 10/1/2026
8.0.0 262 9/30/2026
7.0.0 247 9/29/2026
6.3.0 253 9/29/2026
6.2.0 253 9/29/2026
6.1.0 253 9/28/2026
Loading failed

NEW IN 13.0.0

     BREAKING, the DXF names
     - The DXF types move from GeometryHelper.Export to GeometryHelper.Dxf: a using GeometryHelper.Dxf; replaces or
       joins using GeometryHelper.Export; for DxfReader, DxfWriter, DxfDocument and every other Dxf type. ObjWriter,
       SvgWriter and Wkt stay in GeometryHelper.Export.
     - The reader's shape, DxfEntity, is DxfShape: DxfDocument.Shapes and DxfBlock.Shapes for Entities,
       DxfWriter.Add(DxfShape) and new DxfShape(...). DxfEntity is now the entity of the editing model, as AutoCAD
       names its own.
     - DxfGroup is DxfTypedValue, as AutoCAD's TypedValue: Code is TypeCode, a short, and Value is as it was.
       DxfGroup is now a GROUP of the drawing.
     - DxfUnits has AutoCAD's names, every number as it was: Undefined (was Unitless), Millimeters, Meters,
       MicroInches, Dekameters, Astronomical, USSurveyFeet and the rest. DxfReadOptions.ToMillimetres is
       ToMillimeters, and DxfShape.Colour, TrueColour and Lineweight are Color, TrueColor and LineWeight.
     - A reflection diff against 12.3.0 finds 119 public members removed, every one of them moved or renamed as
       above, and 3 168 added.

     BREAKING, three-point arcs
     - GeoArc2 and GeoArc3.FromThreePoints throw for many points nearly on one line that gave an arc before: of
       300 000 random triples at a thousandth, 35 100 of 45 415 arcs in the plane and 26 071 of 36 386 in space are
       refused. Catch the refusal and take the points as a line, or pass a tolerance of nought for the shallow arc.

     NEW, editing DXF drawings
     - DxfDatabase opens a DXF of R12 to R2018 to edit it as AutoCAD's Database edits a drawing: Open(path),
       Open(stream) or Parse(text), then Save(path), Save(stream) or ToText(). Saved with nothing changed, a file is
       written back byte for byte, comments, code page and the records the library does not read included; a change
       writes only the records it is about. 100 000 lines of 10.5 MB open and save in 36 ms on .NET 10.
     - The classes are AutoCAD's with Dxf in front, used directly, with no ObjectId and no transaction: ModelSpace,
       PaperSpace and the BlockTable of DxfBlockTableRecord; the layer, linetype, text style and dimension style
       tables; the header and AutoCAD's drawing variables by their names (Clayer, Ltscale, Dimasz and the rest);
       dictionaries, xrecords, groups, layouts, viewports, fields, annotation scales and the place on the earth.
     - Every entity of AutoCAD's name: DxfLine, DxfCircle, DxfArc, DxfEllipse, the three polylines, DxfSpline,
       DxfDBText, DxfMText, DxfBlockReference and its attributes, DxfHatch, DxfLeader, DxfMLeader, nine kinds of
       dimension, DxfTable and the meshes; a type with no class yet is a DxfUnknownEntity, kept as the file has it.
       Each is made in code (new DxfLine(start, end) { Layer = "steel" }), appended, erased, moved by TransformBy,
       copied, exploded, met by IntersectWith, joined by JoinEntity, and a curve walked by parameter and distance,
       offset, split and extended as AutoCAD does it.
     - Copies go between drawings as AutoCAD's deep clone takes them, by Clone and AppendEntity,
       WblockCloneObjects, Insert and AttachXref, bringing the blocks, layers and styles they name; a drawing of R12
       takes R12's forms, an MTEXT as one TEXT for each paragraph.
     - Held against ezdxf 1.4.5 on drawings of R12, R2000, R2007 and R2018: its recover and audit find nothing to
       fix in what is written, and it reads each value as set. The guide's DXF part is written for a reader who
       knows AutoCAD's .NET API, with a worked example and the points still to try in AutoCAD itself.

     NEW, reading DXF and shapes
     - DxfReader reads TEXT and MTEXT as the new DxfText, a LEADER as its curve and a MULTILEADER as the lines of
       its leaders, where it counted them in Skipped; DxfDocument.LayerTable and GetLayer give the layers with their
       look; DxfWriter.Add(DxfText) writes a text.
     - GeoCircle3 and GeoArc3 answer CollidesWith, GetIntersections and TryIntersectWith of a GeoEllipse3, as the
       ellipse answers them.

     FIXED, booleans and bodies
     - A union that came out wound against itself is worked out again, or says it was not worked out: a turned cube
       of 100 joined to a slab 0.001 thick inside its top is the cube, where it held 1 000 000.4. A difference or a
       common part enclosing no more than a slab the tolerance thick is nothing, BooleanOutcome.Empty.
     - TryCutOpenings, TrySplitBy, GetVolume and TryGetVolume give closed material or say false: a plate 300 by 200
       by 12 with twelve blind holes 0.015 under its top comes out closed, where 9 of 30 turnings were open, and a
       cracked cube 10 across with the corner of a box in it holds 875.00, where it held 1 000.
     - A boolean at a tolerance of nought returns, where 3 of 33 pairs ran for ever; a body 5E7 from the origin holds
       a point as one at the origin does; at a tolerance of nought a ray finds the crossing of each face it passes.

     FIXED, arcs, circles and ellipses in space
     - The distance to an arc, a curved edge or a curved chain is exact near the centre of a bend; a whole turn keeps
       every point of its circle whatever angle it starts at; GeoArc3.Translate moves a clockwise arc as it is.
     - GeoArc2 and GeoArc3.FromThreePoints read three points as on one line by the tolerance given, and give no arc
       that misses them; StartAngle is from nought up to a full turn however the arc was made; FromBulge past a half
       puts the centre where it is, 5E-12 off where it was 0.001.
     - Ellipses, circles and arcs that pass within the tolerance of each other touch, at both places where there are
       two, and give the same places whichever is asked first.

     FIXED, rays, segments, clash bars and labels
     - A ray meeting a triangle, a polygon or a face is read as its line is, TryIntersectWith agrees with
       GetIntersections, and a ray or segment that CollidesWith says touches is given the point.
     - ClashBar counts in LengthInside every stretch of its centre line within the tolerance of the part: a bar of
       radius 8 laid half its length on a box's top is 400 inside, where it was nought.
     - Arranger.Run reads the tolerance of its options throughout and arranges a scene moved elsewhere as it arranges
       it where it was.

     FIXED, offsets and splines
     - Offset2.Offset of a GeoPolygonArc2 drops a spike narrower than the tolerance, no longer comes back empty at a
       coarse tolerance, reads crossings nearer each other than the tolerance even-odd, and keeps the miter or chamfer
       at each tip where two lobes cross: the bow tie with an arc for its back, grown by 1, encloses 54.460, where its
       miter was cut off at 52.539.
     - Splines lying along each other give the same places however asked and turned, and a copy of a spline that
       crosses itself crosses it there; Flatten of a spline shorter than the tolerance no longer throws.
     - The copy of Clipper2 no longer overflows the stack on a polytree whose paths split off one another in a ring.

     CHANGED, behaviour you may notice
     - A union, a difference, a common part, TryCutOpenings or TrySplitBy can say false where it gave a body open or
       wound against itself. DxfReader refuses a file with letters beyond ASCII whose code page does not read ASCII
       as itself, and its size bound and MaxPlacedEntities, which now count texts and leaders, can refuse an INSERT
       placed before.
     - An edge bowing less off its chord than the rounding of its centre is its chord: IsArc is false.
     - Arranger.Run judges two labels closer than the tolerance as colliding, and ties go to the place tried first.

     CHANGED, speed
     - No longer slow with the square of their size: curved offsets and the crossings of a curved loop (a plus of
       80 000 teeth to each arm is cut in 0.75 to 1.6 s where it took 257 to 299), Clipper2 on combs, zigzags and
       rows of squares, booleans of faces lying back to back, ConvexHull3 and GeoObb3.Fit, merging faces of one
       plane, and clash bars by large meshes; the DXF model's inserts, erases, polylines and dimensions likewise.
       Results are the same to the bit.

     Details in CHANGELOG.md.

     Earlier releases: https://github.com/nguyenthanguth/GeometryHelper/blob/main/CHANGELOG.md