From 55aa072b8ef13f7c8b7bcd997ce779f040f3dabe Mon Sep 17 00:00:00 2001 From: Pierre Louvart Date: Sun, 10 Nov 2024 15:39:18 +0100 Subject: [PATCH] - Add support for chosing between vertical and horizontal orientation. --- src/projections/airocean.cpp | 161 ++++++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 39 deletions(-) diff --git a/src/projections/airocean.cpp b/src/projections/airocean.cpp index da62bb43bc..ff749b0e09 100644 --- a/src/projections/airocean.cpp +++ b/src/projections/airocean.cpp @@ -21,7 +21,8 @@ namespace { // anonymous namespace const PJ_XYZ p2; const PJ_XYZ p3; }; -} // anonymous namespace +} + /* @@ -35,11 +36,11 @@ namespace { // anonymous namespace some faces are split in two (Australia) and 3 (Japan) subfaces. */ // Define the 23 faces and subfaces -constexpr pj_face ico_faces[23] = {{{0.42015243, 0.07814525, 0.90408255}, {0.51883673, 0.83542038, 0.18133184}, {0.99500944, -0.0913478, 0.04014718}}, {{0.42015243, 0.07814525, 0.90408255}, {-0.41468223, 0.65596241, 0.63067581}, {0.51883673, 0.83542038, 0.18133184}}, {{0.42015243, 0.07814525, 0.90408255}, {-0.51545596, -0.3817169, 0.76720099}, {-0.41468223, 0.65596241, 0.63067581}}, {{0.42015243, 0.07814525, 0.90408255}, {0.3557814, -0.84358, 0.40223423}, {-0.51545596, -0.3817169, 0.76720099}}, {{0.42015243, 0.07814525, 0.90408255}, {0.99500944, -0.0913478, 0.04014718}, {0.3557814, -0.84358, 0.40223423}}, {{0.99500944, -0.0913478, 0.04014718}, {0.51883673, 0.83542038, 0.18133184}, {0.51545596, 0.3817169, -0.76720099}}, {{0.51545596, 0.3817169, -0.76720099}, {0.51883673, 0.83542038, 0.18133184}, {-0.3557814, 0.84358, -0.40223423}}, {{-0.3557814, 0.84358, -0.40223423}, {0.51883673, 0.83542038, 0.18133184}, {-0.41468223, 0.65596241, 0.63067581}}, {{-0.51545596, -0.3817169, 0.76720099}, {-0.99500944, 0.0913478, -0.04014718}, {-0.41468223, 0.65596241, 0.63067581}}, {{-0.51545596, -0.3817169, 0.76720099}, {-0.51883673, -0.83542038, -0.18133184}, {-0.99500944, 0.0913478, -0.04014718}}, {{-0.51545596, -0.3817169, 0.76720099}, {0.3557814, -0.84358, 0.40223423}, {-0.51883673, -0.83542038, -0.18133184}}, {{-0.51883673, -0.83542038, -0.18133184}, {0.3557814, -0.84358, 0.40223423}, {0.41468223, -0.65596241, -0.63067581}}, {{0.41468223, -0.65596241, -0.63067581}, {0.3557814, -0.84358, 0.40223423}, {0.99500944, -0.0913478, 0.04014718}}, {{0.51545596, 0.3817169, -0.76720099}, {0.41468223, -0.65596241, -0.63067581}, {0.99500944, -0.0913478, 0.04014718}}, {{-0.42015243, -0.07814525, -0.90408255}, {-0.3557814, 0.84358, -0.40223423}, {-0.99500944, 0.0913478, -0.04014718}}, {{-0.42015243, -0.07814525, -0.90408255}, {-0.99500944, 0.0913478, -0.04014718}, {-0.51883673, -0.83542038, -0.18133184}}, {{-0.42015243, -0.07814525, -0.90408255}, {-0.51883673, -0.83542038, -0.18133184}, {0.41468223, -0.65596241, -0.63067581}}, {{-0.42015243, -0.07814525, -0.90408255}, {0.41468223, -0.65596241, -0.63067581}, {0.51545596, 0.3817169, -0.76720099}}, {{-0.3557814, 0.84358, -0.40223423}, {-0.38796691, 0.38271738, -0.65315839}, {0.51545596, 0.3817169, -0.76720099}}, {{-0.42015243, -0.07814525, -0.90408255}, {0.51545596, 0.3817169, -0.76720099}, {-0.38796691, 0.38271738, -0.65315839}}, {{-0.99500944, 0.0913478, -0.04014718}, {-0.3557814, 0.84358, -0.40223423}, {-0.58849102, 0.53029673, 0.0627648}}, {{-0.3557814, 0.84358, -0.40223423}, {-0.41468223, 0.65596241, 0.63067581}, {-0.58849102, 0.53029673, 0.0627648}}, {{-0.99500944, 0.0913478, -0.04014718}, {-0.58849102, 0.53029673, 0.0627648}, {-0.41468223, 0.65596241, 0.63067581}}}; +constexpr pj_face base_ico_faces[23] = {{{0.42015243, 0.07814525, 0.90408255}, {0.51883673, 0.83542038, 0.18133184}, {0.99500944, -0.0913478, 0.04014718}}, {{0.42015243, 0.07814525, 0.90408255}, {-0.41468223, 0.65596241, 0.63067581}, {0.51883673, 0.83542038, 0.18133184}}, {{0.42015243, 0.07814525, 0.90408255}, {-0.51545596, -0.3817169, 0.76720099}, {-0.41468223, 0.65596241, 0.63067581}}, {{0.42015243, 0.07814525, 0.90408255}, {0.3557814, -0.84358, 0.40223423}, {-0.51545596, -0.3817169, 0.76720099}}, {{0.42015243, 0.07814525, 0.90408255}, {0.99500944, -0.0913478, 0.04014718}, {0.3557814, -0.84358, 0.40223423}}, {{0.99500944, -0.0913478, 0.04014718}, {0.51883673, 0.83542038, 0.18133184}, {0.51545596, 0.3817169, -0.76720099}}, {{0.51545596, 0.3817169, -0.76720099}, {0.51883673, 0.83542038, 0.18133184}, {-0.3557814, 0.84358, -0.40223423}}, {{-0.3557814, 0.84358, -0.40223423}, {0.51883673, 0.83542038, 0.18133184}, {-0.41468223, 0.65596241, 0.63067581}}, {{-0.51545596, -0.3817169, 0.76720099}, {-0.99500944, 0.0913478, -0.04014718}, {-0.41468223, 0.65596241, 0.63067581}}, {{-0.51545596, -0.3817169, 0.76720099}, {-0.51883673, -0.83542038, -0.18133184}, {-0.99500944, 0.0913478, -0.04014718}}, {{-0.51545596, -0.3817169, 0.76720099}, {0.3557814, -0.84358, 0.40223423}, {-0.51883673, -0.83542038, -0.18133184}}, {{-0.51883673, -0.83542038, -0.18133184}, {0.3557814, -0.84358, 0.40223423}, {0.41468223, -0.65596241, -0.63067581}}, {{0.41468223, -0.65596241, -0.63067581}, {0.3557814, -0.84358, 0.40223423}, {0.99500944, -0.0913478, 0.04014718}}, {{0.51545596, 0.3817169, -0.76720099}, {0.41468223, -0.65596241, -0.63067581}, {0.99500944, -0.0913478, 0.04014718}}, {{-0.42015243, -0.07814525, -0.90408255}, {-0.3557814, 0.84358, -0.40223423}, {-0.99500944, 0.0913478, -0.04014718}}, {{-0.42015243, -0.07814525, -0.90408255}, {-0.99500944, 0.0913478, -0.04014718}, {-0.51883673, -0.83542038, -0.18133184}}, {{-0.42015243, -0.07814525, -0.90408255}, {-0.51883673, -0.83542038, -0.18133184}, {0.41468223, -0.65596241, -0.63067581}}, {{-0.42015243, -0.07814525, -0.90408255}, {0.41468223, -0.65596241, -0.63067581}, {0.51545596, 0.3817169, -0.76720099}}, {{-0.3557814, 0.84358, -0.40223423}, {-0.38796691, 0.38271738, -0.65315839}, {0.51545596, 0.3817169, -0.76720099}}, {{-0.42015243, -0.07814525, -0.90408255}, {0.51545596, 0.3817169, -0.76720099}, {-0.38796691, 0.38271738, -0.65315839}}, {{-0.99500944, 0.0913478, -0.04014718}, {-0.3557814, 0.84358, -0.40223423}, {-0.58849102, 0.53029673, 0.0627648}}, {{-0.3557814, 0.84358, -0.40223423}, {-0.41468223, 0.65596241, 0.63067581}, {-0.58849102, 0.53029673, 0.0627648}}, {{-0.99500944, 0.0913478, -0.04014718}, {-0.58849102, 0.53029673, 0.0627648}, {-0.41468223, 0.65596241, 0.63067581}}}; // Define the centers for each face or subface -constexpr PJ_XYZ ico_centers[23] = {{0.6446662, 0.27407261, 0.37518718999999995}, {0.1747689766666667, 0.5231760133333333, 0.5720300666666667}, {-0.16999525333333332, 0.11746358666666666, 0.7673197833333334}, {0.08682595666666666, -0.38238388333333334, 0.69117259}, {0.5903144233333334, -0.28559418333333336, 0.44882131999999997}, {0.6764340433333333, 0.37526316, -0.18190732333333334}, {0.22617043, 0.68690576, -0.3293677933333333}, {-0.08387563333333335, 0.77832093, 0.13659113999999997}, {-0.6417158766666667, 0.12186443666666665, 0.45257653999999997}, {-0.6764340433333333, -0.37526316, 0.18190732333333334}, {-0.22617043, -0.68690576, 0.3293677933333333}, {0.08387563333333335, -0.77832093, -0.13659113999999997}, {0.5884910233333334, -0.5302967366666668, -0.06276479999999997}, {0.6417158766666667, -0.12186443666666665, -0.45257653999999997}, {-0.5903144233333334, 0.28559418333333336, -0.44882131999999997}, {-0.6446662, -0.27407261, -0.37518718999999995}, {-0.1747689766666667, -0.5231760133333333, -0.5720300666666667}, {0.16999525333333332, -0.11746358666666668, -0.7673197833333334}, {-0.07609744999999997, 0.5360047600000001, -0.6075312033333334}, {-0.09755446, 0.22876301, -0.7748139766666666}, {-0.6464272866666667, 0.48840817666666664, -0.12653887}, {-0.45298488333333337, 0.6766130466666667, 0.0970687933333333}, {-0.6660608966666667, 0.42586898, 0.21776447666666665}}; +constexpr PJ_XYZ base_ico_centers[23] = {{0.6446662, 0.27407261, 0.37518718999999995}, {0.1747689766666667, 0.5231760133333333, 0.5720300666666667}, {-0.16999525333333332, 0.11746358666666666, 0.7673197833333334}, {0.08682595666666666, -0.38238388333333334, 0.69117259}, {0.5903144233333334, -0.28559418333333336, 0.44882131999999997}, {0.6764340433333333, 0.37526316, -0.18190732333333334}, {0.22617043, 0.68690576, -0.3293677933333333}, {-0.08387563333333335, 0.77832093, 0.13659113999999997}, {-0.6417158766666667, 0.12186443666666665, 0.45257653999999997}, {-0.6764340433333333, -0.37526316, 0.18190732333333334}, {-0.22617043, -0.68690576, 0.3293677933333333}, {0.08387563333333335, -0.77832093, -0.13659113999999997}, {0.5884910233333334, -0.5302967366666668, -0.06276479999999997}, {0.6417158766666667, -0.12186443666666665, -0.45257653999999997}, {-0.5903144233333334, 0.28559418333333336, -0.44882131999999997}, {-0.6446662, -0.27407261, -0.37518718999999995}, {-0.1747689766666667, -0.5231760133333333, -0.5720300666666667}, {0.16999525333333332, -0.11746358666666668, -0.7673197833333334}, {-0.07609744999999997, 0.5360047600000001, -0.6075312033333334}, {-0.09755446, 0.22876301, -0.7748139766666666}, {-0.6464272866666667, 0.48840817666666664, -0.12653887}, {-0.45298488333333337, 0.6766130466666667, 0.0970687933333333}, {-0.6660608966666667, 0.42586898, 0.21776447666666665}}; // Define the normals for each face and subface -constexpr PJ_XYZ ico_normals[23] = {{0.8112534716456183, 0.3448953244235397, 0.4721387719026189}, {0.21993078167242514, 0.6583691769191125, 0.7198475381327677}, {-0.21392348218574597, 0.1478171768398566, 0.9656017947376752}, {0.10926252593733311, -0.48119515565604315, 0.8697775132750616}, {0.7428567271237952, -0.3593941714860216, 0.5648005953155497}, {0.8512303999921011, 0.4722343774266651, -0.22891373682183738}, {0.28461480749719364, 0.8644080979012073, -0.4144792535654255}, {-0.1055498134715015, 0.9794457311974099, 0.17188745304792394}, {-0.80754076069938, 0.15335524153301364, 0.5695261975567215}, {-0.8512303999921011, -0.4722343774266651, 0.22891373682183735}, {-0.28461480749719364, -0.8644080979012073, 0.4144792535654255}, {0.10554981347150154, -0.97944573119741, -0.17188745304792397}, {0.7405621455042509, -0.6673299596621295, -0.07898375518726185}, {0.80754076069938, -0.15335524153301364, -0.5695261975567215}, {-0.7428567271237952, 0.3593941714860216, -0.5648005953155497}, {-0.8112534716456183, -0.3448953244235397, -0.4721387719026189}, {-0.21993078167242514, -0.6583691769191125, -0.7198475381327677}, {0.21392348218574597, -0.1478171768398566, -0.9656017947376752}, {-0.1092625236946045, 0.48119515875463253, -0.8697775118425345}, {-0.10926252412771359, 0.4811951525529661, -0.8697775152191327}, {-0.7405621389792739, 0.6673299643797594, 0.07898377650727696}, {-0.7405621607654073, 0.6673299431834946, 0.07898375132383098}, {-0.7405621367680706, 0.6673299714231342, 0.07898373773067752}}; +constexpr PJ_XYZ base_ico_normals[23] = {{0.8112534716456183, 0.3448953244235397, 0.4721387719026189}, {0.21993078167242514, 0.6583691769191125, 0.7198475381327677}, {-0.21392348218574597, 0.1478171768398566, 0.9656017947376752}, {0.10926252593733311, -0.48119515565604315, 0.8697775132750616}, {0.7428567271237952, -0.3593941714860216, 0.5648005953155497}, {0.8512303999921011, 0.4722343774266651, -0.22891373682183738}, {0.28461480749719364, 0.8644080979012073, -0.4144792535654255}, {-0.1055498134715015, 0.9794457311974099, 0.17188745304792394}, {-0.80754076069938, 0.15335524153301364, 0.5695261975567215}, {-0.8512303999921011, -0.4722343774266651, 0.22891373682183735}, {-0.28461480749719364, -0.8644080979012073, 0.4144792535654255}, {0.10554981347150154, -0.97944573119741, -0.17188745304792397}, {0.7405621455042509, -0.6673299596621295, -0.07898375518726185}, {0.80754076069938, -0.15335524153301364, -0.5695261975567215}, {-0.7428567271237952, 0.3593941714860216, -0.5648005953155497}, {-0.8112534716456183, -0.3448953244235397, -0.4721387719026189}, {-0.21993078167242514, -0.6583691769191125, -0.7198475381327677}, {0.21392348218574597, -0.1478171768398566, -0.9656017947376752}, {-0.1092625236946045, 0.48119515875463253, -0.8697775118425345}, {-0.10926252412771359, 0.4811951525529661, -0.8697775152191327}, {-0.7405621389792739, 0.6673299643797594, 0.07898377650727696}, {-0.7405621607654073, 0.6673299431834946, 0.07898375132383098}, {-0.7405621367680706, 0.6673299714231342, 0.07898373773067752}}; /* The points of the Airocean projection map are deduced from the unfolded net @@ -47,7 +48,7 @@ constexpr PJ_XYZ ico_normals[23] = {{0.8112534716456183, 0.3448953244235397, 0.4 The distances in the projected 2d space are expressed in meter. */ // Define the 23 unfolded surfaces used (from icosahedron + split faces) -constexpr pj_face airocean_faces[23] = {{{11602775.971724393, 20096597.491866, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {17404163.95758659, 23446030.407177, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {5801387.985862196, 23446030.407177, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {5801387.985862196, 16747164.576555002, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {5801387.985862196, 16747164.576555002, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {17404163.95758659, 23446030.407177, 1.0}, {17404163.95758659, 16747164.576555002, 1.0}}, {{17404163.95758659, 23446030.407177, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {17404163.95758659, 30144896.237799004, 1.0}}, {{11602775.971724393, 33494329.153110005, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {5801387.985862196, 30144896.237799004, 1.0}}, {{5801387.985862196, 30144896.237799004, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}, {{5801387.985862196, 16747164.576555002, 1.0}, {0.0, 20096597.491866, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}, {{5801387.985862196, 16747164.576555002, 1.0}, {5801387.985862196, 10048298.745933, 1.0}, {0.0, 13397731.661244001, 1.0}}, {{5801387.985862196, 16747164.576555002, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {5801387.985862196, 10048298.745933, 1.0}}, {{5801387.985862196, 10048298.745933, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}}, {{11602775.971724393, 6698865.830622001, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {17404163.95758659, 10048298.745933, 1.0}}, {{11602775.971724393, 0.0, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}, {17404163.95758659, 3349432.9153110003, 1.0}}, {{0.0, 33494329.153110005, 1.0}, {5801387.985862196, 30144896.237799004, 1.0}, {0.0, 26795463.322488002, 1.0}}, {{0.0, 6698865.830622001, 1.0}, {0.0, 13397731.661244001, 1.0}, {5801387.985862196, 10048298.745933, 1.0}}, {{5801387.985862196, 3349432.9153110003, 1.0}, {5801387.985862196, 10048298.745933, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}}, {{5801387.985862196, 3349432.9153110003, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}, {11602775.971724393, 0.0, 1.0}}, {{5801387.985862196, 30144896.237799004, 1.0}, {2900693.992931098, 31819612.695454504, 1.0}, {5801387.985862196, 36843762.068421006, 1.0}}, {{5801387.985862196, 3349432.9153110003, 1.0}, {11602775.971724393, 0.0, 1.0}, {5801387.985862196, 0.0, 1.0}}, {{0.0, 26795463.322488002, 1.0}, {5801387.985862196, 30144896.237799004, 1.0}, {3867591.9905747976, 26795463.322488002, 1.0}}, {{5801387.985862196, 30144896.237799004, 1.0}, {5801387.985862196, 23446030.407177, 1.0}, {3867591.9905747976, 26795463.322488002, 1.0}}, {{0.0, 20096597.491866, 1.0}, {1933795.9952873988, 23446030.407177, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}}; +constexpr pj_face base_airocean_faces[23] = {{{11602775.971724393, 20096597.491866, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {17404163.95758659, 23446030.407177, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {5801387.985862196, 23446030.407177, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {5801387.985862196, 16747164.576555002, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {5801387.985862196, 16747164.576555002, 1.0}}, {{11602775.971724393, 20096597.491866, 1.0}, {17404163.95758659, 23446030.407177, 1.0}, {17404163.95758659, 16747164.576555002, 1.0}}, {{17404163.95758659, 23446030.407177, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {17404163.95758659, 30144896.237799004, 1.0}}, {{11602775.971724393, 33494329.153110005, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {5801387.985862196, 30144896.237799004, 1.0}}, {{5801387.985862196, 30144896.237799004, 1.0}, {11602775.971724393, 26795463.322488002, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}, {{5801387.985862196, 16747164.576555002, 1.0}, {0.0, 20096597.491866, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}, {{5801387.985862196, 16747164.576555002, 1.0}, {5801387.985862196, 10048298.745933, 1.0}, {0.0, 13397731.661244001, 1.0}}, {{5801387.985862196, 16747164.576555002, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {5801387.985862196, 10048298.745933, 1.0}}, {{5801387.985862196, 10048298.745933, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}}, {{11602775.971724393, 6698865.830622001, 1.0}, {11602775.971724393, 13397731.661244001, 1.0}, {17404163.95758659, 10048298.745933, 1.0}}, {{11602775.971724393, 0.0, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}, {17404163.95758659, 3349432.9153110003, 1.0}}, {{0.0, 33494329.153110005, 1.0}, {5801387.985862196, 30144896.237799004, 1.0}, {0.0, 26795463.322488002, 1.0}}, {{0.0, 6698865.830622001, 1.0}, {0.0, 13397731.661244001, 1.0}, {5801387.985862196, 10048298.745933, 1.0}}, {{5801387.985862196, 3349432.9153110003, 1.0}, {5801387.985862196, 10048298.745933, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}}, {{5801387.985862196, 3349432.9153110003, 1.0}, {11602775.971724393, 6698865.830622001, 1.0}, {11602775.971724393, 0.0, 1.0}}, {{5801387.985862196, 30144896.237799004, 1.0}, {2900693.992931098, 31819612.695454504, 1.0}, {5801387.985862196, 36843762.068421006, 1.0}}, {{5801387.985862196, 3349432.9153110003, 1.0}, {11602775.971724393, 0.0, 1.0}, {5801387.985862196, 0.0, 1.0}}, {{0.0, 26795463.322488002, 1.0}, {5801387.985862196, 30144896.237799004, 1.0}, {3867591.9905747976, 26795463.322488002, 1.0}}, {{5801387.985862196, 30144896.237799004, 1.0}, {5801387.985862196, 23446030.407177, 1.0}, {3867591.9905747976, 26795463.322488002, 1.0}}, {{0.0, 20096597.491866, 1.0}, {1933795.9952873988, 23446030.407177, 1.0}, {5801387.985862196, 23446030.407177, 1.0}}}; /* The parameters here are extracted from the transition matrices @@ -57,9 +58,62 @@ constexpr pj_face airocean_faces[23] = {{{11602775.971724393, 20096597.491866, 1 the irrelevant ones has been discarded. */ // Icosahedron to Airocean (forward) -constexpr double ico_air_trans[23][2][4] = {{{3676785.549175448, -3835017.5266620647, -3516181.101897219, 13536571.968889877}, {597946.080039791, 4588467.120428165, -4379277.476119764, 23446030.430853583}}, {{6186178.005526091, -1393567.8850913076, -615475.9158875226, 9668979.99656166}, {597946.0790283178, 4588467.148836121, -4379277.446492919, 23446030.4022735}}, {{6193487.416382644, -412638.42193403625, 1435299.1565727487, 7735183.994711302}, {610606.2949588482, 6287486.763792622, -827230.771869741, 20096597.453907937}}, {{6320833.951539666, -6999.925417495968, -797903.6054442794, 9668979.964544488}, {390035.65785509185, 5584900.2162612835, 3040789.86561249, 16747164.583089648}}, {{1785817.7160921493, -3817376.067203325, -4777879.901545344, 15470367.97086971}, {3873198.4648612146, 4557911.12782605, -2193951.0189847522, 20096597.472239383}}, {{1653953.7567438218, -4829262.323420258, -3812125.829251187, 15470367.969285296}, {-2905701.3326818133, 2866384.6227320307, -4891868.725058803, 26795463.326497696}}, {{6107473.604777472, -1644266.325782215, 764719.3302896866, 9668979.973521523}, {-20484.65208776388, -2749071.5526177026, -5747332.168284684, 30144896.23069373}}, {{6325351.398413758, 599247.844237452, 469545.1345954169, 7735183.991104206}, {356890.77665911405, 1136808.9376555325, -6258588.903331836, 26795463.365920186}}, {{3707748.6155441254, 320266.3046413801, 5171041.531732354, 3867591.9864321505}, {610606.2818745336, 6287486.766371998, -827230.7619227654, 20096597.44051682}}, {{3343388.0482846545, -4896993.062013145, 2330419.6732539237, 3867591.9905542377}, {20484.69631605078, 2749071.5422549895, 5747332.173083752, 13397731.669298988}}, {{6107473.604777474, -1644266.3257822143, 764719.330289686, 7735183.984065069}, {20484.65208776346, 2749071.552617706, 5747332.168284684, 13397731.654138729}}, {{6325351.398413757, 599247.8442374519, 469545.1345954159, 9668979.966482382}, {-356890.77665911167, -1136808.9376555379, 6258588.903331836, 10048298.789365184}}, {{4266333.348411551, 4606685.482609389, 1080041.5914374113, 13536571.961679665}, {-356890.81480763154, -1136808.9649443403, 6258588.896199714, 10048298.78278621}}, {{3707748.6155441264, 320266.30464138015, 5171041.531732352, 13536571.97115444}, {-610606.2818745337, -6287486.766372, 827230.7619227694, 3349432.8639618154}}, {{2461379.4064226267, 5855954.858490806, 488922.63367311924, 1933796.0165698116}, {3483162.7410947136, -1026989.0860837825, -5234740.880461738, 30144896.24019003}}, {{1320556.279179943, -5891237.854051452, 2034474.9935921053, 1933796.0148528814}, {-3483162.72987335, 1026989.0418338334, 5234740.896609632, 10048298.759397767}}, {{6186178.005526091, -1393567.885091309, -615475.9158875229, 7735183.961024929}, {-597946.0790283154, -4588467.148836119, 4379277.446492919, 6698865.825718503}}, {{6193487.416382645, -412638.4219340361, 1435299.156572748, 9668979.962875288}, {-610606.2949588535, -6287486.763792623, 827230.7718697439, 3349432.877352944}}, {{3498197.81693495, 4833165.559061878, 2234449.5231911456, 3867591.983769496}, {5278984.96116607, -2798512.200701845, -2211399.7153384583, 33494329.158408284}}, {{6320833.983680945, -6999.984355479206, -797903.6271294819, 7735183.9823354}, {-390035.68446349393, -5584900.177255948, -3040789.814780467, 0.044359486997177525}}, {{4266333.41772867, 4606685.445409489, 1080041.6365273518, 3867592.0700864717}, {356890.72771489987, 1136809.053212709, -6258588.866576485, 26795463.265809294}}, {{4266333.204506115, 4606685.540218764, 1080041.5936954806, 3867591.897018196}, {356890.8007120557, 1136808.9497242568, -6258588.899768077, 26795463.365730304}}, {{1824090.1118675405, 1318837.3514699321, 5960117.7705610385, 1933795.9110601672}, {3873198.583330483, 4557911.083457602, -2193951.0468033054, 23446030.547617782}}}; +constexpr double base_ico_air_trans[23][4][4] = {{{3676785.549175448, -3835017.5266620647, -3516181.101897219, 13536571.968889877}, {597946.080039791, 4588467.120428165, -4379277.476119764, 23446030.430853583}, {0.8112534716456183, 0.3448953244235397, 0.4721387719026189, -0.7946544736643394}, {0.0, 0.0, 0.0, 0.9999999999999999}}, {{6186178.005526091, -1393567.8850913076, -615475.9158875226, 9668979.99656166}, {597946.0790283178, 4588467.148836121, -4379277.446492919, 23446030.4022735}, {0.2199307816724251, 0.6583691769191125, 0.7198475381327677, -0.794654474160402}, {2.7755575615628914e-17, 0.0, 0.0, 1.0}}, {{6193487.416382644, -412638.42193403625, 1435299.1565727487, 7735183.994711302}, {610606.2949588482, 6287486.763792622, -827230.771869741, 20096597.453907937}, {-0.213923482185746, 0.14781717683985665, 0.9656017947376753, -0.7946544722350559}, {-1.3877787807814457e-16, 2.7755575615628914e-17, 0.0, 1.0}}, {{6320833.951539666, -6999.925417495968, -797903.6054442794, 9668979.964544488}, {390035.65785509185, 5584900.2162612835, 3040789.86561249, 16747164.583089648}, {0.1092625259373331, -0.48119515565604315, 0.8697775132750618, -0.794654472177355}, {1.1102230246251565e-16, 5.551115123125783e-17, 0.0, 1.0}}, {{1785817.7160921493, -3817376.067203325, -4777879.901545344, 15470367.97086971}, {3873198.4648612146, 4557911.12782605, -2193951.0189847522, 20096597.472239383}, {0.7428567271237952, -0.3593941714860217, 0.5648005953155497, -0.7946544741179917}, {0.0, 0.0, 0.0, 1.0000000000000002}}, {{1653953.7567438218, -4829262.323420258, -3812125.829251187, 15470367.969285296}, {-2905701.3326818133, 2866384.6227320307, -4891868.725058803, 26795463.326497696}, {0.8512303999921013, 0.4722343774266651, -0.22891373682183747, -0.7946544711481622}, {0.0, -5.551115123125783e-17, 1.1102230246251565e-16, 1.0}}, {{6107473.604777472, -1644266.325782215, 764719.3302896866, 9668979.973521523}, {-20484.65208776388, -2749071.5526177026, -5747332.168284684, 30144896.23069373}, {0.2846148074971938, 0.8644080979012073, -0.41447925356542553, -0.7946544719642821}, {0.0, -1.1102230246251565e-16, 0.0, 1.0}}, {{6325351.398413758, 599247.844237452, 469545.1345954169, 7735183.991104206}, {356890.77665911405, 1136808.9376555325, -6258588.903331836, 26795463.365920186}, {-0.10554981347150151, 0.97944573119741, 0.17188745304792394, -0.794654473006748}, {-1.3877787807814457e-17, 0.0, 8.326672684688674e-17, 1.0}}, {{3707748.6155441254, 320266.3046413801, 5171041.531732354, 3867591.9864321505}, {610606.2818745336, 6287486.766371998, -827230.7619227654, 20096597.44051682}, {-0.8075407606993799, 0.15335524153301364, 0.5695261975567214, -0.7946544732451482}, {0.0, -8.326672684688674e-17, 0.0, 1.0}}, {{3343388.0482846545, -4896993.062013145, 2330419.6732539237, 3867591.9905542377}, {20484.69631605078, 2749071.5422549895, 5747332.173083752, 13397731.669298988}, {-0.8512303999921013, -0.4722343774266651, 0.22891373682183733, -0.7946544711481622}, {1.1102230246251565e-16, 0.0, -2.7755575615628914e-17, 1.0}}, {{6107473.604777474, -1644266.3257822143, 764719.330289686, 7735183.984065069}, {20484.65208776346, 2749071.552617706, 5747332.168284684, 13397731.654138729}, {-0.28461480749719376, -0.8644080979012073, 0.41447925356542553, -0.7946544719642822}, {-5.551115123125783e-17, 0.0, -5.551115123125783e-17, 1.0}}, {{6325351.398413757, 599247.8442374519, 469545.1345954159, 9668979.966482382}, {-356890.77665911167, -1136808.9376555379, 6258588.903331836, 10048298.789365184}, {0.10554981347150151, -0.97944573119741, -0.17188745304792394, -0.794654473006748}, {1.249000902703301e-16, 0.0, -8.326672684688674e-17, 1.0}}, {{4266333.348411551, 4606685.482609389, 1080041.5914374113, 13536571.961679665}, {-356890.81480763154, -1136808.9649443403, 6258588.896199714, 10048298.78278621}, {0.7405621455042507, -0.6673299596621294, -0.07898375518726183, -0.7946544743360283}, {1.1102230246251565e-16, 0.0, 5.551115123125783e-17, 0.9999999999999999}}, {{3707748.6155441264, 320266.30464138015, 5171041.531732352, 13536571.97115444}, {-610606.2818745337, -6287486.766372, 827230.7619227694, 3349432.8639618154}, {0.8075407606993799, -0.15335524153301364, -0.5695261975567214, -0.7946544732451483}, {-1.1102230246251565e-16, -2.7755575615628914e-17, 0.0, 1.0}}, {{2461379.4064226267, 5855954.858490806, 488922.63367311924, 1933796.0165698116}, {3483162.7410947136, -1026989.0860837825, -5234740.880461738, 30144896.24019003}, {-0.7428567271237954, 0.35939417148602165, -0.5648005953155498, -0.7946544741179918}, {-1.1102230246251565e-16, 5.551115123125783e-17, 0.0, 1.0}}, {{1320556.279179943, -5891237.854051452, 2034474.9935921053, 1933796.0148528814}, {-3483162.72987335, 1026989.0418338334, 5234740.896609632, 10048298.759397767}, {-0.8112534716456183, -0.34489532442353976, -0.4721387719026189, -0.7946544736643393}, {0.0, 1.1102230246251565e-16, 0.0, 1.0}}, {{6186178.005526091, -1393567.885091309, -615475.9158875229, 7735183.961024929}, {-597946.0790283154, -4588467.148836119, 4379277.446492919, 6698865.825718503}, {-0.21993078167242508, -0.6583691769191125, -0.7198475381327677, -0.794654474160402}, {0.0, -1.1102230246251565e-16, 0.0, 1.0}}, {{6193487.416382645, -412638.4219340361, 1435299.156572748, 9668979.962875288}, {-610606.2949588535, -6287486.763792623, 827230.7718697439, 3349432.877352944}, {0.21392348218574594, -0.14781717683985665, -0.965601794737675, -0.7946544722350558}, {-1.3877787807814457e-16, -2.7755575615628914e-17, 0.0, 1.0}}, {{3498197.81693495, 4833165.559061878, 2234449.5231911456, 3867591.983769496}, {5278984.96116607, -2798512.200701845, -2211399.7153384583, 33494329.158408284}, {-0.10926252369460446, 0.4811951587546325, -0.8697775118425342, -0.7946544734171301}, {8.326672684688674e-17, 0.0, 0.0, 0.9999999999999998}}, {{6320833.983680945, -6999.984355479206, -797903.6271294819, 7735183.9823354}, {-390035.68446349393, -5584900.177255948, -3040789.814780467, 0.044359486997177525}, {-0.10926252412771358, 0.48119515255296597, -0.8697775152191325, -0.79465447341713}, {-4.163336342344337e-17, -1.1102230246251565e-16, 0.0, 0.9999999999999999}}, {{4266333.41772867, 4606685.445409489, 1080041.6365273518, 3867592.0700864717}, {356890.72771489987, 1136809.053212709, -6258588.866576485, 26795463.265809294}, {-0.7405621389792741, 0.6673299643797597, 0.07898377650727716, -0.7946544674186218}, {1.1102230246251565e-16, 0.0, -1.3877787807814457e-17, 1.0}}, {{4266333.204506115, 4606685.540218764, 1080041.5936954806, 3867591.897018196}, {356890.8007120557, 1136808.9497242568, -6258588.899768077, 26795463.365730304}, {-0.7405621607654075, 0.6673299431834948, 0.07898375132383098, -0.7946544674186217}, {1.1102230246251565e-16, -1.1102230246251565e-16, 2.7755575615628914e-17, 0.9999999999999999}}, {{1824090.1118675405, 1318837.3514699321, 5960117.7705610385, 1933795.9110601672}, {3873198.583330483, 4557911.083457602, -2193951.0468033054, 23446030.547617782}, {-0.7405621367680707, 0.667329971423134, 0.07898373773067754, -0.7946544674186213}, {0.0, 0.0, 8.326672684688674e-17, 1.0}}}; // Airocean to Icosahedron (inverse) -constexpr double air_ico_trans[23][3][3] = {{{9.058433279771384e-08, 1.4731493732699052e-08, -0.9269301899999991}, {-9.44826679987233e-08, 1.1304527499839262e-07, -1.0974189099999994}, {-8.662754779110161e-08, -1.0789150406568015e-07, 4.077454709999999}}, {{1.5240780519329358e-07, 1.473149373269901e-08, -1.6442540899999978}, {-3.4333093302050216e-08, 1.1304527499839258e-07, -1.7953209499999985}, {-1.51633738709386e-08, -1.0789150406568015e-07, 3.248271909999998}}, {{1.525878853745444e-07, 1.504340175606161e-08, -1.6526118100000007}, {-1.0166102516109274e-08, 1.5490373090569122e-07, -2.9169376700000003}, {3.536121881520939e-08, -2.0380342501548998e-08, 0.9033697899999995}}, {{1.557252983599121e-07, 9.609243061078464e-09, -1.5798064100000002}, {-1.7245441994882394e-10, 1.375942246501773e-07, -2.6850295500000003}, {-1.96578129712955e-08, 7.491541593592458e-08, -0.37337721000000035}}, {{4.399688326690425e-08, 9.54233233151121e-08, -2.0080176699999996}, {-9.404803666461074e-08, 1.122924714451482e-07, -1.0873330499999996}, {-1.1771180391040664e-07, -5.405199315156007e-08, 3.3561273899999997}}, {{4.074817450170371e-08, -7.158726449003567e-08, 1.9642587099999982}, {-1.1897770528054373e-07, 7.061862589298568e-08, 0.3236332400000001}, {-9.391868744648748e-08, -1.2052012839388902e-07, 4.500442009999996}}, {{1.5046877525297362e-07, -5.046779687011883e-10, -1.2134956799999999}, {-4.0509505754953036e-08, -6.772840231043597e-08, 3.120257019999999}, {1.8840259480379495e-08, -1.4159603341569342e-07, 3.7568638499999985}}, {{1.55836594139745e-07, 8.792657069014762e-09, -1.52490368}, {1.4763566099823772e-08, 2.800736643244269e-08, -0.08634832999999958}, {1.1568102351290336e-08, -1.5419177904390005e-07, 4.178749899999998}}, {{9.134716490113195e-08, 1.504340175606163e-08, -1.2973306300000003}, {7.890345398644546e-09, 1.5490373090569127e-07, -3.021690130000001}, {1.2739806091251417e-07, -2.0380342501549028e-08, 0.3694283599999999}}, {{8.237047688665845e-08, 5.04677968701152e-10, -1.0017709799999996}, {-1.2064637664394705e-07, 6.772840231043599e-08, -0.8160591599999997}, {5.741414913322641e-08, 1.4159603341569342e-07, -1.937212839999999}}, {{1.504687752529736e-07, 5.046779687011514e-10, -1.3968356299999996}, {-4.0509505754953036e-08, 6.772840231043597e-08, -1.2809642399999992}, {1.8840259480379524e-08, 1.415960334156934e-07, -1.713430739999999}}, {{1.55836594139745e-07, -8.792657069014724e-09, -1.3345540299999996}, {1.4763566099823759e-08, -2.8007366432442684e-08, -0.6396431699999997}, {1.1568102351290311e-08, 1.5419177904390013e-07, -1.7978079499999997}}, {{1.0510891988020954e-07, -8.792657069014762e-09, -0.7459721899999996}, {1.1349411668458604e-07, -2.8007366432442694e-08, -1.7851916299999993}, {2.6608799545245027e-08, 1.541917790439001e-07, -1.9723217899999996}}, {{9.134716490113195e-08, -1.5043401756061595e-08, -0.5444247299999998}, {7.890345398644617e-09, -1.5490373090569122e-07, 0.29016699000000007}, {1.2739806091251412e-07, 2.038034250154901e-08, -2.2453721499999992}}, {{6.064058047097081e-08, 8.58140802540336e-08, -3.294437479999999}, {1.4427215125754238e-07, -2.530175320502907e-08, 0.7693199999999997}, {1.2045502760769865e-08, -1.2896740908748457e-07, 3.4155942999999986}}, {{3.2534318590648264e-08, -8.581408025403363e-08, 0.15470457999999998}, {-1.4514141392576755e-07, 2.530175320502908e-08, -0.2476383}, {5.01230094778404e-08, 1.289674090874846e-07, -1.7680179200000001}}, {{1.524078051932937e-07, -1.4731493732699067e-08, -1.25498709}, {-3.433309330205022e-08, -1.1304527499839266e-07, 0.49967191}, {-1.5163373870938614e-08, 1.0789150406568026e-07, -1.17748929}}, {{1.5258788537454444e-07, -1.50434017560616e-08, -1.25498709}, {-1.016610251610931e-08, -1.5490373090569122e-07, 0.49967191}, {3.536121881520941e-08, 2.0380342501549018e-08, -1.17748929}}, {{8.618449605826386e-08, 1.3005744286105568e-07, -4.776339219999996}, {1.1907386502737676e-07, -6.894646223375916e-08, 2.2311702599999985}, {5.5049746849940485e-08, -5.4481873383947436e-08, 0.9207512499999986}}, {{1.5572529749804938e-07, -9.609244553868475e-09, -1.29138978}, {-1.7245528181154292e-10, -1.3759422614296728e-07, 0.38371785999999997}, {-1.9657812971295542e-08, -7.491541593592457e-08, -0.53911579}}, {{1.0510892074207234e-07, 8.792655576224747e-09, -1.2306127199999985}, {1.1349411496086066e-07, 2.8007369418022736e-08, -0.6591226399999993}, {2.6608799545244997e-08, -1.5419177904390008e-07, 4.091492979999998}}, {{1.0510891815648413e-07, 8.79265706901476e-09, -1.2306127500000001}, {1.1349412013203696e-07, 2.8007366432442717e-08, -0.6591225800000001}, {2.6608799545245066e-08, -1.5419177904390005e-07, 4.091492979999997}}, {{4.4939794689710465e-08, 9.54233248079021e-08, -2.9126935899999995}, {3.249196924242356e-08, 1.1229246845956814e-07, -2.1653487399999993}, {1.4683839747935709e-07, -5.405199315156002e-08, 1.0461139699999995}}}; +constexpr double base_air_ico_trans[23][4][4] = {{{9.058433279771384e-08, 1.4731493732699052e-08, 0.8112534716456185, -0.9269301899999991}, {-9.44826679987233e-08, 1.1304527499839262e-07, 0.34489532442353965, -1.0974189099999994}, {-8.662754779110161e-08, -1.0789150406568015e-07, 0.47213877190261877, 4.077454709999999}, {0.0, 2.646977960169691e-23, 0.0, 1.0}}, {{1.5240780519329358e-07, 1.473149373269901e-08, 0.219930781672425, -1.6442540899999978}, {-3.4333093302050216e-08, 1.1304527499839258e-07, 0.6583691769191122, -1.7953209499999985}, {-1.51633738709386e-08, -1.0789150406568015e-07, 0.719847538132768, 3.248271909999998}, {-1.3234889800848443e-23, 2.6469779601696886e-23, 0.0, 1.0}}, {{1.525878853745444e-07, 1.504340175606161e-08, -0.21392348218574625, -1.6526118100000007}, {-1.0166102516109274e-08, 1.5490373090569122e-07, 0.14781717683985585, -2.9169376700000003}, {3.536121881520939e-08, -2.0380342501548998e-08, 0.9656017947376755, 0.9033697899999995}, {-1.3234889800848443e-23, 2.6469779601696886e-23, 2.220446049250313e-16, 1.0}}, {{1.557252983599121e-07, 9.609243061078464e-09, 0.10926252593733309, -1.5798064100000002}, {-1.7245441994882394e-10, 1.375942246501773e-07, -0.48119515565604315, -2.6850295500000003}, {-1.96578129712955e-08, 7.491541593592458e-08, 0.8697775132750615, -0.37337721000000035}, {2.6469779601696886e-23, 1.3234889800848443e-23, 0.0, 1.0}}, {{4.399688326690425e-08, 9.54233233151121e-08, 0.7428567271237949, -2.0080176699999996}, {-9.404803666461074e-08, 1.122924714451482e-07, -0.35939417148602176, -1.0873330499999996}, {-1.1771180391040664e-07, -5.405199315156007e-08, 0.5648005953155502, 3.3561273899999997}, {0.0, 0.0, 0.0, 1.0}}, {{4.074817450170371e-08, -7.158726449003567e-08, 0.8512303999921009, 1.9642587099999982}, {-1.1897770528054373e-07, 7.061862589298568e-08, 0.4722343774266655, 0.3236332400000001}, {-9.391868744648748e-08, -1.2052012839388902e-07, -0.22891373682183766, 4.500442009999996}, {1.3234889800848443e-23, 2.6469779601696886e-23, 0.0, 0.9999999999999991}}, {{1.5046877525297362e-07, -5.046779687011883e-10, 0.2846148074971936, -1.2134956799999999}, {-4.0509505754953036e-08, -6.772840231043597e-08, 0.8644080979012075, 3.120257019999999}, {1.8840259480379495e-08, -1.4159603341569342e-07, -0.4144792535654251, 3.7568638499999985}, {0.0, -1.1754943508222875e-38, 0.0, 1.0}}, {{1.55836594139745e-07, 8.792657069014762e-09, -0.1055498134715016, -1.52490368}, {1.4763566099823772e-08, 2.800736643244269e-08, 0.97944573119741, -0.08634832999999958}, {1.1568102351290336e-08, -1.5419177904390005e-07, 0.17188745304792347, 4.178749899999998}, {1.3234889800848443e-23, 0.0, 0.0, 1.0}}, {{9.134716490113195e-08, 1.504340175606163e-08, -0.80754076069938, -1.2973306300000003}, {7.890345398644546e-09, 1.5490373090569127e-07, 0.15335524153301333, -3.021690130000001}, {1.2739806091251417e-07, -2.0380342501549028e-08, 0.5695261975567216, 0.3694283599999999}, {1.3234889800848443e-23, -2.6469779601696886e-23, 0.0, 1.0}}, {{8.237047688665845e-08, 5.04677968701152e-10, -0.8512303999921011, -1.0017709799999996}, {-1.2064637664394705e-07, 6.772840231043599e-08, -0.472234377426665, -0.8160591599999997}, {5.741414913322641e-08, 1.4159603341569342e-07, 0.2289137368218376, -1.937212839999999}, {-2.6469779601696886e-23, 1.323488980084844e-23, 0.0, 1.0}}, {{1.504687752529736e-07, 5.046779687011514e-10, -0.2846148074971936, -1.3968356299999996}, {-4.0509505754953036e-08, 6.772840231043597e-08, -0.8644080979012072, -1.2809642399999992}, {1.8840259480379524e-08, 1.415960334156934e-07, 0.41447925356542575, -1.713430739999999}, {1.3234889800848443e-23, 0.0, 0.0, 0.9999999999999998}}, {{1.55836594139745e-07, -8.792657069014724e-09, 0.10554981347150141, -1.3345540299999996}, {1.4763566099823759e-08, -2.8007366432442684e-08, -0.97944573119741, -0.6396431699999997}, {1.1568102351290311e-08, 1.5419177904390013e-07, -0.17188745304792416, -1.7978079499999997}, {0.0, -2.6469779601696886e-23, 0.0, 0.9999999999999998}}, {{1.0510891988020954e-07, -8.792657069014762e-09, 0.740562145504251, -0.7459721899999996}, {1.1349411668458604e-07, -2.8007366432442694e-08, -0.6673299596621296, -1.7851916299999993}, {2.6608799545245027e-08, 1.541917790439001e-07, -0.07898375518726153, -1.9723217899999996}, {0.0, 0.0, 0.0, 1.0}}, {{9.134716490113195e-08, -1.5043401756061595e-08, 0.80754076069938, -0.5444247299999998}, {7.890345398644617e-09, -1.5490373090569122e-07, -0.15335524153301372, 0.29016699000000007}, {1.2739806091251412e-07, 2.038034250154901e-08, -0.5695261975567216, -2.2453721499999992}, {0.0, 0.0, 0.0, 1.0}}, {{6.064058047097081e-08, 8.58140802540336e-08, -0.7428567271237954, -3.294437479999999}, {1.4427215125754238e-07, -2.530175320502907e-08, 0.3593941714860216, 0.7693199999999997}, {1.2045502760769865e-08, -1.2896740908748457e-07, -0.5648005953155495, 3.4155942999999986}, {1.3234889800848443e-23, 0.0, 0.0, 1.0}}, {{3.2534318590648264e-08, -8.581408025403363e-08, -0.8112534716456185, 0.15470457999999998}, {-1.4514141392576755e-07, 2.530175320502908e-08, -0.34489532442353965, -0.2476383}, {5.01230094778404e-08, 1.289674090874846e-07, -0.47213877190261855, -1.7680179200000001}, {0.0, 0.0, 0.0, 1.0}}, {{1.524078051932937e-07, -1.4731493732699067e-08, -0.21993078167242536, -1.25498709}, {-3.433309330205022e-08, -1.1304527499839266e-07, -0.6583691769191123, 0.49967191}, {-1.5163373870938614e-08, 1.0789150406568026e-07, -0.7198475381327679, -1.17748929}, {0.0, 0.0, 2.220446049250313e-16, 1.0}}, {{1.5258788537454444e-07, -1.50434017560616e-08, 0.2139234821857457, -1.25498709}, {-1.016610251610931e-08, -1.5490373090569122e-07, -0.14781717683985668, 0.49967191}, {3.536121881520941e-08, 2.0380342501549018e-08, -0.9656017947376753, -1.17748929}, {0.0, 0.0, 0.0, 1.0}}, {{8.618449605826386e-08, 1.3005744286105568e-07, -0.10926252369460417, -4.776339219999996}, {1.1907386502737676e-07, -6.894646223375916e-08, 0.48119515875463226, 2.2311702599999985}, {5.5049746849940485e-08, -5.4481873383947436e-08, -0.8697775118425347, 0.9207512499999986}, {1.3234889800848443e-23, 2.6469779601696886e-23, 0.0, 1.0}}, {{1.5572529749804938e-07, -9.609244553868475e-09, -0.10926252412771378, -1.29138978}, {-1.7245528181154292e-10, -1.3759422614296728e-07, 0.48119515255296613, 0.38371785999999997}, {-1.9657812971295542e-08, -7.491541593592457e-08, -0.8697775152191327, -0.53911579}, {0.0, 0.0, 1.1102230246251565e-16, 1.0}}, {{1.0510892074207234e-07, 8.792655576224747e-09, -0.7405621389792737, -1.2306127199999985}, {1.1349411496086066e-07, 2.8007369418022736e-08, 0.6673299643797594, -0.6591226399999993}, {2.6608799545244997e-08, -1.5419177904390008e-07, 0.07898377650727657, 4.091492979999998}, {0.0, 0.0, 0.0, 1.0}}, {{1.0510891815648413e-07, 8.79265706901476e-09, -0.7405621607654073, -1.2306127500000001}, {1.1349412013203696e-07, 2.8007366432442717e-08, 0.6673299431834946, -0.6591225800000001}, {2.6608799545245066e-08, -1.5419177904390005e-07, 0.07898375132383044, 4.091492979999997}, {0.0, 1.323488980084842e-23, 0.0, 1.0}}, {{4.4939794689710465e-08, 9.54233248079021e-08, -0.7405621367680707, -2.9126935899999995}, {3.249196924242356e-08, 1.1229246845956814e-07, 0.6673299714231342, -2.1653487399999993}, {1.4683839747935709e-07, -5.405199315156002e-08, 0.07898373773067752, 1.0461139699999995}, {0.0, -2.6469779601696886e-23, 0.0, 0.9999999999999996}}}; + + +// By default the resulting orientation of the projection is vertical +// the following transforms are used to alter the projection data +// so that the resulting orientation is horizontal instead +constexpr double orient_horizontal_trans[4][4] = {{0.0, -1.0, 0.0, 36843762.068421006}, {1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}; +constexpr double orient_horizontal_inv_trans[4][4] = {{0.0, 1.0, 0.0, 0.0}, {-1.0, -0.0, -0.0, 36843762.068421006}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}; + +namespace { // anonymous namespace + + struct pj_airocean_data { + pj_face ico_faces[23] = {}; + PJ_XYZ ico_centers[23] = {}; + PJ_XYZ ico_normals[23] = {}; + pj_face airocean_faces[23] = {}; + double ico_air_trans[23][4][4] = {}; + double air_ico_trans[23][4][4] = {}; + + void initialize() { + memcpy((char *) this->ico_faces, (char *) base_ico_faces, sizeof(pj_face[23])); + memcpy((char *) this->airocean_faces, (char *) base_airocean_faces, sizeof(pj_face[23])); + memcpy(this->ico_centers, base_ico_centers, sizeof(PJ_XYZ[23])); + memcpy(this->ico_normals, base_ico_normals, sizeof(PJ_XYZ[23])); + memcpy(this->ico_air_trans, base_ico_air_trans, sizeof(double[23][4][4])); + memcpy(this->air_ico_trans, base_air_ico_trans, sizeof(double[23][4][4])); + } + + void mult4x4(const double m1[4][4], const double m2[4][4], double res[4][4]) { + for (unsigned char i = 0; i < 4; ++i) + for (unsigned char j = 0; j < 4; ++j) + res[i][j] = (m1[i][0] * m2[0][j]) + + (m1[i][1] * m2[1][j]) + + (m1[i][2] * m2[2][j]) + + (m1[i][3] * m2[3][j]); + } + + void transform(const double m[4][4], const double inv_m[4][4]) { + for (unsigned char i=0; i < 23; i++) { + mult4x4(m, base_ico_air_trans[i], this->ico_air_trans[i]); + } + for (unsigned char i=0; i < 23; i++) { + mult4x4(base_air_ico_trans[i], inv_m, this->air_ico_trans[i]); + } + } + + + }; + + + +} // anonymous namespace + + inline double det(const PJ_XYZ *u, const PJ_XYZ *v, const PJ_XYZ *w) { @@ -79,9 +133,9 @@ inline bool is_point_in_face(const PJ_XYZ *p, const pj_face * face) { } -inline unsigned char get_ico_face_index(const PJ_XYZ *p) { +inline unsigned char get_ico_face_index(const pj_airocean_data * pj_data, const PJ_XYZ *p) { for (unsigned char i=0; i < 23; i++) { - if (is_point_in_face(p, &ico_faces[i])) { + if (is_point_in_face(p, &pj_data->ico_faces[i])) { return i; } } @@ -89,10 +143,10 @@ inline unsigned char get_ico_face_index(const PJ_XYZ *p) { return 23; } -inline unsigned char get_dym_face_index(const PJ_XY *p) { +inline unsigned char get_dym_face_index(const pj_airocean_data * pj_data, const PJ_XY *p) { const PJ_XYZ pp{p->x, p->y, 1.0}; for (unsigned char i=0; i < 23; i++) { - if (is_point_in_face(&pp, &airocean_faces[i])) { + if (is_point_in_face(&pp, &pj_data->airocean_faces[i])) { return i; } } @@ -100,36 +154,36 @@ inline unsigned char get_dym_face_index(const PJ_XY *p) { return 23; } -inline PJ_XY ico_to_dym(const PJ_XYZ * p, unsigned char face_id) { +inline PJ_XY ico_to_dym(const pj_airocean_data * pj_data, const PJ_XYZ * p, unsigned char face_id) { return PJ_XY{ - ico_air_trans[face_id][0][0] * p->x + - ico_air_trans[face_id][0][1] * p->y + - ico_air_trans[face_id][0][2] * p->z + - ico_air_trans[face_id][0][3], - ico_air_trans[face_id][1][0] * p->x + - ico_air_trans[face_id][1][1] * p->y + - ico_air_trans[face_id][1][2] * p->z + - ico_air_trans[face_id][1][3], + pj_data->ico_air_trans[face_id][0][0] * p->x + // * -1 + pj_data->ico_air_trans[face_id][0][1] * p->y + // + pj_data->ico_air_trans[face_id][0][2] * p->z + // + pj_data->ico_air_trans[face_id][0][3], // +1000 + pj_data->ico_air_trans[face_id][1][0] * p->x + + pj_data->ico_air_trans[face_id][1][1] * p->y + + pj_data->ico_air_trans[face_id][1][2] * p->z + + pj_data->ico_air_trans[face_id][1][3], }; } -inline PJ_XYZ dym_to_ico(const PJ_XY * p, unsigned char face_id) { +inline PJ_XYZ dym_to_ico(const pj_airocean_data * pj_data, const PJ_XY * p, unsigned char face_id) { return PJ_XYZ{ - air_ico_trans[face_id][0][0] * p->x + - air_ico_trans[face_id][0][1] * p->y + - air_ico_trans[face_id][0][2], - air_ico_trans[face_id][1][0] * p->x + - air_ico_trans[face_id][1][1] * p->y + - air_ico_trans[face_id][1][2], - air_ico_trans[face_id][2][0] * p->x + - air_ico_trans[face_id][2][1] * p->y + - air_ico_trans[face_id][2][2], + pj_data->air_ico_trans[face_id][0][0] * p->x + // * -1 + pj_data->air_ico_trans[face_id][0][1] * p->y + // + pj_data->air_ico_trans[face_id][0][3], // + [face_id][0][0] * 1000 + pj_data->air_ico_trans[face_id][1][0] * p->x + + pj_data->air_ico_trans[face_id][1][1] * p->y + + pj_data->air_ico_trans[face_id][1][3], + pj_data->air_ico_trans[face_id][2][0] * p->x + + pj_data->air_ico_trans[face_id][2][1] * p->y + + pj_data->air_ico_trans[face_id][2][3], }; } -inline PJ_XYZ cartesian_to_ico(const PJ_XYZ *p, unsigned char face_id) { - const PJ_XYZ * center = &ico_centers[face_id]; - const PJ_XYZ * normal = &ico_normals[face_id]; +inline PJ_XYZ cartesian_to_ico(const pj_airocean_data * pj_data, const PJ_XYZ *p, unsigned char face_id) { + const PJ_XYZ * center = &pj_data->ico_centers[face_id]; + const PJ_XYZ * normal = &pj_data->ico_normals[face_id]; // cppcheck-suppress unreadVariable double a = 1.0 - ( @@ -156,6 +210,9 @@ inline PJ_XYZ cartesian_to_ico(const PJ_XYZ *p, unsigned char face_id) { // // ============================================ static PJ_XY airocean_forward(PJ_LP lp, PJ *P) { + const struct pj_airocean_data *Q = + static_cast(P->opaque); + double lat; /* Convert the geodetic latitude to a geocentric latitude. @@ -184,11 +241,11 @@ static PJ_XY airocean_forward(PJ_LP lp, PJ *P) { PJ_XYZ cartesianPoint{x, y, z}; - unsigned char face_id = get_ico_face_index(&cartesianPoint); + unsigned char face_id = get_ico_face_index(Q, &cartesianPoint); - PJ_XYZ icoPoint = cartesian_to_ico(&cartesianPoint, face_id); + PJ_XYZ icoPoint = cartesian_to_ico(Q, &cartesianPoint, face_id); - PJ_XY airoceanPoint = ico_to_dym(&icoPoint, face_id); + PJ_XY airoceanPoint = ico_to_dym(Q, &icoPoint, face_id); return airoceanPoint; @@ -196,9 +253,12 @@ static PJ_XY airocean_forward(PJ_LP lp, PJ *P) { static PJ_LP airocean_inverse(PJ_XY xy, PJ *P) { + const struct pj_airocean_data *Q = + static_cast(P->opaque); + PJ_LP lp = {0.0, 0.0}; - unsigned char face_id = get_dym_face_index(&xy); + unsigned char face_id = get_dym_face_index(Q, &xy); if (face_id == 23) { // Point lies outside icosahedron net faces @@ -208,8 +268,7 @@ static PJ_LP airocean_inverse(PJ_XY xy, PJ *P) { return lp; } - - PJ_XYZ sphereCoords = dym_to_ico(&xy, face_id); + PJ_XYZ sphereCoords = dym_to_ico(Q, &xy, face_id); double norm = sqrt((sphereCoords.x * sphereCoords.x) + (sphereCoords.y * sphereCoords.y) + (sphereCoords.z * sphereCoords.z)); double q = sphereCoords.x / norm; @@ -240,6 +299,30 @@ static PJ_LP airocean_inverse(PJ_XY xy, PJ *P) { } PJ *PJ_PROJECTION(airocean) { + char *opt; + struct pj_airocean_data *Q = static_cast( + calloc(1, sizeof(struct pj_airocean_data))); + if (nullptr == Q) + return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); + Q->initialize(); + P->opaque = Q; + opt = pj_param(P->ctx, P->params, "sorient").s; + if (opt) { + if (!strcmp(opt, "horizontal")) { + Q->transform(orient_horizontal_trans, orient_horizontal_inv_trans); + } else if (!strcmp(opt, "vertical")) { + // the orientation is vertical by default. + } else { + proj_log_error( + P, + _("Invalid value for orient: only vertical or horizontal are supported")); + return pj_default_destructor(P, + PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); + } + } + + + P->left = PJ_IO_UNITS_RADIANS; P->right = PJ_IO_UNITS_PROJECTED; P->from_greenwich = -P->lam0;