or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

coordinate-systems.mdcore-data-structures.mdfile-io.mdgeometric-operations.mdindex.mdspatial-relationships.mdtesting-utilities.mdvisualization.md

geometric-operations.mddocs/

0

# Geometric Operations

1

2

GeoPandas provides a comprehensive set of geometric operations for spatial analysis and geometric computations. These operations work on individual geometries and return new geometric objects or scalar values, enabling complex spatial analysis workflows.

3

4

## Capabilities

5

6

### Geometric Properties

7

8

Properties that return scalar values describing geometric characteristics.

9

10

```python { .api }

11

class GeoSeries:

12

@property

13

def area(self):

14

"""

15

Area of each geometry in the GeoSeries.

16

17

Returns:

18

- pandas.Series: Area values (units depend on CRS)

19

"""

20

...

21

22

@property

23

def length(self):

24

"""

25

Length of each geometry in the GeoSeries.

26

27

Returns:

28

- pandas.Series: Length values (units depend on CRS)

29

"""

30

...

31

32

@property

33

def geom_type(self):

34

"""

35

Geometry type of each geometry.

36

37

Returns:

38

- pandas.Series: Geometry type names ('Point', 'LineString', etc.)

39

"""

40

...

41

42

@property

43

def is_empty(self):

44

"""

45

Whether each geometry is empty.

46

47

Returns:

48

- pandas.Series: Boolean values indicating if geometry is empty

49

"""

50

...

51

52

@property

53

def is_ring(self):

54

"""

55

Whether each geometry is a closed ring.

56

57

Returns:

58

- pandas.Series: Boolean values indicating if geometry is a ring

59

"""

60

...

61

62

@property

63

def is_simple(self):

64

"""

65

Whether each geometry is simple (non-self-intersecting).

66

67

Returns:

68

- pandas.Series: Boolean values indicating if geometry is simple

69

"""

70

...

71

72

@property

73

def is_valid(self):

74

"""

75

Whether each geometry is valid.

76

77

Returns:

78

- pandas.Series: Boolean values indicating if geometry is valid

79

"""

80

...

81

82

@property

83

def is_closed(self):

84

"""

85

Whether each LinearRing or LineString geometry is closed.

86

87

Returns:

88

- pandas.Series: Boolean values indicating if geometry is closed

89

"""

90

...

91

92

@property

93

def is_ccw(self):

94

"""

95

Whether each LinearRing geometry has counter-clockwise orientation.

96

97

Returns:

98

- pandas.Series: Boolean values indicating counter-clockwise orientation

99

"""

100

...

101

102

@property

103

def has_z(self):

104

"""

105

Whether each geometry has Z (3D) coordinates.

106

107

Returns:

108

- pandas.Series: Boolean values indicating presence of Z coordinates

109

"""

110

...

111

112

@property

113

def has_m(self):

114

"""

115

Whether each geometry has M (measure) coordinates.

116

117

Returns:

118

- pandas.Series: Boolean values indicating presence of M coordinates

119

"""

120

...

121

```

122

123

### Geometric Constructors

124

125

Methods that create new geometries based on existing ones.

126

127

