|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- import {PNG} from 'pngjs';
- import {Projection} from '../../utils/types';
- import * as d3geo from 'd3-geo';
-
- export default interface ProjectionService {}
- export class ProjectionServiceImpl implements ProjectionService {
- private readonly projections: Record<Projection, Function> = {
- [Projection.EQUIRECTANGULAR]: d3geo.geoEquirectangular,
- [Projection.MERCATOR]: d3geo.geoMercator,
- } as const
-
- private readonly referenceWidth = 960 as const;
-
- project(equiImage: PNG, projection: Projection) {
- if (projection === Projection.EQUIRECTANGULAR) {
- return equiImage;
- }
-
- const projectionFunction = this.projections[projection]();
- if (!projectionFunction.invert) {
- return undefined;
- }
-
- const sx = equiImage.width;
- const sy = equiImage.height;
- const sourceData = equiImage.data;
- const tx = sx;
- // const py = projection === Projection.MERCATOR ? dy * 2 : dy;
- const ty = sy;
- const target = new PNG({
- width: tx,
- height: ty,
- });
- const targetData = target.data;
-
- let i = 0;
- for (let y = 0; y < sy; y += 1) {
- for (let x = 0; x < sx; x += 1) {
- const projected = projectionFunction.invert([x / sx * this.referenceWidth, y / sx * this.referenceWidth]) as [number, number];
- if (projected) {
- const [lambda, phi] = projected;
- if (!(lambda > 180 || lambda < -180 || phi > 90 || phi < -90)) {
- const q = ((90 - phi) / 180 * sy | 0) * sx + ((180 + lambda) / 360 * sx | 0) << 2;
- targetData[i] = sourceData[q];
- targetData[i + 1] = sourceData[q + 1];
- targetData[i + 2] = sourceData[q + 2];
- targetData[i + 3] = 255;
- }
- }
- i += 4;
- }
- }
-
- return target;
- }
- }
-
|