• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iTowns / itowns / 10635241580

30 Aug 2024 03:26PM UTC coverage: 86.966% (-2.8%) from 89.766%
10635241580

push

github

jailln
feat(3dtiles): add new OGC3DTilesLayer using 3d-tiles-renderer-js

Deprecate C3DTilesLayer (replaced by OGC3DTilesLayer).
Add new iGLTFLoader that loads gltf 1.0 and 2.0 files.

2791 of 3694 branches covered (75.55%)

Branch coverage included in aggregate %.

480 of 644 new or added lines in 8 files covered. (74.53%)

2144 existing lines in 111 files now uncovered.

24319 of 27479 relevant lines covered (88.5%)

1024.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.47
/src/Converter/Feature2Texture.js
1
import * as THREE from 'three';
1✔
2
import { FEATURE_TYPES } from 'Core/Feature';
1✔
3
import Extent from 'Core/Geographic/Extent';
1✔
4
import Coordinates from 'Core/Geographic/Coordinates';
1✔
5
import Style, { StyleContext } from 'Core/Style';
1✔
6

1✔
7
const defaultStyle = new Style();
1✔
8
const context = new StyleContext();
1✔
9
let style;
1✔
10

1✔
11
/**
1✔
12
 * Draw polygon (contour, line edge and fill) based on feature vertices into canvas
1✔
13
 * using the given style(s). Several styles will re-draws the polygon each one with
1✔
14
 * a different style.
1✔
15
 * @param      {CanvasRenderingContext2D} ctx - canvas' 2D rendering context.
1✔
16
 * @param      {Number[]} vertices - All the vertices of the Feature.
1✔
17
 * @param      {Object[]} indices - Contains the indices that define the geometry.
1✔
18
 * Objects stored in this array have two properties, an `offset` and a `count`.
1✔
19
* The offset is related to the overall number of vertices in the Feature.
1✔
20
 * @param      {Number} size - The size of the feature.
1✔
21
 * @param      {Number} extent - The extent.
1✔
22
 * @param      {Number} invCtxScale - The ration to scale line width and radius circle.
1✔
23
 * @param      {Boolean} canBeFilled - true if feature.type == FEATURE_TYPES.POLYGON
1✔
24
 */
1✔
25
function drawPolygon(ctx, vertices, indices = [{ offset: 0, count: 1 }], size, extent, invCtxScale, canBeFilled) {
3!
26
    if (vertices.length === 0) {
3!
27
        return;
×
28
    }
×
29
    // build contour
3✔
30
    const path = new Path2D();
3✔
31

3✔
32
    for (const indice of indices) {
3✔
33
        if (indice.extent && Extent.intersectsExtent(indice.extent, extent)) {
4✔
34
            const offset = indice.offset * size;
4✔
35
            const count = offset + indice.count * size;
4✔
36
            path.moveTo(vertices[offset], vertices[offset + 1]);
4✔
37
            for (let j = offset + size; j < count; j += size) {
4✔
38
                path.lineTo(vertices[j], vertices[j + 1]);
12✔
39
            }
12✔
40
        }
4✔
41
    }
4✔
42
    style.applyToCanvasPolygon(ctx, path, invCtxScale, canBeFilled);
3✔
43
}
3✔
44

1✔
45
function drawPoint(ctx, x, y, invCtxScale) {
1✔
46
    ctx.beginPath();
1✔
47
    const opacity = style.point.opacity == undefined ? 1.0 : style.point.opacity;
1!
48
    if (opacity !== ctx.globalAlpha) {
1✔
49
        ctx.globalAlpha = opacity;
1✔
50
    }
1✔
51

1✔
52
    ctx.arc(x, y, (style.point.radius || 3.0) * invCtxScale, 0, 2 * Math.PI, false);
1!
53
    if (style.point.color) {
1✔
54
        ctx.fillStyle = style.point.color;
1✔
55
        ctx.fill();
1✔
56
    }
1✔
57
    if (style.point.line) {
1✔
58
        ctx.lineWidth = (style.point.width || 1.0) * invCtxScale;
1✔
59
        ctx.strokeStyle = style.point.line;
1✔
60
        ctx.stroke();
1✔
61
    }
1✔
62
}
1✔
63

1✔
64
const coord = new Coordinates('EPSG:4326', 0, 0, 0);
1✔
65

1✔
66
function drawFeature(ctx, feature, extent, invCtxScale) {
2✔
67
    const extentDim = extent.planarDimensions();
2✔
68
    const scaleRadius = extentDim.x / ctx.canvas.width;
2✔
69

2✔
70
    for (const geometry of feature.geometries) {
2✔
71
        if (Extent.intersectsExtent(geometry.extent, extent)) {
4✔
72
            context.setGeometry(geometry);
4✔
73

4✔
74
            if (
4✔
75
                feature.type === FEATURE_TYPES.POINT && style.point
4✔
76
            ) {
4✔
77
                // cross multiplication to know in the extent system the real size of
1✔
78
                // the point
1✔
79
                const px = (Math.round(style.point.radius * invCtxScale) || 3 * invCtxScale) * scaleRadius;
1!
80
                for (const indice of geometry.indices) {
1✔
81
                    const offset = indice.offset * feature.size;
1✔
82
                    const count = offset + indice.count * feature.size;
1✔
83
                    for (let j = offset; j < count; j += feature.size) {
1✔
84
                        coord.setFromArray(feature.vertices, j);
1✔
85
                        if (extent.isPointInside(coord, px)) {
1✔
86
                            drawPoint(ctx, feature.vertices[j], feature.vertices[j + 1], invCtxScale);
1✔
87
                        }
1✔
88
                    }
1✔
89
                }
1✔
90
            } else {
4✔
91
                drawPolygon(ctx, feature.vertices, geometry.indices, feature.size, extent, invCtxScale, (feature.type == FEATURE_TYPES.POLYGON));
3✔
92
            }
3✔
93
        }
4✔
94
    }
4✔
95
}
2✔
96