```python { .api }

128

class GeoSeries:

129

def buffer(self, distance, resolution=16, **kwargs):

130

"""

131

Buffer each geometry by given distance.

132

133

Parameters:

134

- distance: Buffer distance (units depend on CRS)

135

- resolution: Number of segments for circular arcs

136

- **kwargs: Additional parameters for shapely buffer

137

138

Returns:

139

- GeoSeries: Buffered geometries

140

"""

141

...

142

143

def boundary(self):

144

"""

145

Boundary of each geometry.

146

147

Returns:

148

- GeoSeries: Boundary geometries

149

"""

150

...

151

152

def centroid(self):

153

"""

154

Centroid of each geometry.

155

156

Returns:

157

- GeoSeries: Point geometries representing centroids

158

"""

159

...

160

161

def convex_hull(self):

162

"""

163

Convex hull of each geometry.

164

165

Returns:

166

- GeoSeries: Convex hull geometries

167

"""

168

...

169

170

def envelope(self):

171

"""

172

Envelope (bounding box) of each geometry.

173

174

Returns:

175

- GeoSeries: Rectangular envelope geometries

176

"""

177

...

178

179

def exterior(self):

180

"""

181

Exterior ring of each Polygon geometry.

182

183

Returns:

184

- GeoSeries: LinearRing geometries

185

"""

186

...

187

188

def interiors(self):

189

"""

190

Interior rings of each Polygon geometry.

191

192

Returns:

193

- pandas.Series: Lists of LinearRing geometries

194

"""

195

...

196

197

def representative_point(self):

198

"""

199

Representative point for each geometry (guaranteed to be within geometry).

200

201

Returns:

202

- GeoSeries: Point geometries within original geometries

203

"""

204

...

205

206

def simplify(self, tolerance, preserve_topology=True):

207

"""

208

Simplify geometries using Douglas-Peucker algorithm.

209

210

Parameters:

211

- tolerance: Simplification tolerance (units depend on CRS)

212

- preserve_topology: Whether to preserve topology

213

214

Returns:

215

- GeoSeries: Simplified geometries

216

"""

217

...

218

219

def minimum_rotated_rectangle(self):

220

"""

221

Minimum rotated bounding rectangle for each geometry.

222

223

Returns:

224

- GeoSeries: Rectangular geometries with minimum area enclosing original

225

"""

226

...

227

228

def minimum_bounding_circle(self):

229

"""

230

Minimum bounding circle for each geometry.

231

232

Returns:

233

- GeoSeries: Circular geometries with minimum area enclosing original

234

"""

235

...

236

237

def minimum_bounding_radius(self):

238

"""

239

Radius of minimum bounding circle for each geometry.

240

241

Returns:

242

- pandas.Series: Radius values for minimum bounding circles

243

"""

244

...

245

246

def concave_hull(self, ratio=0.0, allow_holes=False):

247

"""

248

Concave hull of each geometry using alpha shapes algorithm.

249

250

Parameters:

251

- ratio: Ratio parameter controlling concaveness (0.0 = convex hull, 1.0 = maximum concaveness)

252

- allow_holes: Whether to allow holes in the hull

253

254

Returns:

255

- GeoSeries: Concave hull geometries

256

"""

257

...

258

259

def delaunay_triangles(self, tolerance=0.0, only_edges=False):

260

"""

261

Delaunay triangulation of geometry coordinates.

262

263

Parameters:

264

- tolerance: Coordinate tolerance for triangulation

265

- only_edges: Return only triangle edges instead of filled triangles

266

267

Returns:

268

- GeoSeries: Triangle geometries or edge LineStrings

269

"""

270

...

271

272

def voronoi_polygons(self, tolerance=0.0, extend_to=None, only_edges=False):

273

"""

274

Voronoi diagram of Point geometries.

275

276

Parameters:

277

- tolerance: Coordinate tolerance for diagram generation

278

- extend_to: Geometry to extend diagram to (default: bounding box)

279

- only_edges: Return only diagram edges instead of filled polygons

280

281

Returns:

282

- GeoSeries: Voronoi polygon geometries or edge LineStrings

283

"""

284

...

285

286

def offset_curve(self, distance, quad_segs=8, join_style=1, mitre_limit=5.0):

287

"""

288

Create offset curve (parallel line) from LineString geometries.

289

290

Parameters:

291

- distance: Offset distance (positive for left, negative for right)

292

- quad_segs: Number of segments for quarter circle

293

- join_style: Join style (1=round, 2=mitre, 3=bevel)

294

- mitre_limit: Mitre ratio limit for mitre joins

295

296

Returns:

297

- GeoSeries: Offset curve geometries

298

"""

299

...

300

301

def line_merge(self, directed=False):

302

"""

303

Merge connected LineString geometries into continuous lines.

304

305

Parameters:

306

- directed: Whether to consider line direction in merging

307

308

Returns:

309

- GeoSeries: Merged LineString or MultiLineString geometries

310

"""

311

...

312

```

313

314

### Linear Referencing

315

316

Methods for working with linear geometries and distance-based positioning.

317

318

