@reearth/core 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.js +12486 -9418
- package/dist/core.umd.cjs +76 -73
- package/package.json +4 -2
- package/src/.DS_Store +0 -0
- package/src/Map/utils.ts +8 -2
- package/src/engines/Cesium/.DS_Store +0 -0
- package/src/engines/Cesium/Feature/.DS_Store +0 -0
- package/src/engines/Cesium/core/.DS_Store +0 -0
- package/src/engines/Cesium/hooks.ts +6 -0
- package/src/engines/Cesium/type.d.ts +0 -1
- package/src/engines/Cesium/utils/polygon.ts +2 -2
- package/src/mantle/atoms/compute.ts +2 -2
- package/src/mantle/data/gpx.ts +1 -1
- package/src/mantle/data/shapefile/index.ts +51 -0
- package/src/mantle/data/shapefile/parseDbf.ts +85 -0
- package/src/mantle/data/shapefile/parseShp.ts +459 -0
- package/src/mantle/data/shapefile/parseZip.ts +64 -0
- package/src/mantle/evaluator/simple/expression/variableReplacer.ts +0 -2
- package/src/mantle/evaluator/simple/index.ts +0 -5
- package/src/mantle/evaluator/simple/utils.ts +0 -1
- package/src/test/utils.tsx +0 -2
- package/src/utils/.DS_Store +0 -0
- package/src/mantle/data/shapefile.ts +0 -232
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import type { GeoJSON } from "geojson";
|
|
2
|
-
import JSZip from "jszip";
|
|
3
|
-
|
|
4
|
-
import type { Data, DataRange, Feature } from "../types";
|
|
5
|
-
|
|
6
|
-
import { processGeoJSON } from "./geojson";
|
|
7
|
-
import { f, FetchOptions } from "./utils";
|
|
8
|
-
|
|
9
|
-
export async function fetchShapefile(
|
|
10
|
-
data: Data,
|
|
11
|
-
range?: DataRange,
|
|
12
|
-
options?: FetchOptions,
|
|
13
|
-
): Promise<Feature[] | void> {
|
|
14
|
-
const arrayBuffer = data.url ? await (await f(data.url, options)).arrayBuffer() : data.value;
|
|
15
|
-
const zip = await JSZip.loadAsync(new Uint8Array(arrayBuffer));
|
|
16
|
-
|
|
17
|
-
let shpFileArrayBuffer: ArrayBuffer | undefined;
|
|
18
|
-
let dbfFileArrayBuffer: ArrayBuffer | undefined;
|
|
19
|
-
|
|
20
|
-
// Access the files inside the ZIP archive
|
|
21
|
-
const zipEntries = Object.values(zip.files);
|
|
22
|
-
for (const entry of zipEntries) {
|
|
23
|
-
const filename = entry.name;
|
|
24
|
-
if (filename.endsWith(".shp")) {
|
|
25
|
-
shpFileArrayBuffer = await entry.async("arraybuffer");
|
|
26
|
-
} else if (filename.endsWith(".dbf")) {
|
|
27
|
-
dbfFileArrayBuffer = await entry.async("arraybuffer");
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (shpFileArrayBuffer && dbfFileArrayBuffer) {
|
|
32
|
-
return processGeoJSON(await parseShapefiles(shpFileArrayBuffer, dbfFileArrayBuffer), range);
|
|
33
|
-
} else {
|
|
34
|
-
throw new Error(`Zip archive does not contain .shp and .dbf files`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const parseShapefiles = async (
|
|
39
|
-
shpFile: ArrayBuffer,
|
|
40
|
-
dbfFile: ArrayBuffer,
|
|
41
|
-
configuration?: Configuration,
|
|
42
|
-
): Promise<GeoJSON> => {
|
|
43
|
-
return new ShapefileParser(shpFile, dbfFile, configuration).parse();
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
interface Configuration {
|
|
47
|
-
trim?: boolean;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
class ShapefileParser {
|
|
51
|
-
#shp: ArrayBuffer;
|
|
52
|
-
#dbf: ArrayBuffer;
|
|
53
|
-
#configuration?: Configuration;
|
|
54
|
-
#features: any[] = [];
|
|
55
|
-
#propertiesArray: any[] = [];
|
|
56
|
-
|
|
57
|
-
constructor(shp: ArrayBuffer, dbf: ArrayBuffer, configuration?: Configuration) {
|
|
58
|
-
this.#shp = shp;
|
|
59
|
-
this.#dbf = dbf;
|
|
60
|
-
this.#configuration = configuration;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
#parseShp() {
|
|
64
|
-
const dataView = new DataView(this.#shp);
|
|
65
|
-
let idx = 0;
|
|
66
|
-
const wordLength = dataView.getInt32((idx += 6 * 4), false);
|
|
67
|
-
const byteLength = wordLength * 2;
|
|
68
|
-
idx += 4; //version
|
|
69
|
-
idx += 4; //shapeType
|
|
70
|
-
idx += 4; //minX, minY
|
|
71
|
-
idx += 8 * 8; //min(Y, Z, M),max(X, Y, Z, M)
|
|
72
|
-
|
|
73
|
-
const features: any[] = [];
|
|
74
|
-
while (idx < byteLength) {
|
|
75
|
-
const feature: any = {};
|
|
76
|
-
const length: number = dataView.getInt32((idx += 4), false);
|
|
77
|
-
|
|
78
|
-
const type: number = dataView.getInt32((idx += 4), true);
|
|
79
|
-
let idxFeature: number = idx + 4;
|
|
80
|
-
let numberOfParts: number, nbpoints: number, numberOfPoints: number, nbpartsPoint: number[];
|
|
81
|
-
switch (type) {
|
|
82
|
-
case 1:
|
|
83
|
-
case 11:
|
|
84
|
-
case 21:
|
|
85
|
-
feature.type = "Point";
|
|
86
|
-
feature.coordinates = [
|
|
87
|
-
dataView.getFloat64(idxFeature, true),
|
|
88
|
-
dataView.getFloat64(idxFeature + 8, true),
|
|
89
|
-
];
|
|
90
|
-
break;
|
|
91
|
-
case 3:
|
|
92
|
-
case 13:
|
|
93
|
-
case 23:
|
|
94
|
-
case 5:
|
|
95
|
-
case 15:
|
|
96
|
-
case 25:
|
|
97
|
-
if (type === 3 || type === 13 || type === 23) {
|
|
98
|
-
feature.type = "MultiLineString";
|
|
99
|
-
} else if (type === 5 || type === 15 || type === 25) {
|
|
100
|
-
feature.type = "Polygon";
|
|
101
|
-
}
|
|
102
|
-
numberOfParts = dataView.getInt32(idxFeature + 32, true);
|
|
103
|
-
nbpoints = dataView.getInt32(idxFeature + 36, true);
|
|
104
|
-
idxFeature += 40;
|
|
105
|
-
nbpartsPoint = new Array(numberOfParts).fill(0).map(() => {
|
|
106
|
-
const result = dataView.getInt32(idxFeature, true);
|
|
107
|
-
idxFeature += 4;
|
|
108
|
-
return result;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
feature.coordinates = new Array(numberOfParts).fill(0).map((_, i) => {
|
|
112
|
-
const idstart = nbpartsPoint[i];
|
|
113
|
-
const idend = (i < numberOfParts - 1 ? nbpartsPoint[i + 1] : nbpoints) - 1;
|
|
114
|
-
const part = [];
|
|
115
|
-
for (let j = idstart; j <= idend; j++) {
|
|
116
|
-
part.push([
|
|
117
|
-
dataView.getFloat64(idxFeature, true),
|
|
118
|
-
dataView.getFloat64(idxFeature + 8, true),
|
|
119
|
-
]);
|
|
120
|
-
idxFeature += 16;
|
|
121
|
-
}
|
|
122
|
-
return part;
|
|
123
|
-
});
|
|
124
|
-
break;
|
|
125
|
-
case 8:
|
|
126
|
-
case 18:
|
|
127
|
-
case 28:
|
|
128
|
-
feature.type = "MultiPoint";
|
|
129
|
-
numberOfPoints = dataView.getInt32(idxFeature + 32, true);
|
|
130
|
-
idxFeature += 36;
|
|
131
|
-
feature.coordinates = new Array(numberOfPoints).fill(0).map(() => {
|
|
132
|
-
const result = [
|
|
133
|
-
dataView.getFloat64(idxFeature, true),
|
|
134
|
-
dataView.getFloat64(idxFeature + 8, true),
|
|
135
|
-
];
|
|
136
|
-
idxFeature += 16;
|
|
137
|
-
return result;
|
|
138
|
-
});
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
idx += length * 2;
|
|
143
|
-
features.push(feature);
|
|
144
|
-
}
|
|
145
|
-
this.#features = features;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
#parseDbf() {
|
|
149
|
-
const dataView = new DataView(new Uint8Array(this.#dbf).buffer);
|
|
150
|
-
let idx = 4;
|
|
151
|
-
const numberOfRecords: number = dataView.getInt32(idx, true);
|
|
152
|
-
idx += 28;
|
|
153
|
-
let end = false;
|
|
154
|
-
const fields = [];
|
|
155
|
-
while (!end) {
|
|
156
|
-
const field: any = {};
|
|
157
|
-
const nameArray: string[] = [];
|
|
158
|
-
for (let i = 0; i < 10; i++) {
|
|
159
|
-
const letter = dataView.getUint8(idx);
|
|
160
|
-
if (letter !== 0) {
|
|
161
|
-
nameArray.push(String.fromCharCode(letter));
|
|
162
|
-
}
|
|
163
|
-
idx += 1;
|
|
164
|
-
}
|
|
165
|
-
field.name = nameArray.join("");
|
|
166
|
-
idx += 1;
|
|
167
|
-
field.type = String.fromCharCode(dataView.getUint8(idx));
|
|
168
|
-
idx += 5;
|
|
169
|
-
field.fieldLength = dataView.getUint8(idx);
|
|
170
|
-
idx += 16;
|
|
171
|
-
fields.push(field);
|
|
172
|
-
if (dataView.getUint8(idx) === 0x0d) {
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
idx += 1;
|
|
177
|
-
const propertiesArray = [];
|
|
178
|
-
for (let i = 0; i < numberOfRecords; i++) {
|
|
179
|
-
const properties: any = {};
|
|
180
|
-
if (!end) {
|
|
181
|
-
try {
|
|
182
|
-
idx += 1;
|
|
183
|
-
for (let j = 0; j < fields.length; j++) {
|
|
184
|
-
let str = "";
|
|
185
|
-
const charString = [];
|
|
186
|
-
for (let h = 0; h < fields[j].fieldLength; h++) {
|
|
187
|
-
charString.push(String.fromCharCode(dataView.getUint8(idx)));
|
|
188
|
-
idx += 1;
|
|
189
|
-
}
|
|
190
|
-
str = charString.join("");
|
|
191
|
-
// }
|
|
192
|
-
if (this.#configuration?.trim !== false) {
|
|
193
|
-
str = str.trim();
|
|
194
|
-
}
|
|
195
|
-
const number = parseFloat(str);
|
|
196
|
-
if (isNaN(number)) {
|
|
197
|
-
properties[fields[j].name] = str;
|
|
198
|
-
} else {
|
|
199
|
-
properties[fields[j].name] = number;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
} catch (err) {
|
|
203
|
-
end = true;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
propertiesArray.push(properties);
|
|
207
|
-
}
|
|
208
|
-
this.#propertiesArray = propertiesArray;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
#geoJSON() {
|
|
212
|
-
const geojson: any = {
|
|
213
|
-
type: "FeatureCollection",
|
|
214
|
-
features: [],
|
|
215
|
-
};
|
|
216
|
-
for (let i = 0; i < Math.min(this.#features.length, this.#propertiesArray.length); i++) {
|
|
217
|
-
geojson.features.push({
|
|
218
|
-
type: "Feature",
|
|
219
|
-
geometry: this.#features[i],
|
|
220
|
-
properties: this.#propertiesArray[i],
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
return geojson;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
parse(): GeoJSON {
|
|
227
|
-
this.#parseShp();
|
|
228
|
-
this.#parseDbf();
|
|
229
|
-
|
|
230
|
-
return this.#geoJSON();
|
|
231
|
-
}
|
|
232
|
-
}
|