# Custom CRSs

## Projection

To define a `Proj4Crs` (custom CRS) you have to register a projection of `proj4.Projection`. For that you must import `proj4dart` library as follows:

```dart
import 'package:proj4dart/proj4dart.dart' as proj4;
```

You can create and register your custom projection in multiple ways, but the recommended is to use a **Proj4 definition string** from [epsg.io](https://epsg.io). For example for `EPSG:3413` (*WGS 84 / NSIDC Sea Ice Polar Stereographic North*) you can find it [here](https://epsg.io/3413.proj4). This is how a Proj4 definition string looks like:

```dart
+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m + no_defs
```

With this **Proj4 definition string** and a **string identifier** register your `proj4.Projection` like this:

```dart
var customProjection = proj4.Projection.add('EPSG:3413',
    '+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
```

For more possible ways to register `proj4.Projection` see [proj4dart documentation](https://github.com/maRci002/proj4dart).

## Coordinate Reference System (CRS)

You can use your previously registered `proj4.Projection` to create a custom CRS of type `Proj4Crs`. You can use the following parameters:

* `<String>` `code` (required): string identifier for the selected CRS, e.g. `EPSG:3413`
* `<proj4.Projection>` `proj4Projection` (required): the `proj4.Projection` object you wish to use
* `<Bounds>` `bounds`: bounds of the CRS in projected coordinates
* `<List<double>>` `resolutions`: an array of zoom factors (projection units per pixel, eg. meters/pixel)
* `<List<double>>` `scales`: scale factors (pixels per projection unit); specify either scales or resolutions, but not both!
* `<List<Point>>` `origins`: tile origin in projected coordinates (for TileLayer). Why is it needed? GeoServer by default can define different origins (top left coordinates) for each zoom levels. In case of origin mismatch the tile will be drawn on the wrong place: the map will jump at such zoom levels. If your origins vary with zoom levels the number of origins must match the number of resolutions. You can get the desired origins from a `GetCapabilities` WMTS call from geoserver e.g. `http://[ip:port]/geoserver/gwc/service/wmts?request=GetCapabilities`. This results an XML, and you have to look up for the `TopLeftCorner`s for each TileMatrix of your TileMatrixSet.<br>
* `<Transformation>` `transformation`: the transformation to use when transforming projected coordinates into pixel coordinates

An example:

```dart
var epsg3413 = proj4.Projection.add('EPSG:3413',
    '+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');

final resolutions = <double>[
  32768,
  16384,
  8192,
  4096,
  2048,
  1024,
  512,
  256,
  128,
];

final epsg3413Bounds = Bounds<double>(
  Point<double>(-4511619.0, -4511336.0),
  Point<double>(4510883.0, 4510996.0),
);

var maxZoom = (resolutions.length - 1).toDouble();

var epsg3413CRS = Proj4Crs.fromFactory(
  code: 'EPSG:3413',
  proj4Projection: epsg3413,
  resolutions: resolutions,
  bounds: epsg3413Bounds,
  origins: [Point(0, 0)],
  scales: null,
  transformation: null,
);
```

## Usage

Proj4Crs has multiple uses:

* Set `FlutterMap`'s default CRS:

  ```dart
    FlutterMap(
      options: MapOptions(
        // Set the default CRS
        crs: epsg3413CRS,
        center: LatLng(65.05166470332148, -19.171744826394896),
        zoom: 3.0,
        maxZoom: maxZoom,
      ),
      layers: [],
    );
  ```
* Set a WMS layer's CRS

  ```dart
    TileLayer(
      wmsOptions: WMSTileLayerOptions(
        // Set the WMS layer's CRS
        crs: epsg3413CRS,
        transparent: true,
        format: 'image/jpeg',
        baseUrl:
            'https://www.gebco.net/data_and_products/gebco_web_services/north_polar_view_wms/mapserv?',
        layers: ['gebco_north_polar_view'],
      ),
    );
  ```

For complete code (with point transformation from one projection to another) see the page source code. This is how it looks like:


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fleaflet.dev/usage/options/custom-crss.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