```python { .api }

319

class GeoSeries:

320

def project(self, other, normalized=False):

321

"""

322

Project point onto line geometry and return distance along line.

323

324

Parameters:

325

- other: Point geometry or GeoSeries of Points to project

326

- normalized: Return distance as fraction of line length (0.0 to 1.0)

327

328

Returns:

329

- pandas.Series: Distance values along the line

330

"""

331

...

332

333

def interpolate(self, distance, normalized=False):

334

"""

335

Return point at specified distance along line geometry.

336

337

Parameters:

338

- distance: Distance along line or array of distances

339

- normalized: Interpret distance as fraction of line length

340

341

Returns:

342

- GeoSeries: Point geometries at specified distances

343

"""

344

...

345

```

346

347

### Affine Transformations

348

349

Methods for applying affine transformations to geometries.

350

351

```python { .api }

352

class GeoSeries:

353

def translate(self, xoff=0.0, yoff=0.0, zoff=0.0):

354

"""

355

Translate geometries by given offsets.

356

357

Parameters:

358

- xoff: X offset

359

- yoff: Y offset

360

- zoff: Z offset

361

362

Returns:

363

- GeoSeries: Translated geometries

364

"""

365

...

366

367

def rotate(self, angle, origin='center', use_radians=False):

368

"""

369

Rotate geometries by given angle.

370

371

Parameters:

372

- angle: Rotation angle

373

- origin: Center of rotation ('center', 'centroid', or Point)

374

- use_radians: Whether angle is in radians (default: degrees)

375

376

Returns:

377

- GeoSeries: Rotated geometries

378

"""

379

...

380

381

def scale(self, xfact=1.0, yfact=1.0, zfact=1.0, origin='center'):

382

"""

383

Scale geometries by given factors.

384

385

Parameters:

386

- xfact: X scale factor

387

- yfact: Y scale factor

388

- zfact: Z scale factor

389

- origin: Center of scaling ('center', 'centroid', or Point)

390

391

Returns:

392

- GeoSeries: Scaled geometries

393

"""

394

...

395

396

def skew(self, xs=0.0, ys=0.0, origin='center', use_radians=False):

397

"""

398

Skew geometries by given angles.

399

400

Parameters:

401

- xs: X skew angle

402

- ys: Y skew angle

403

- origin: Center of skewing ('center', 'centroid', or Point)

404

- use_radians: Whether angles are in radians (default: degrees)

405

406

Returns:

407

- GeoSeries: Skewed geometries

408

"""

409

...

410

```

411

412

### Coordinate Access

413

414

Properties for accessing coordinate information from Point geometries.

415

416

```python { .api }

417

class GeoSeries:

418

@property

419

def x(self):

420

"""

421

X coordinates of Point geometries.

422

423

Returns:

424

- pandas.Series: X coordinate values (NaN for non-Point geometries)

425

"""

426

...

427

428

@property

429

def y(self):

430

"""

431

Y coordinates of Point geometries.

432

433

Returns:

434

- pandas.Series: Y coordinate values (NaN for non-Point geometries)

435

"""

436

...

437

438

@property

439

def z(self):

440

"""

441

Z coordinates of Point geometries.

442

443

Returns:

444

- pandas.Series: Z coordinate values (NaN for 2D or non-Point geometries)

445

"""

446

...

447

448

@property

449

def m(self):

450

"""

451

M coordinates of Point geometries.

452

453

Returns:

454

- pandas.Series: M coordinate values (NaN for non-M or non-Point geometries)

455

"""

456

...

457

458

@property

459

def bounds(self):

460

"""

461

Bounds of each geometry as (minx, miny, maxx, maxy).

462

463

Returns:

464

- pandas.DataFrame: DataFrame with minx, miny, maxx, maxy columns

465

"""

466

...

467

468

@property

469

def total_bounds(self):

470

"""

471

Total bounds of all geometries as (minx, miny, maxx, maxy).

472

473

Returns:

474

- numpy.ndarray: Array with [minx, miny, maxx, maxy]

475

"""

476

...

477

```

478

479

### Geometric Validation and Repair

480

481

Methods for validating and repairing geometries.

482

483

```python { .api }

484

class GeoSeries:

485

def make_valid(self, method='auto'):

486

"""

487

Make invalid geometries valid.

488

489

Parameters:

490

- method: Repair method ('auto', 'structure', 'linework')

491

492

Returns:

493

- GeoSeries: Valid geometries

494

"""

495

...

496

497

def normalize(self):

498

"""

499

Normalize geometries to canonical form.

500

501

Returns:

502

- GeoSeries: Normalized geometries

503

"""

504

...

505

506

def is_valid_reason(self):

507

"""

508

Return reason why each geometry is invalid.

509

510

Returns:

511

- pandas.Series: Text descriptions of invalidity reasons

512

"""

513

...

514

515

def clip_by_rect(self, xmin, ymin, xmax, ymax):

516

"""

517

Clip geometries to rectangular bounds.

518

519

Parameters:

520

- xmin: Minimum X coordinate

521

- ymin: Minimum Y coordinate

522

- xmax: Maximum X coordinate

523

- ymax: Maximum Y coordinate

524

525

Returns:

526

- GeoSeries: Clipped geometries

527

"""

528

...

529

530

def snap(self, other, tolerance):

531

"""

532

Snap vertices of geometries to reference geometries within tolerance.

533

534

Parameters:

535

- other: Reference geometry or GeoSeries to snap to

536

- tolerance: Snapping tolerance distance

537

538

Returns:

539

- GeoSeries: Snapped geometries

540

"""

541

...

542

543

def polygonize(self, node=True, full=False):

544

"""

545

Create polygons from collection of LineString geometries.

546

547

Parameters:

548

- node: Whether to node the lines first

549

- full: Return all polygonization products

550

551

Returns:

552

- GeoSeries: Polygonal geometries

553

"""

554

...

555

556

def unary_union(self):

557

"""

558

Union all geometries in the series into a single geometry.

559

560

Returns:

561

- Geometry: Single geometry representing union of all geometries

562

"""

563

...

564

565

def get_coordinates(self, include_z=None, ignore_index=False, index_parts=False):

566

"""

567

Extract coordinate arrays from geometries.

568

569

Parameters:

570

- include_z: Include Z coordinates if available

571

- ignore_index: Reset index in result

572

- index_parts: Include part indices for multi-part geometries

573

574

Returns:

575

- pandas.DataFrame: Coordinate arrays with x, y (and optionally z) columns

576

"""

577

...

578

```

579

580

## Usage Examples

581

582

### Basic Geometric Properties

583

584

```python

585

import geopandas as gpd

586

from shapely.geometry import Point, Polygon, LineString

587

588

# Create sample geometries

589

gdf = gpd.GeoDataFrame({

590

'name': ['Circle', 'Square', 'Line'],

591

'geometry': [

592

Point(0, 0).buffer(1), # Circle

593

Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]), # Square

594

LineString([(0, 0), (1, 1), (2, 0)]) # Line

595

]

596

})

597

598

# Calculate geometric properties

599

print(f"Areas: {gdf.geometry.area}")

600

print(f"Lengths: {gdf.geometry.length}")

601

print(f"Types: {gdf.geometry.geom_type}")

602

print(f"Bounds: {gdf.geometry.bounds}")

603

print(f"Total bounds: {gdf.geometry.total_bounds}")

604

```

605

606

### Geometric Constructors

607

608

```python

609

# Create derived geometries

610

centroids = gdf.geometry.centroid

611

envelopes = gdf.geometry.envelope

612

convex_hulls = gdf.geometry.convex_hull

613

boundaries = gdf.geometry.boundary

614

615

# Buffer operations

616

buffered_small = gdf.geometry.buffer(0.5)

617

buffered_large = gdf.geometry.buffer(2.0, resolution=32)

618

619

# Simplification

620

complex_line = LineString([(i/10, (i/10)**2) for i in range(100)])

621

simplified = gpd.GeoSeries([complex_line]).simplify(0.1)

622

```

623

624

### Affine Transformations

625

626

```python

627

# Translation

628

translated = gdf.geometry.translate(xoff=10, yoff=5)

629

630

# Rotation (45 degrees counterclockwise)

631

rotated = gdf.geometry.rotate(45, origin='center')

632

633

# Scaling

634

scaled = gdf.geometry.scale(xfact=2.0, yfact=0.5, origin='center')

635

636

# Skewing

637

skewed = gdf.geometry.skew(xs=15, ys=0, origin='center')

638

639

# Combine transformations

640

transformed = (gdf.geometry

641

.translate(xoff=5, yoff=5)

642

.rotate(30, origin='center')

643

.scale(xfact=1.5, yfact=1.5, origin='center'))

644

```

645

646

### Coordinate Access

647

648

```python

649

# Create points

650

points = gpd.GeoSeries([

651

Point(1, 2),

652

Point(3, 4, 5), # 3D point

653

Point(6, 7)

654

])

655

656

# Access coordinates

657

print(f"X coordinates: {points.x}")

658

print(f"Y coordinates: {points.y}")

659

print(f"Z coordinates: {points.z}") # NaN for 2D points

660

661

# For non-Point geometries, coordinates are NaN

662

mixed_geoms = gpd.GeoSeries([

663

Point(1, 2),

664

LineString([(0, 0), (1, 1)]),

665

Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])

666

])

667

print(f"X coordinates: {mixed_geoms.x}") # Only Point has valid X

668

```

669

670

### Working with Complex Geometries

671

672

```python

673

# Polygon with holes

674

exterior = [(0, 0), (10, 0), (10, 10), (0, 10)]

675

hole1 = [(2, 2), (4, 2), (4, 4), (2, 4)]

676

hole2 = [(6, 6), (8, 6), (8, 8), (6, 8)]

677

polygon_with_holes = Polygon(exterior, [hole1, hole2])

678

679

gdf_complex = gpd.GeoDataFrame({'geometry': [polygon_with_holes]})

680

681

# Access polygon components

682

exterior_ring = gdf_complex.geometry.exterior

683

interior_rings = gdf_complex.geometry.interiors

684

685

print(f"Exterior: {exterior_ring.iloc[0]}")

686

print(f"Number of holes: {len(interior_rings.iloc[0])}")

687

```

688

689

### Geometric Validation and Repair

690

691

```python

692

from shapely.geometry import Polygon

693

694

# Create invalid geometry (self-intersecting polygon)

695

invalid_polygon = Polygon([(0, 0), (2, 2), (2, 0), (0, 2)])

696

gdf_invalid = gpd.GeoDataFrame({'geometry': [invalid_polygon]})

697

698

# Check validity

699

print(f"Is valid: {gdf_invalid.geometry.is_valid.iloc[0]}")

700

701

# Repair invalid geometry

702

gdf_repaired = gdf_invalid.copy()

703

gdf_repaired['geometry'] = gdf_repaired.geometry.make_valid()

704

print(f"Repaired is valid: {gdf_repaired.geometry.is_valid.iloc[0]}")

705

706

# Normalize geometries

707

normalized = gdf_repaired.geometry.normalize()

708

```

709

710

### Area and Distance Calculations

711

712

```python

713

# For accurate measurements, use projected CRS

714

gdf_geographic = gpd.read_file('world.shp') # WGS84

715

716

# Convert to appropriate UTM zone for accurate area calculation

717

utm_crs = gdf_geographic.estimate_utm_crs()

718

gdf_utm = gdf_geographic.to_crs(utm_crs)

719

720

# Calculate areas in square meters

721

areas_sqm = gdf_utm.geometry.area

722

723

# Calculate perimeters in meters

724

perimeters_m = gdf_utm.geometry.length

725

726

# Convert back to square kilometers for readability

727

areas_sqkm = areas_sqm / 1_000_000

728

729

print(f"Country areas (sq km): {areas_sqkm}")

730

```

731

732

### Representative Points

733

734

```python

735

# For complex polygons, centroids might fall outside the geometry

736

# Representative points are guaranteed to be inside

737

complex_polygon = gpd.read_file('complex_country.shp')

738

739

centroids = complex_polygon.geometry.centroid

740

rep_points = complex_polygon.geometry.representative_point()

741

742

# Check which centroids fall outside their polygons

743

centroids_outside = ~complex_polygon.geometry.contains(centroids)

744

print(f"Centroids outside polygon: {centroids_outside.sum()}")

745

746

# Representative points are always inside

747

rep_points_inside = complex_polygon.geometry.contains(rep_points)

748

print(f"Representative points inside: {rep_points_inside.all()}")

749

```