1✔
97
const origin = new THREE.Vector3();
1✔
98
const dimension = new THREE.Vector3(0, 0, 1);
1✔
99
const scale = new THREE.Vector3();
1✔
100
const quaternion = new THREE.Quaternion();
1✔
101
const world2texture = new THREE.Matrix4();
1✔
102
const feature2texture = new THREE.Matrix4();
1✔
103
const worldTextureOrigin = new THREE.Vector3();
1✔
104

1✔
105
const featureExtent = new Extent('EPSG:4326', 0, 0, 0, 0);
1✔
106

1✔
107
export default {
1✔
108
    // backgroundColor is a THREE.Color to specify a color to fill the texture
1✔
109
    // with, given there is no feature passed in parameter
1✔
110
    createTextureFromFeature(collection, extent, sizeTexture, layerStyle, backgroundColor) {
1✔
111
        style = layerStyle || defaultStyle;
1!
112
        style.setContext(context);
1✔
113
        let texture;
1✔
114

1✔
115
        if (collection) {
1✔
116
            // A texture is instancied drawn canvas
1✔
117
            // origin and dimension are used to transform the feature's coordinates to canvas's space
1✔
118
            extent.planarDimensions(dimension);
1✔
119
            const c = document.createElement('canvas');
1✔
120

1✔
121
            coord.crs = extent.crs;
1✔
122

1✔
123
            c.width = sizeTexture;
1✔
124
            c.height = sizeTexture;
1✔
125
            const ctx = c.getContext('2d');
1✔
126
            if (backgroundColor) {
1!
UNCOV
127
                ctx.fillStyle = backgroundColor.getStyle();
×
UNCOV
128
                ctx.fillRect(0, 0, sizeTexture, sizeTexture);
×
UNCOV
129
            }
×
130

1✔
131
            // Documentation needed !!
1✔
132
            ctx.globalCompositeOperation = layerStyle.globalCompositeOperation || 'source-over';
1✔
133
            ctx.imageSmoothingEnabled = false;
1✔
134
            ctx.lineJoin = 'round';
1✔
135

1✔
136
            // transform extent to feature projection
1✔
137
            extent.as(collection.crs, featureExtent);
1✔
138
            // transform extent to local system
1✔
139
            featureExtent.applyMatrix4(collection.matrixWorldInverse);
1✔
140

1✔
141
            // compute matrix transformation `world2texture` to convert coordinates to texture coordinates
1✔
142
            if (collection.isInverted) {
1!
UNCOV
143
                worldTextureOrigin.set(extent.west, extent.north, 0);
×
UNCOV
144
                scale.set(ctx.canvas.width, -ctx.canvas.height, 1.0).divide(dimension);
×
145
            } else {
1✔
146
                worldTextureOrigin.set(extent.west, extent.south, 0);
1✔
147
                scale.set(ctx.canvas.width, ctx.canvas.height, 1.0).divide(dimension);
1✔
148
            }
1✔
149

1✔
150
            world2texture.compose(worldTextureOrigin.multiply(scale).negate(), quaternion, scale);
1✔
151

1✔
152
            // compute matrix transformation `feature2texture` to convert features coordinates to texture coordinates
1✔
153
            feature2texture.multiplyMatrices(world2texture, collection.matrixWorld);
1✔
154
            feature2texture.decompose(origin, quaternion, scale);
1✔
155

1✔
156
            ctx.setTransform(scale.x, 0, 0, scale.y, origin.x, origin.y);
1✔
157

1✔
158
            // to scale line width and radius circle
1✔
159
            const invCtxScale = Math.abs(1 / scale.x);
1✔
160

1✔
161
            context.setZoom(extent.zoom);
1✔
162

1✔
163
            // Draw the canvas
1✔
164
            for (const feature of collection.features) {
1✔
165
                context.setFeature(feature);
2✔
166
                drawFeature(ctx, feature, featureExtent, invCtxScale);
2✔
167
            }
2✔
168

1✔
169
            texture = new THREE.CanvasTexture(c);
1✔
170
            texture.flipY = collection.isInverted;
1✔
171
        } else if (backgroundColor) {
1!
UNCOV
172
            const data = new Uint8Array(3);
×
UNCOV
173
            data[0] = backgroundColor.r * 255;
×
UNCOV
174
            data[1] = backgroundColor.g * 255;
×
UNCOV
175
            data[2] = backgroundColor.b * 255;
×
UNCOV
176
            texture = new THREE.DataTexture(data, 1, 1, THREE.RGBAFormat);
×
UNCOV
177
        } else {
×
UNCOV
178
            texture = new THREE.Texture();
×
UNCOV
179
        }
×
180

1✔
181
        return texture;
1✔
182
    },
1✔
183
};
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc