I'm reading the values directly from the Buffer object that is returned from fs.readFile using buffer.readUInt32LE and buffer[index], then convert the values to doubles to do the hit-test and if it succeeds, it's immediately written to the output buffer.
The nodejs Buffer object is a subclass of Uint8Array as far as I know.
On writing, the double coordinate values are transformed back into a fixed-precision integer format and stored in the output Buffer object.
I'm not generating an intermediate buffer since that does decrease performance a bit. It's directly from input buffer to output buffer. Output buffer is initially allocated with the same size as the input, and before sending it to the output stream it's cut to the actual size.
One thing I've previously learned and which has shown to be still true is that writing individual bytes to a buffer is faster than writing integers.
So originally I did this:
outBuffer.writeInt32LE(ux, outOffset + 0);
But this turned out to be significantly faster. (~20%)
// do once
let tmpBuffer = new ArrayBuffer(4);
let tmpUint32 = new Uint32Array(tmpBuffer);
let tmpUint8 = new Uint8Array(tmpBuffer);
// do many times
tmpUint32[0] = ux;
outBuffer[outOffset + 0] = tmpUint8[0];
outBuffer[outOffset + 1] = tmpUint8[1];
outBuffer[outOffset + 2] = tmpUint8[2];
outBuffer[outOffset + 3] = tmpUint8[3];
The buffer contains not just integer but also byte, unsigned byte, short, etc. Due to this, the buffer length may not be a multiple of 4, and Uint32Array views can only be constructed on buffers with a length of a multiple of 4.
Edit:
Also, the stride from one record to the next can be anything, e.g. 15. An Uint32Array would need a stride of 4 or a multiple of 4 to be useful.
Edit2:
I could try to create 4 Uint32Arrays with byteOffsets 0 to 3, and with a view length of a multiple of 4, then use the one that works with the attribute I'm currently processing. Not sure if that's really going to be faster but who knows.