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

iTowns / itowns / 6979781676

24 Nov 2023 10:44AM UTC coverage: 77.111% (+0.1%) from 77.004%
6979781676

Pull #2223

github

web-flow
Merge 23836a3b7 into 1d10290b5
Pull Request #2223: Fix base alti for mesh 3d

4051 of 5992 branches covered (0.0%)

Branch coverage included in aggregate %.

216 of 238 new or added lines in 9 files covered. (90.76%)

9 existing lines in 4 files now uncovered.

7986 of 9618 relevant lines covered (83.03%)

1640.25 hits per line

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

75.39
/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,735!
6

7
const context = new StyleContext();
1✔
8
let userStyle = new Style();
1✔
9

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

38
function _drawPolygon(ctx, vertices, indices, style, size, extent, invCtxScale, canBeFilled) {
39
    // build contour
40
    const path = new Path2D();
3✔
41

42
    for (const indice of indices) {
4✔
43
        if (indice.extent && Extent.intersectsExtent(indice.extent, extent)) {
4!
44
            const offset = indice.offset * size;
4✔
45
            const count = offset + indice.count * size;
4✔
46
            path.moveTo(vertices[offset], vertices[offset + 1]);
4✔
47
            for (let j = offset + size; j < count; j += size) {
4✔
48
                path.lineTo(vertices[j], vertices[j + 1]);
12✔
49
            }
50
        }
51
    }
3✔
52
    Style.prototype.applyToCanvasPolygon.call(style, ctx, path, invCtxScale, canBeFilled);
3✔
53
}
54

55
function drawPoint(ctx, x, y, style = {}, invCtxScale) {
1!
56
    ctx.beginPath();
1✔
57
    const opacity = style.point.opacity == undefined ? 1.0 : style.point.opacity;
1!
58
    if (opacity !== ctx.globalAlpha) {
1!
59
        ctx.globalAlpha = opacity;
1✔
60
    }
61

62
    ctx.arc(x, y, (style.point.radius || 3.0) * invCtxScale, 0, 2 * Math.PI, false);
1!
63
    if (style.point.color) {
1!
64
        ctx.fillStyle = style.point.color;
1✔
65
        ctx.fill();
1✔
66
    }
67
    if (style.point.line) {
1!
68
        ctx.lineWidth = (style.point.width || 1.0) * invCtxScale;
1✔
69
        ctx.strokeStyle = style.point.line;
1✔
70
        ctx.stroke();
1✔
71
    }
72
}
73

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

76
function drawFeature(ctx, feature, extent, invCtxScale) {
77
    const extentDim = extent.planarDimensions();
2✔
78
    const scaleRadius = extentDim.x / ctx.canvas.width;
2✔
79

80
    for (const geometry of feature.geometries) {
4✔
81
        if (Extent.intersectsExtent(geometry.extent, extent)) {
4!
82
            context.setGeometry(geometry);
4✔
83

84
            userStyle.setContext(context);
4✔
85

86
            if (userStyle) {
4!
87
                if (
4✔
88
                    feature.type === FEATURE_TYPES.POINT && userStyle.point
5✔
89
                ) {
90
                    // cross multiplication to know in the extent system the real size of
91
                    // the point
92
                    const px = (Math.round(userStyle.point.radius * invCtxScale) || 3 * invCtxScale) * scaleRadius;
1!
93
                    for (const indice of geometry.indices) {
1✔
94
                        const offset = indice.offset * feature.size;
1✔
95
                        const count = offset + indice.count * feature.size;
1✔
96
                        for (let j = offset; j < count; j += feature.size) {
1✔
97
                            coord.setFromArray(feature.vertices, j);
1✔
98
                            if (extent.isPointInside(coord, px)) {
1!
99
                                drawPoint(ctx, feature.vertices[j], feature.vertices[j + 1], userStyle, invCtxScale);
1✔
100
                            }
101
                        }
102
                    }
1✔
103
                } else {
104
                    drawPolygon(ctx, feature.vertices, geometry.indices, userStyle, feature.size, extent, invCtxScale, (feature.type == FEATURE_TYPES.POLYGON));
3✔
105
                }
106
            }
107
        }
108
    }
2✔
109
}
110

