ngageoint / opensphere-asm

opensphere-asm
Apache License 2.0
9 stars 6 forks source link

Can this be adapted to convert to UTM as well? #12

Open jayarjo opened 3 years ago

jayarjo commented 3 years ago

This is not a report but rather a question. I see that these modules can be used to convert to LatLon or MGRS. Do you think it will be relatively easy to add conversion to UTM as well?

schmidtk commented 3 years ago

Yes it would be relatively straightforward to support converting to/from UTM. Our MGRS conversion already converts to UTM as an intermediate step due to the GeographicLib MGRS API, so they would be a good basis for new UTM functions.

https://github.com/ngageoint/opensphere-asm/blob/92de38be1cf6b7c72cf440e5630044230d4867ee/src/bindings.cpp#L161-L162

https://github.com/ngageoint/opensphere-asm/blob/92de38be1cf6b7c72cf440e5630044230d4867ee/src/bindings.cpp#L172-L174

jayarjo commented 3 years ago

@schmidtk thanks for taking your time to respond! I just did that. I also removed all the bindings that we do not require in an effort to reduce the size of resulting wasm file. However it still weighs 150+kb. I thought it would be much smaller. Is such size typical? Any way to shrink it any further (before gzipping)?

schmidtk commented 3 years ago

@wallw-bits may be more familiar with what contributes to the wasm size, but that does seem hefty. We may want to look into optimizing that further.

jayarjo commented 3 years ago

@schmidtk without my "optimizations" it was even bigger - 200+kb.

jayarjo commented 3 years ago

Actually I now went on and dropped every source file and unrelated includes except UTMUPS and resulting wasm file didn't decrease in size, which makes me think that it might be some kind of boilerplate taking up the space?

jayarjo commented 3 years ago

Even with -0z it didn't shrink below 141kb :/

schmidtk commented 3 years ago

Emscripten does include some boilerplate, though that still feels excessive to me.

wallw-teal commented 3 years ago

You want -0s or -0z for optimizing for size when building Web Assembly. Something like this:

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int add(int x, int y) {
  return x + y;
}

Should be ~42 bytes:

 (type $0 (func (param i32 i32) (result i32)))
 (export "_add" (func $0))
 (func $0 (; 0 ;) (type $0) (param $var$0 i32) (param $var$1 i32) (result i32)
  (i32.add
   (get_local $var$1)
   (get_local $var$0)
  )
 )
)

As for your specific problem, that depends on your code, which you haven't shared. If you're concerned about size, there are JS implementations of UTM conversion that are ~5.8kb. For this particular project, we are concerned about performance and accuracy for the direct and inverse geodesic/rhumb problems.

jayarjo commented 3 years ago

It builds with:

emcc --bind -Oz --pre-js src/prefix.js --post-js src/postfix.js --llvm-lto 1 -s NO_FILESYSTEM=1 -Ilib/geographiclib/include/ -s WASM=1 -o dist/os-wasm.js ... src

My bindings.cpp:

#include <emscripten/bind.h>
#include <GeographicLib/UTMUPS.hpp>

using namespace GeographicLib;
using namespace emscripten;

// coordinate conversion
void UTM2LL(double x, double y, int zone, intptr_t ptr)
{
  bool northp = true;
  double *result = reinterpret_cast<double *>(ptr);
  UTMUPS::Reverse(zone, northp, x, y, result[1], result[0]);
};

void LL2UTM(double lat, double lng, int zone, intptr_t ptr)
{
  bool northp = true;
  double *result = reinterpret_cast<double *>(ptr);
  UTMUPS::Forward(lat, lng, zone, northp, result[1], result[0]);
};

EMSCRIPTEN_BINDINGS(GeographicLib)
{
  function("UTM2LL_", &UTM2LL);
  function("LL2UTM_", &LL2UTM);
}

I've also stripped whole lib to just three files: Math.cpp, TransverseMercator.cpp and UTMUPS.cpp.

I've seen other libraries, but they are not accurate, this is why I'm considering alternative options :/ But 141kb feels unnecessarily excessive. I tested it and algorithm produces much more accurate conversions, but I'm now considering to maybe port it to pure JavaScript (because of this size outcome).

jayarjo commented 3 years ago

For this particular project, we are concerned about performance and accuracy for the direct and inverse geodesic/rhumb problems.

I understand, but it feels like there's 100+kb of overhead (at least) of something unrelated in the final .wasm file.

wallw-teal commented 3 years ago

That's just the size of the emscripten bindings plus the size of the the geographiclib dependency. If I compile just the add function above, but exposed with emscripten/bind.h (which adds type checks when crossing the JS/WASM bridge), then the resulting output is ~37kb. The rest is GeographicLib and whatever it includes.

wallw-teal commented 3 years ago

For this particular project, we are concerned about performance and accuracy for the direct and inverse geodesic/rhumb problems.

I understand, but it feels like there's 100+kb of overhead (at least) of something unrelated in the final .wasm file.

Web Assembly is, unfortunately, entirely statically linked.