Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mapgl_Viewport #3

Open
wants to merge 1 commit into
base: prototype
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ declare global {
declare var window: any;

const map = new mapgl.Map('container', {
center: [55.31878, 25.23584],
zoom: 16.2,
center: [55.30401193485671, 25.273124140912344],
zoom: 17.021087495312493,
pitch: 35.38661417565734,
rotation: -111.26507733271275,
key: '4970330e-7f1c-4921-808c-0eb7c4e63001',
});
initDeckGL();

async function initDeckGL() {
console.log('Layer data - Loading...');
fetch(
'https://urbi-geo-api-staging2.web-staging.2gis.ru/building/items/values?tag=floors_count,height&bounds=POLYGON+((55.13142+25.544679,+55.203999+25.567715,+55.279599+25.566579,+55.43176+25.759947,+55.55436+25.811148,+55.666094+25.897751,+55.76817+25.925981,+55.826597+26.007005,+55.888369+26.151722,+56.086425+26.050441,+56.15912+26.062127,+56.195513+25.979301,+56.163975+25.946893,+56.177561+25.892732,+56.139167+25.8325,+56.1725+25.769167,+56.140833+25.735,+56.143611+25.676111,+56.191111+25.648056,+56.201874+25.611984,+56.253291+25.60219,+56.266328+25.606335,+56.254586+25.613159,+56.264173+25.627665,+56.418384+25.682657,+56.549221+25.692716,+56.591385+25.549234,+56.602446+25.323577,+56.585359+25.087633,+56.594079+25.007481,+56.323288+24.972644,+56.348923+24.934376,+56.338442+24.914535,+56.259358+24.859817,+56.205659+24.850507,+56.201022+24.784219,+56.144333+24.741556,+56.060585+24.746639,+56.036157+24.810922,+55.978341+24.877363,+55.980164+24.894492,+56.062185+24.870801,+56.042048+24.886589,+56.058722+24.949126,+56.042075+24.947686,+56.045483+24.967887,+56.006871+24.994727,+55.960882+25.005958,+55.910907+24.965663,+55.851301+24.965812,+55.812409+24.910874,+55.836502+24.671031,+55.793833+24.637012,+55.816207+24.615223,+55.767784+24.572526,+55.764989+24.52949,+55.834202+24.409554,+55.833944+24.327733,+55.759405+24.261142,+55.752895+24.234821,+55.833523+24.200902,+55.954447+24.222568,+55.969652+24.182449,+55.960753+24.170318,+56.017506+24.066605,+55.902317+24.046941,+55.833035+24.01459,+55.801126+24.025482,+55.781754+24.055948,+55.731246+24.058066,+55.485274+23.944384,+55.533725+23.849352,+55.531869+23.757286,+55.569228+23.720734,+55.572308+23.629646,+55.452588+23.465217,+55.430691+23.399593,+55.416507+23.382151,+55.401537+23.392525,+55.232271+23.110348,+55.216283+23.02621,+55.227508+22.791619,+55.21284+22.705686,+55.137388+22.631591,+52.58104+22.939203,+51.590376+24.126971,+51.589825+24.26588,+51.529512+24.336352,+51.416071+24.393194,+51.466454+24.462489,+51.565206+24.553035,+51.589187+24.619704,+51.586122+24.664189,+52.02542+24.75828,+52.309194+24.842176,+52.378334+24.900336,+52.337088+24.949252,+52.345961+24.997718,+52.405921+25.018775,+52.450032+24.982958,+52.647202+25.143128,+52.894479+25.470458,+54.182354+25.450646,+55.13142+25.544679))',
'https://urbi-geo-api-staging.web-staging.2gis.ru/building/items/values?tag=floors_count,height&bounds=POLYGON+((55.13142+25.544679,+55.203999+25.567715,+55.279599+25.566579,+55.43176+25.759947,+55.55436+25.811148,+55.666094+25.897751,+55.76817+25.925981,+55.826597+26.007005,+55.888369+26.151722,+56.086425+26.050441,+56.15912+26.062127,+56.195513+25.979301,+56.163975+25.946893,+56.177561+25.892732,+56.139167+25.8325,+56.1725+25.769167,+56.140833+25.735,+56.143611+25.676111,+56.191111+25.648056,+56.201874+25.611984,+56.253291+25.60219,+56.266328+25.606335,+56.254586+25.613159,+56.264173+25.627665,+56.418384+25.682657,+56.549221+25.692716,+56.591385+25.549234,+56.602446+25.323577,+56.585359+25.087633,+56.594079+25.007481,+56.323288+24.972644,+56.348923+24.934376,+56.338442+24.914535,+56.259358+24.859817,+56.205659+24.850507,+56.201022+24.784219,+56.144333+24.741556,+56.060585+24.746639,+56.036157+24.810922,+55.978341+24.877363,+55.980164+24.894492,+56.062185+24.870801,+56.042048+24.886589,+56.058722+24.949126,+56.042075+24.947686,+56.045483+24.967887,+56.006871+24.994727,+55.960882+25.005958,+55.910907+24.965663,+55.851301+24.965812,+55.812409+24.910874,+55.836502+24.671031,+55.793833+24.637012,+55.816207+24.615223,+55.767784+24.572526,+55.764989+24.52949,+55.834202+24.409554,+55.833944+24.327733,+55.759405+24.261142,+55.752895+24.234821,+55.833523+24.200902,+55.954447+24.222568,+55.969652+24.182449,+55.960753+24.170318,+56.017506+24.066605,+55.902317+24.046941,+55.833035+24.01459,+55.801126+24.025482,+55.781754+24.055948,+55.731246+24.058066,+55.485274+23.944384,+55.533725+23.849352,+55.531869+23.757286,+55.569228+23.720734,+55.572308+23.629646,+55.452588+23.465217,+55.430691+23.399593,+55.416507+23.382151,+55.401537+23.392525,+55.232271+23.110348,+55.216283+23.02621,+55.227508+22.791619,+55.21284+22.705686,+55.137388+22.631591,+52.58104+22.939203,+51.590376+24.126971,+51.589825+24.26588,+51.529512+24.336352,+51.416071+24.393194,+51.466454+24.462489,+51.565206+24.553035,+51.589187+24.619704,+51.586122+24.664189,+52.02542+24.75828,+52.309194+24.842176,+52.378334+24.900336,+52.337088+24.949252,+52.345961+24.997718,+52.405921+25.018775,+52.450032+24.982958,+52.647202+25.143128,+52.894479+25.470458,+54.182354+25.450646,+55.13142+25.544679))',
)
.then((response) => {
return response.json();
Expand All @@ -38,12 +40,12 @@ function createDeckLayer(data, map) {
pickable: true,

parameters: {
depthTest: false,
depthTest: true,
},
radius: 100,
elevationScale: 4,
elevationScale: 1,
getPosition: (d: any) => [d.point.lon, d.point.lat],
extruded: false,
extruded: true,
} as any);
// todo need add call in map.addLayer(layer) for customLayer
poiLayer.onAdd(map, map.getWebGLContext());
Expand Down
292 changes: 292 additions & 0 deletions src/mapglViewport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
import { WebMercatorViewport } from '@deck.gl/core';

export default class MapglViewport {
static displayName = 'WebMercatorViewport';
viewport: WebMercatorViewport;

constructor(viewport: WebMercatorViewport) {
this.viewport = viewport;
}

getDistanceScales(coordinateOrigin?: number[]) {
return this.viewport.getDistanceScales(coordinateOrigin)
}

get longitude(): number {
return this.viewport.longitude
}
get latitude(): number {
return this.viewport.latitude
}
get pitch(): number {
return this.viewport.pitch
}
get bearing(): number {
return this.viewport.bearing
}
get altitude(): number {
return this.viewport.altitude
}
get fovy(): number {
return this.viewport.fovy
}
get orthographic(): number {
return this.viewport.orthographic
}

get metersPerPixel(): number {
return this.viewport.metersPerPixel
}

get projectionMode(): number {
return this.viewport.projectionMode
}

get id(): string {
return this.viewport.id
}
get x(): number {
return this.viewport.x
}
get y(): number {
return this.viewport.y
}
get width(): number {
return this.viewport.width
}
get height(): number {
return this.viewport.height
}
get isGeospatial(): boolean {
return this.viewport.isGeospatial
}
get zoom(): number {
return this.viewport.zoom
}
get focalDistance(): number {
return this.viewport.focalDistance
}
get position(): number[] {
return this.viewport.position
}
get modelMatrix(): number[] | null {
return this.viewport.modelMatrix
}

/** Derived parameters */

// `!` post-fix expression operator asserts that its operand is non-null and non-undefined in contexts
// where the type checker is unable to conclude that fact.

get distanceScales(): any {
return this.viewport.distanceScales
}
get scale(): number {
return this.viewport.scale
}
get center(): number[] {
return this.viewport.center
}
get cameraPosition(): number[] {
return this.viewport.cameraPosition
}
get projectionMatrix(): number[] {
return this.viewport.projectionMatrix
}
get viewMatrix(): number[] {
return this.viewport.viewMatrix
}
get viewMatrixUncentered(): number[] {
return this.viewport.viewMatrixUncentered
}
get viewMatrixInverse(): number[] {
return this.viewport.viewMatrixInverse
}
get viewProjectionMatrix(): number[] {
return this.viewport.viewProjectionMatrix
}
get pixelProjectionMatrix(): number[] {
return this.viewport.pixelProjectionMatrix
}
get pixelUnprojectionMatrix(): number[] {
return this.viewport.pixelUnprojectionMatrix
}
get resolution(): number[] {
return this.viewport.resolution
}



// Two viewports are equal if width and height are identical, and if
// their view and projection matrices are (approximately) equal.
equals(viewport: any): boolean {
return this.viewport.equals(viewport)
}

/**
* Projects xyz (possibly latitude and longitude) to pixel coordinates in window
* using viewport projection parameters
* - [longitude, latitude] to [x, y]
* - [longitude, latitude, Z] => [x, y, z]
* Note: By default, returns top-left coordinates for canvas/SVG type render
*
* @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z]
* @param {Object} opts - options
* @param {Object} opts.topLeft=true - Whether projected coords are top left
* @return {Array} - [x, y] or [x, y, z] in top left coords
*/
project(xyz: number[], { topLeft = true }: { topLeft?: boolean } = {}): number[] {
return this.viewport.project(xyz, { topLeft })
}

/**
* Unproject pixel coordinates on screen onto world coordinates,
* (possibly [lon, lat]) on map.
* - [x, y] => [lng, lat]
* - [x, y, z] => [lng, lat, Z]
* @param {Array} xyz -
* @param {Object} opts - options
* @param {Object} opts.topLeft=true - Whether origin is top left
* @return {Array|null} - [lng, lat, Z] or [X, Y, Z]
*/
unproject(
xyz: number[],
{ topLeft = true, targetZ }: { topLeft?: boolean; targetZ?: number } = {}
): number[] {
return this.viewport.unproject(xyz, { topLeft, targetZ })
}

// NON_LINEAR PROJECTION HOOKS
// Used for web meractor projection

projectPosition(xyz: number[]): [number, number, number] {
console.log(xyz,this.viewport.projectPosition(xyz));
return this.viewport.projectPosition(xyz)
}

unprojectPosition(xyz: number[]): [number, number, number] {
return this.viewport.unprojectPosition(xyz)
}

/**
* Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
* Performs the nonlinear part of the web mercator projection.
* Remaining projection is done with 4x4 matrices which also handles
* perspective.
* @param {Array} lngLat - [lng, lat] coordinates
* Specifies a point on the sphere to project onto the map.
* @return {Array} [x,y] coordinates.
*/
projectFlat(xyz: number[]): [number, number] {
return this.viewport.projectFlat(xyz)
}

/**
* Unproject world point [x,y] on map onto {lat, lon} on sphere
* @param {object|Vector} xy - object with {x,y} members
* representing point on projected map plane
* @return {GeoCoordinates} - object with {lat,lon} of point on sphere.
* Has toArray method if you need a GeoJSON Array.
* Per cartographic tradition, lat and lon are specified as degrees.
*/
unprojectFlat(xyz: number[]): [number, number] {
return this.viewport.unprojectFlat(xyz)
}

/**
* Get bounds of the current viewport
* @return {Array} - [minX, minY, maxX, maxY]
*/
getBounds(options: { z?: number } = {}): [number, number, number, number] {
return this.viewport.getBounds(options)
}


containsPixel({
x,
y,
width = 1,
height = 1
}: {
x: number;
y: number;
width?: number;
height?: number;
}): boolean {
return this.viewport.containsPixel(x, y, width, height)
}

// Extract frustum planes in common space
getFrustumPlanes(): {
left: any;
right: any;
bottom: any;
top: any;
near: any;
far: any;
} {
return this.viewport.getFrustumPlanes()
}

// EXPERIMENTAL METHODS

/**
* Needed by panning and linear transition
* Pan the viewport to place a given world coordinate at screen point [x, y]
*
* @param {Array} coords - world coordinates
* @param {Array} pixel - [x,y] coordinates on screen
* @return {Object} props of the new viewport
*/
panByPosition(coords: number[], pixel: number[]): any {
return this.viewport.panByPosition(coords, pixel);
}

get subViewports(): WebMercatorViewport[] | null {
return this.viewport.subViewports
}


/**
* Add a meter delta to a base lnglat coordinate, returning a new lnglat array
*
* Note: Uses simple linear approximation around the viewport center
* Error increases with size of offset (roughly 1% per 100km)
*
* @param {[Number,Number]|[Number,Number,Number]) lngLatZ - base coordinate
* @param {[Number,Number]|[Number,Number,Number]) xyz - array of meter deltas
* @return {[Number,Number]|[Number,Number,Number]) array of [lng,lat,z] deltas
*/
addMetersToLngLat(lngLatZ: number[], xyz: number[]): number[] {
return this.viewport.addMetersToLngLat(lngLatZ, xyz)
}




/**
* Returns a new viewport that fit around the given rectangle.
* Only supports non-perspective mode.
*/
fitBounds(
/** [[lon, lat], [lon, lat]] */
bounds: [[number, number], [number, number]],
options: {
/** If not supplied, will use the current width of the viewport (default `1`) */
width?: number;
/** If not supplied, will use the current height of the viewport (default `1`) */
height?: number;
/** In degrees, 0.01 would be about 1000 meters */
minExtent?: number;
/** Max zoom level */
maxZoom?: number;
/** Extra padding in pixels */
padding?: number | Required<any>;
/** Center shift in pixels */
offset?: number[];
} = {}
) {
return this.viewport.fitBounds(bounds, options);
}

}
15 changes: 11 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import type { Map } from '@2gis/mapgl/types';

import { DeckCustomLayer } from './types';
import { Deck2gisLayer } from './deckgl2gisLayer';
import MapglViewport from './mapglViewport';

type UserData = {
isExternal: boolean;
currentViewport?: WebMercatorViewport | null;
currentViewport?: MapglViewport | null;
customLayers: Set<DeckCustomLayer>;
};

Expand Down Expand Up @@ -98,21 +99,27 @@ export function updateLayer(deck: Deck, _layer: Deck2gisLayer<any>): void {
updateLayers(deck);
}

export function drawLayer(deck: Deck, map: Map, layer: Deck2gisLayer<any>): void {
export function drawLayer(deck: Deck, map: Map, layer: Deck2gisLayer<any>, m?): void {
let { currentViewport } = deck.userData as UserData;
let clearStack = false;
if (!currentViewport) {
// This is the first layer drawn in this render cycle.
// Generate viewport from the current map state.
currentViewport = getViewport(deck, map, true);

// Обвертка над вьюпортом WebMercatorViewport
// попробовать тут применить наши матрицы проекций на карту и на экран
currentViewport = new MapglViewport(getViewport(deck, map, true, m));
(deck.userData as UserData).currentViewport = currentViewport;
clearStack = true;
}

if (!deck.isInitialized) {
return;
}

// отчистить буфер глубины что бы перекрыть 3д объекты карты
//const gl = map.getWebGLContext();
//gl.clear(gl.DEPTH_BUFFER_BIT);
//gl.clearDepth(0);
deck._drawLayers('2gis-repaint', {
viewports: [currentViewport],
layerFilter: ({ layer: deckLayer }) => layer.id === deckLayer.id,
Expand Down