Vector Shapes
This page documents the concrete vector shape classes in Leaflet: Polyline, Polygon, Circle, CircleMarker, and Rectangle. These classes extend the Path base class and represent geometric shapes drawn as vectors on the map. Each shape class handles coordinate conversion, bounds calculation, projection, and geometry-specific operations.
For information about the vector rendering system (Canvas and SVG renderers), see Vector Rendering System. For the base Path class and shared functionality, see Vector Layers.
Class Hierarchy
All vector shapes extend from the Path base class, which provides common styling and rendering integration. The hierarchy is organized by geometric type:
Shape Comparison
| Shape | Extends | Coordinate Type | Radius Type | Supports Multi | Supports Holes |
|---|---|---|---|---|---|
| Polyline | Path | Array of LatLng | N/A | Yes | No |
| Polygon | Polyline | Array of arrays | N/A | Yes | Yes |
| Rectangle | Polygon | LatLngBounds | N/A | No | No |
| CircleMarker | Path | Single LatLng | Pixels | No | No |
| Circle | CircleMarker | Single LatLng | Meters | No | No |
Coordinate Structure Patterns
Vector shapes support different levels of coordinate nesting to represent simple shapes, multi-part shapes, and shapes with holes:
Polyline
The Polyline class draws lines connecting geographic points. It supports both simple polylines (single line) and MultiPolyline (multiple separate lines).
Key Methods
| Method | Description | Return Type |
|---|---|---|
getLatLngs() | Returns the array of points or nested arrays for multi-polyline | LatLng[] or LatLng[][] |
setLatLngs(latlngs) | Replaces all points and redraws | this |
addLatLng(latlng, latlngs?) | Adds a point, optionally to a specific ring | this |
isEmpty() | Returns true if no points | Boolean |
getBounds() | Returns the bounding box | LatLngBounds |
getCenter() | Returns the centroid | LatLng |
closestLayerPoint(p) | Finds closest point on the line to given point | Point |
Options
{
smoothFactor: 1.0, // Simplification tolerance (higher = more simplified)
noClip: false // Disable polyline clipping for performance
}Internal Coordinate Processing
The Polyline class performs several transformations on coordinates:
Implementation Details
Coordinate Conversion (src/layer/vector/Polyline.js158-172):
- Recursively converts input arrays to
LatLnginstances - Determines if array is flat (single line) or nested (multi-line) using
LineUtil.isFlat() - Calculates and extends
_boundsduring conversion
Projection (src/layer/vector/Polyline.js174-210):
- Converts geographic coordinates to pixel coordinates via
map.latLngToLayerPoint() - Creates
_ringsarray of projected coordinate arrays - Maintains
_rawPxBoundsfor the unprojected bounds
Clipping (src/layer/vector/Polyline.js213-247):
- Clips line segments to renderer bounds using
LineUtil.clipSegment() - Creates
_partsarray containing visible segments - Skipped if
noClip: trueoption is set
Simplification (src/layer/vector/Polyline.js250-257):
- Applies Douglas-Peucker algorithm via
LineUtil.simplify() - Controlled by
smoothFactoroption - Reduces point count for performance while maintaining visual accuracy
Hit Detection (src/layer/vector/Polyline.js272-291):
- Used by Canvas renderer for interactivity
- Checks if point is within
_clickTolerance()of any line segment - Uses
LineUtil.pointToSegmentDistance()for distance calculation
Polygon
The Polygon class extends Polyline to draw closed shapes. It supports holes (interior rings) and MultiPolygon geometries.
Key Methods
| Method | Description | Notes |
|---|---|---|
isEmpty() | Returns true if no rings or first ring is empty | Overrides Polyline version |
getCenter() | Returns polygon centroid | Uses PolyUtil.polygonCenter() |
Coordinate Structure
Polygons use a more complex nesting structure than polylines:
- Simple Polygon:
[[[lat,lng], [lat,lng], ...]]- Single outer ring wrapped in array - Polygon with Holes: First array is outer ring, subsequent arrays are holes
- MultiPolygon: Each element is a polygon (which itself can have holes)
Implementation Details
Coordinate Normalization (src/layer/vector/Polygon.js76-92):
- Ensures
_latlngsis never flat (always wrapped in at least one array) - Removes duplicate last point if it equals the first point
- First ring is always the outer boundary, others are holes
Clipping Algorithm (src/layer/vector/Polygon.js98-124):
- Uses
PolyUtil.clipPolygon()instead of line segment clipping - Expands clip bounds by stroke width to avoid edge artifacts
- Clips each ring independently
Hit Detection (src/layer/vector/Polygon.js131-153):
- Uses ray casting algorithm to check if point is inside polygon
- Falls back to Polyline's
_containsPoint()to check stroke - Handles holes by alternating inside/outside state
Circle and CircleMarker
These classes provide two different types of circular shapes with fundamentally different coordinate systems.
CircleMarker: Fixed Pixel Radius
CircleMarker draws a circle with a fixed pixel radius that doesn't scale with zoom level. Useful for markers and point features.
Key Characteristics:
- Radius specified in pixels
- Radius stays constant across zoom levels
- Simple projection: just converts center point to layer coordinates
Options:
{
fill: true,
radius: 10 // pixels
}Circle: Geographic Radius
Circle draws a circle with a radius in meters, accounting for map projection. The pixel radius changes with zoom and latitude.
Key Characteristics:
- Radius specified in meters (geographic distance)
- Pixel size varies with zoom level and latitude
- Complex projection calculations for Earth CRS
Options:
{
radius: 200 // meters (required)
}Circle Projection Comparison
Circle Earth Projection Details
For Earth CRS (Web Mercator), Circle performs sophisticated calculations (src/layer/vector/Circle.js76-92):
Calculate latitude radius in degrees from meter radius:
latR = (meters / Earth.R) / (π/180)Project top and bottom points at
[lat ± latR, lng]Calculate center and adjusted latitude from projected points
Calculate longitude radius using spherical trigonometry:
cos(latR) = cos(lat) * cos(lat2) * cos(lngR) + sin(lat) * sin(lat2)Handle edge cases: Falls back to simplified calculation near poles
Store ellipse parameters:
_radius(x),_radiusY(y) for non-circular projection
This accounts for the fact that circles on the Earth's surface project as ellipses in Web Mercator projection, with distortion increasing at higher latitudes.
Methods Comparison
| Method | CircleMarker | Circle |
|---|---|---|
setRadius(radius) | Pixels | Meters |
getRadius() | Returns pixel radius | Returns meter radius |
setLatLng(latlng) | ✓ | ✓ (inherited) |
getLatLng() | ✓ | ✓ (inherited) |
getBounds() | Pixel-based bounds | Geographic bounds |
Rectangle
The Rectangle class is a specialized Polygon that creates a four-cornered shape from a LatLngBounds object.
Constructor and Methods
// Create from LatLngBounds
const bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
const rectangle = new Rectangle(bounds, {color: "#ff7800", weight: 1});
// Update bounds
rectangle.setBounds(newBounds);Internal Implementation
Bounds to Coordinates Conversion (src/layer/vector/Rectangle.js41-49):
The _boundsToLatLngs() method converts a LatLngBounds to four corner points in counter-clockwise order:
- South-West corner
- North-West corner
- North-East corner
- South-East corner
This creates a properly oriented polygon for the renderer.
Common Operations
All vector shapes share certain operations inherited from Path and implemented in shape-specific ways.
Bounds Calculation
Each shape calculates its bounding box differently:
| Shape | Bounds Calculation |
|---|---|
| Polyline | Extends bounds for each point during conversion |
| Polygon | Inherits from Polyline |
| CircleMarker | Center ± radius in pixels |
| Circle | Projects center ± radius to LatLng bounds |
| Rectangle | Defined by constructor LatLngBounds |
Center Calculation
Notes:
- Polyline and Polygon
getCenter()require the shape to be added to the map first (throws error otherwise) - This is because center calculation requires projected coordinates via the map's CRS
- Circles simply return their center point
Hit Detection
Hit detection is used by the Canvas renderer to determine if a mouse/touch event intersects the shape:
| Shape | Algorithm | Implementation |
|---|---|---|
| Polyline | Point-to-segment distance | LineUtil.pointToSegmentDistance() ≤ tolerance |
| Polygon | Ray casting + stroke check | Count edge crossings, then check Polyline |
| CircleMarker | Distance check | point.distanceTo(center) ≤ radius |
| Circle | Distance check | Inherited from CircleMarker |
Performance Optimizations
Vector shapes employ several optimizations to maintain performance with large datasets.
Clipping
Purpose: Reduce rendering workload by excluding geometry outside the visible area.
Implementation:
- Polyline: Uses
LineUtil.clipSegment()to clip each line segment to renderer bounds (src/layer/vector/Polyline.js213-247) - Polygon: Uses
PolyUtil.clipPolygon()with expanded bounds for stroke width (src/layer/vector/Polygon.js98-124) - Can be disabled with
noClip: trueoption
Process:
Simplification
Purpose: Reduce point count while maintaining visual accuracy using the Douglas-Peucker algorithm.
Configuration:
- Controlled by
smoothFactoroption (default: 1.0) - Higher values = more aggressive simplification
- Applied after clipping via
LineUtil.simplify()
Trade-offs:
- Higher smoothFactor: Better performance, less detail
- Lower smoothFactor: More detail, slower rendering
- Value of 0 disables simplification
// Heavy simplification (faster, less accurate)
const polyline1 = new Polyline(coords, {smoothFactor: 3.0});
// Minimal simplification (slower, more accurate)
const polyline2 = new Polyline(coords, {smoothFactor: 0.5});
// No simplification (slowest, exact)
const polyline3 = new Polyline(coords, {smoothFactor: 0});Update Pipeline
The complete update pipeline for polyline-based shapes:
File Reference Summary
Core Implementation Files
- src/layer/vector/Polyline.js - Polyline class, coordinate handling, clipping, simplification
- src/layer/vector/Polygon.js - Polygon class, hole support, ray casting hit detection
- src/layer/vector/Circle.js - Circle class with geographic radius
- src/layer/vector/CircleMarker.js - CircleMarker class with pixel radius
- src/layer/vector/Rectangle.js - Rectangle class, LatLngBounds conversion
Test Files
- spec/suites/layer/vector/PolylineSpec.js - Polyline tests including multi-line support
- spec/suites/layer/vector/PolygonSpec.js - Polygon tests including holes and MultiPolygon