111
const origin = new THREE.Vector3();
1✔
112
const dimension = new THREE.Vector3(0, 0, 1);
1✔
113
const scale = new THREE.Vector3();
1✔
114
const quaternion = new THREE.Quaternion();
1✔
115
const world2texture = new THREE.Matrix4();
1✔
116
const feature2texture = new THREE.Matrix4();
1✔
117
const worldTextureOrigin = new THREE.Vector3();
1✔
118

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

121
export default {
1✔
122
    // backgroundColor is a THREE.Color to specify a color to fill the texture
123
    // with, given there is no feature passed in parameter
124
    createTextureFromFeature(collection, extent, sizeTexture, layerStyle = userStyle, backgroundColor) {
1!
125
        let texture;
126
        userStyle = layerStyle;
1✔
127

128
        if (collection) {
1!
129
            // A texture is instancied drawn canvas
130
            // origin and dimension are used to transform the feature's coordinates to canvas's space
131
            extent.planarDimensions(dimension);
1✔
132
            const c = document.createElement('canvas');
1✔
133

134
            coord.crs = extent.crs;
1✔
135

136
            c.width = sizeTexture;
1✔
137
            c.height = sizeTexture;
1✔
138
            const ctx = c.getContext('2d');
1✔
139
            if (backgroundColor) {
1!
140
                ctx.fillStyle = backgroundColor.getStyle();
×
141
                ctx.fillRect(0, 0, sizeTexture, sizeTexture);
×
142
            }
143

144
            // Documentation needed !!
145
            ctx.globalCompositeOperation = layerStyle.globalCompositeOperation || 'source-over';
1✔
146
            ctx.imageSmoothingEnabled = false;
1✔
147
            ctx.lineJoin = 'round';
1✔
148

149
            // transform extent to feature projection
150
            extent.as(collection.crs, featureExtent);
1✔
151
            // transform extent to local system
152
            featureExtent.applyMatrix4(collection.matrixWorldInverse);
1✔
153

154
            // compute matrix transformation `world2texture` to convert coordinates to texture coordinates
155
            if (collection.isInverted) {
1!
156
                worldTextureOrigin.set(extent.west, extent.north, 0);
×
157
                scale.set(ctx.canvas.width, -ctx.canvas.height, 1.0).divide(dimension);
×
158
            } else {
159
                worldTextureOrigin.set(extent.west, extent.south, 0);
1✔
160
                scale.set(ctx.canvas.width, ctx.canvas.height, 1.0).divide(dimension);
1✔
161
            }
162

163
            world2texture.compose(worldTextureOrigin.multiply(scale).negate(), quaternion, scale);
1✔
164

165
            // compute matrix transformation `feature2texture` to convert features coordinates to texture coordinates
166
            feature2texture.multiplyMatrices(world2texture, collection.matrixWorld);
1✔
167
            feature2texture.decompose(origin, quaternion, scale);
1✔
168

169
            ctx.setTransform(scale.x, 0, 0, scale.y, origin.x, origin.y);
1✔
170

171
            // to scale line width and radius circle
172
            const invCtxScale = Math.abs(1 / scale.x);
1✔
173

174
            context.setZoom(extent.zoom);
1✔
175

176
            // Draw the canvas
1✔
177
            for (const feature of collection.features) {
2✔
178
                context.setFeature(feature);
2✔
179
                drawFeature(ctx, feature, featureExtent, invCtxScale);
2✔
180
            }
1✔
181

182
            texture = new THREE.CanvasTexture(c);
1✔
183
            texture.flipY = collection.isInverted;
1✔
184
        } else if (backgroundColor) {
×
185
            const data = new Uint8Array(3);
×
186
            data[0] = backgroundColor.r * 255;
×
187
            data[1] = backgroundColor.g * 255;
×
188
            data[2] = backgroundColor.b * 255;
×
189
            texture = new THREE.DataTexture(data, 1, 1, THREE.RGBAFormat);
×
190
        } else {
191
            texture = new THREE.Texture();
×
192
        }
193

194
        return texture;
1✔
195
    },
196
};
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

© 2025 Coveralls, Inc