using System; using System.Collections.Generic; namespace Sog { public static class ILMath { #if USE_FLOAT private static float[] s_Sin = new float[360] { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f, 0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f, 0.2079117f, 0.2249510f, 0.2419219f, 0.2588190f, 0.2756373f, 0.2923717f, 0.3090170f, 0.3255681f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f, 0.4067366f, 0.4226182f, 0.4383711f, 0.4539905f, 0.4694715f, 0.4848096f, 0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f, 0.5877852f, 0.6018150f, 0.6156614f, 0.6293204f, 0.6427876f, 0.6560590f, 0.6691306f, 0.6819983f, 0.6946583f, 0.7071068f, 0.7193398f, 0.7313537f, 0.7431448f, 0.7547095f, 0.7660444f, 0.7771459f, 0.7880107f, 0.7986355f, 0.8090169f, 0.8191520f, 0.8290375f, 0.8386706f, 0.8480481f, 0.8571673f, 0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f, 0.9135454f, 0.9205048f, 0.9271838f, 0.9335804f, 0.9396926f, 0.9455186f, 0.9510565f, 0.9563047f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f, 0.9781476f, 0.9816272f, 0.9848077f, 0.9876883f, 0.9902681f, 0.9925461f, 0.9945219f, 0.9961947f, 0.9975640f, 0.9986295f, 0.9993908f, 0.9998477f, 1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f, 0.9945219f, 0.9925461f, 0.9902681f, 0.9876884f, 0.9848078f, 0.9816272f, 0.9781476f, 0.9743701f, 0.9702957f, 0.9659259f, 0.9612617f, 0.9563048f, 0.9510565f, 0.9455186f, 0.9396927f, 0.9335805f, 0.9271839f, 0.9205049f, 0.9135455f, 0.9063078f, 0.8987941f, 0.8910066f, 0.8829476f, 0.8746198f, 0.8660254f, 0.8571674f, 0.8480482f, 0.8386706f, 0.8290376f, 0.8191521f, 0.8090171f, 0.7986356f, 0.7880108f, 0.7771460f, 0.7660445f, 0.7547097f, 0.7431449f, 0.7313538f, 0.7193399f, 0.7071069f, 0.6946585f, 0.6819984f, 0.6691307f, 0.6560591f, 0.6427877f, 0.6293205f, 0.6156616f, 0.6018151f, 0.5877854f, 0.5735765f, 0.5591930f, 0.5446391f, 0.5299194f, 0.5150382f, 0.5000001f, 0.4848097f, 0.4694717f, 0.4539906f, 0.4383713f, 0.4226184f, 0.4067368f, 0.3907312f, 0.3746067f, 0.3583681f, 0.3420203f, 0.3255683f, 0.3090171f, 0.2923718f, 0.2756375f, 0.2588192f, 0.2419220f, 0.2249512f, 0.2079118f, 0.1908091f, 0.1736483f, 0.1564346f, 0.1391732f, 0.1218695f, 0.1045286f, 0.0871559f, 0.0697566f, 0.0523361f, 0.0348996f, 0.0174526f, 0.0000002f, -0.0174523f, -0.0348993f, -0.0523358f, -0.0697563f, -0.0871556f, -0.1045283f, -0.1218692f, -0.1391729f, -0.1564343f, -0.1736480f, -0.1908088f, -0.2079115f, -0.2249509f, -0.2419217f, -0.2588189f, -0.2756372f, -0.2923715f, -0.3090168f, -0.3255680f, -0.3420200f, -0.3583678f, -0.3746064f, -0.3907310f, -0.4067365f, -0.4226181f, -0.4383710f, -0.4539903f, -0.4694714f, -0.4848095f, -0.4999999f, -0.5150379f, -0.5299191f, -0.5446389f, -0.5591928f, -0.5735763f, -0.5877851f, -0.6018149f, -0.6156613f, -0.6293203f, -0.6427875f, -0.6560589f, -0.6691304f, -0.6819983f, -0.6946582f, -0.7071066f, -0.7193397f, -0.7313536f, -0.7431447f, -0.7547095f, -0.7660443f, -0.7771459f, -0.7880107f, -0.7986354f, -0.8090169f, -0.8191519f, -0.8290375f, -0.8386704f, -0.8480480f, -0.8571672f, -0.8660253f, -0.8746196f, -0.8829475f, -0.8910064f, -0.8987939f, -0.9063077f, -0.9135454f, -0.9205047f, -0.9271837f, -0.9335803f, -0.9396926f, -0.9455185f, -0.9510565f, -0.9563047f, -0.9612616f, -0.9659258f, -0.9702957f, -0.9743700f, -0.9781476f, -0.9816272f, -0.9848077f, -0.9876883f, -0.9902681f, -0.9925461f, -0.9945219f, -0.9961947f, -0.9975640f, -0.9986295f, -0.9993908f, -0.9998477f, -1.0000000f, -0.9998477f, -0.9993908f, -0.9986296f, -0.9975641f, -0.9961947f, -0.9945219f, -0.9925462f, -0.9902681f, -0.9876884f, -0.9848078f, -0.9816272f, -0.9781476f, -0.9743701f, -0.9702958f, -0.9659259f, -0.9612617f, -0.9563048f, -0.9510566f, -0.9455187f, -0.9396927f, -0.9335805f, -0.9271839f, -0.9205049f, -0.9135455f, -0.9063079f, -0.8987942f, -0.8910066f, -0.8829477f, -0.8746198f, -0.8660255f, -0.8571674f, -0.8480482f, -0.8386707f, -0.8290377f, -0.8191522f, -0.8090171f, -0.7986357f, -0.7880109f, -0.7771461f, -0.7660446f, -0.7547098f, -0.7431450f, -0.7313539f, -0.7193400f, -0.7071069f, -0.6946586f, -0.6819986f, -0.6691308f, -0.6560592f, -0.6427878f, -0.6293206f, -0.6156617f, -0.6018152f, -0.5877855f, -0.5735767f, -0.5591931f, -0.5446393f, -0.5299195f, -0.5150383f, -0.5000002f, -0.4848099f, -0.4694718f, -0.4539908f, -0.4383714f, -0.4226185f, -0.4067369f, -0.3907314f, -0.3746068f, -0.3583682f, -0.3420204f, -0.3255684f, -0.3090173f, -0.2923720f, -0.2756376f, -0.2588193f, -0.2419222f, -0.2249513f, -0.2079120f, -0.1908093f, -0.1736485f, -0.1564348f, -0.1391734f, -0.1218696f, -0.1045288f, -0.0871560f, -0.0697568f, -0.0523363f, -0.0348998f, -0.0174527f }; private static float[] s_Cos = new float[360] { 1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f, 0.9945219f, 0.9925461f, 0.9902681f, 0.9876884f, 0.9848077f, 0.9816272f, 0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f, 0.9510565f, 0.9455186f, 0.9396926f, 0.9335805f, 0.9271839f, 0.9205049f, 0.9135455f, 0.9063078f, 0.8987941f, 0.8910065f, 0.8829476f, 0.8746197f, 0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191521f, 0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f, 0.7431449f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f, 0.6691306f, 0.6560591f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f, 0.5877853f, 0.5735765f, 0.5591930f, 0.5446391f, 0.5299193f, 0.5150381f, 0.5000001f, 0.4848097f, 0.4694716f, 0.4539905f, 0.4383712f, 0.4226183f, 0.4067367f, 0.3907312f, 0.3746066f, 0.3583680f, 0.3420202f, 0.3255682f, 0.3090171f, 0.2923717f, 0.2756374f, 0.2588191f, 0.2419220f, 0.2249511f, 0.2079118f, 0.1908091f, 0.1736482f, 0.1564345f, 0.1391732f, 0.1218694f, 0.1045285f, 0.0871558f, 0.0697565f, 0.0523360f, 0.0348996f, 0.0174525f, 0.0000001f, -0.0174523f, -0.0348994f, -0.0523359f, -0.0697564f, -0.0871557f, -0.1045284f, -0.1218693f, -0.1391730f, -0.1564344f, -0.1736481f, -0.1908089f, -0.2079116f, -0.2249510f, -0.2419218f, -0.2588190f, -0.2756373f, -0.2923716f, -0.3090169f, -0.3255681f, -0.3420201f, -0.3583679f, -0.3746065f, -0.3907310f, -0.4067366f, -0.4226182f, -0.4383711f, -0.4539904f, -0.4694715f, -0.4848095f, -0.4999999f, -0.5150380f, -0.5299192f, -0.5446389f, -0.5591928f, -0.5735763f, -0.5877852f, -0.6018149f, -0.6156614f, -0.6293203f, -0.6427875f, -0.6560590f, -0.6691305f, -0.6819983f, -0.6946583f, -0.7071067f, -0.7193397f, -0.7313536f, -0.7431448f, -0.7547095f, -0.7660444f, -0.7771459f, -0.7880107f, -0.7986354f, -0.8090169f, -0.8191520f, -0.8290375f, -0.8386705f, -0.8480480f, -0.8571672f, -0.8660253f, -0.8746197f, -0.8829475f, -0.8910065f, -0.8987940f, -0.9063078f, -0.9135454f, -0.9205048f, -0.9271838f, -0.9335804f, -0.9396926f, -0.9455186f, -0.9510565f, -0.9563047f, -0.9612616f, -0.9659258f, -0.9702957f, -0.9743701f, -0.9781476f, -0.9816272f, -0.9848077f, -0.9876883f, -0.9902681f, -0.9925461f, -0.9945219f, -0.9961947f, -0.9975640f, -0.9986295f, -0.9993908f, -0.9998477f, -1.0000000f, -0.9998477f, -0.9993908f, -0.9986296f, -0.9975641f, -0.9961947f, -0.9945219f, -0.9925461f, -0.9902681f, -0.9876884f, -0.9848078f, -0.9816272f, -0.9781476f, -0.9743701f, -0.9702958f, -0.9659259f, -0.9612617f, -0.9563048f, -0.9510565f, -0.9455186f, -0.9396927f, -0.9335805f, -0.9271839f, -0.9205049f, -0.9135455f, -0.9063079f, -0.8987941f, -0.8910066f, -0.8829477f, -0.8746198f, -0.8660255f, -0.8571674f, -0.8480482f, -0.8386707f, -0.8290377f, -0.8191522f, -0.8090171f, -0.7986356f, -0.7880109f, -0.7771461f, -0.7660446f, -0.7547097f, -0.7431449f, -0.7313538f, -0.7193399f, -0.7071069f, -0.6946585f, -0.6819985f, -0.6691307f, -0.6560591f, -0.6427878f, -0.6293206f, -0.6156616f, -0.6018152f, -0.5877854f, -0.5735766f, -0.5591931f, -0.5446392f, -0.5299194f, -0.5150383f, -0.5000002f, -0.4848098f, -0.4694718f, -0.4539907f, -0.4383713f, -0.4226184f, -0.4067368f, -0.3907313f, -0.3746068f, -0.3583682f, -0.3420203f, -0.3255683f, -0.3090172f, -0.2923719f, -0.2756376f, -0.2588193f, -0.2419221f, -0.2249513f, -0.2079119f, -0.1908092f, -0.1736484f, -0.1564347f, -0.1391733f, -0.1218696f, -0.1045287f, -0.0871560f, -0.0697567f, -0.0523362f, -0.0348997f, -0.0174526f, -0.0000002f, 0.0174522f, 0.0348993f, 0.0523357f, 0.0697562f, 0.0871555f, 0.1045282f, 0.1218691f, 0.1391729f, 0.1564342f, 0.1736479f, 0.1908088f, 0.2079115f, 0.2249508f, 0.2419217f, 0.2588188f, 0.2756371f, 0.2923715f, 0.3090168f, 0.3255679f, 0.3420199f, 0.3583677f, 0.3746064f, 0.3907309f, 0.4067364f, 0.4226180f, 0.4383709f, 0.4539903f, 0.4694713f, 0.4848094f, 0.4999998f, 0.5150378f, 0.5299190f, 0.5446388f, 0.5591927f, 0.5735762f, 0.5877851f, 0.6018148f, 0.6156613f, 0.6293202f, 0.6427874f, 0.6560588f, 0.6691304f, 0.6819982f, 0.6946582f, 0.7071066f, 0.7193396f, 0.7313535f, 0.7431446f, 0.7547094f, 0.7660443f, 0.7771458f, 0.7880106f, 0.7986354f, 0.8090168f, 0.8191519f, 0.8290374f, 0.8386704f, 0.8480480f, 0.8571672f, 0.8660253f, 0.8746195f, 0.8829474f, 0.8910064f, 0.8987939f, 0.9063077f, 0.9135454f, 0.9205047f, 0.9271837f, 0.9335803f, 0.9396925f, 0.9455185f, 0.9510564f, 0.9563047f, 0.9612616f, 0.9659258f, 0.9702957f, 0.9743700f, 0.9781476f, 0.9816271f, 0.9848077f, 0.9876883f, 0.9902681f, 0.9925461f, 0.9945219f, 0.9961947f, 0.9975640f, 0.9986295f, 0.9993908f, 0.9998477f }; public static float Sin(int angle) { angle = (360 + angle % 360) % 360; return s_Sin[angle]; } public static float Cos(int angle) { angle = (360 + angle % 360) % 360; return s_Cos[angle]; } #else private static readonly int[] s_Sin = new int[360] { 0, 17, 34, 52, 69, 87, 104, 121, 139, 156, 173, 190, 207, 224, 241, 258, 275, 292, 309, 325, 342, 358, 374, 390, 406, 422, 438, 453, 469, 484, 499, 515, 529, 544, 559, 573, 587, 601, 615, 629, 642, 656, 669, 681, 694, 707, 719, 731, 743, 754, 766, 777, 788, 798, 809, 819, 829, 838, 848, 857, 866, 874, 882, 891, 898, 906, 913, 920, 927, 933, 939, 945, 951, 956, 961, 965, 970, 974, 978, 981, 984, 987, 990, 992, 994, 996, 997, 998, 999, 999, 1000, 999, 999, 998, 997, 996, 994, 992, 990, 987, 984, 981, 978, 974, 970, 965, 961, 956, 951, 945, 939, 933, 927, 920, 913, 906, 898, 891, 882, 874, 866, 857, 848, 838, 829, 819, 809, 798, 788, 777, 766, 754, 743, 731, 719, 707, 694, 681, 669, 656, 642, 629, 615, 601, 587, 573, 559, 544, 529, 515, 499, 484, 469, 453, 438, 422, 406, 390, 374, 358, 342, 325, 309, 292, 275, 258, 241, 224, 207, 190, 173, 156, 139, 121, 104, 87, 69, 52, 34, 17, 0, -17, -34, -52, -69, -87, -104, -121, -139, -156, -173, -190, -207, -224, -241, -258, -275, -292, -309, -325, -342, -358, -374, -390, -406, -422, -438, -453, -469, -484, -500, -515, -529, -544, -559, -573, -587, -601, -615, -629, -642, -656, -669, -681, -694, -707, -719, -731, -743, -754, -766, -777, -788, -798, -809, -819, -829, -838, -848, -857, -866, -874, -882, -891, -898, -906, -913, -920, -927, -933, -939, -945, -951, -956, -961, -965, -970, -974, -978, -981, -984, -987, -990, -992, -994, -996, -997, -998, -999, -999, -1000, -999, -999, -998, -997, -996, -994, -992, -990, -987, -984, -981, -978, -974, -970, -965, -961, -956, -951, -945, -939, -933, -927, -920, -913, -906, -898, -891, -882, -874, -866, -857, -848, -838, -829, -819, -809, -798, -788, -777, -766, -754, -743, -731, -719, -707, -694, -681, -669, -656, -642, -629, -615, -601, -587, -573, -559, -544, -529, -515, -500, -484, -469, -453, -438, -422, -406, -390, -374, -358, -342, -325, -309, -292, -275, -258, -241, -224, -207, -190, -173, -156, -139, -121, -104, -87, -69, -52, -34, -17, }; private static readonly int[] s_Cos = new int[360] { 1000, 999, 999, 998, 997, 996, 994, 992, 990, 987, 984, 981, 978, 974, 970, 965, 961, 956, 951, 945, 939, 933, 927, 920, 913, 906, 898, 891, 882, 874, 866, 857, 848, 838, 829, 819, 809, 798, 788, 777, 766, 754, 743, 731, 719, 707, 694, 681, 669, 656, 642, 629, 615, 601, 587, 573, 559, 544, 529, 515, 500, 484, 469, 453, 438, 422, 406, 390, 374, 358, 342, 325, 309, 292, 275, 258, 241, 224, 207, 190, 173, 156, 139, 121, 104, 87, 69, 52, 34, 17, 0, -17, -34, -52, -69, -87, -104, -121, -139, -156, -173, -190, -207, -224, -241, -258, -275, -292, -309, -325, -342, -358, -374, -390, -406, -422, -438, -453, -469, -484, -499, -515, -529, -544, -559, -573, -587, -601, -615, -629, -642, -656, -669, -681, -694, -707, -719, -731, -743, -754, -766, -777, -788, -798, -809, -819, -829, -838, -848, -857, -866, -874, -882, -891, -898, -906, -913, -920, -927, -933, -939, -945, -951, -956, -961, -965, -970, -974, -978, -981, -984, -987, -990, -992, -994, -996, -997, -998, -999, -999, -1000, -999, -999, -998, -997, -996, -994, -992, -990, -987, -984, -981, -978, -974, -970, -965, -961, -956, -951, -945, -939, -933, -927, -920, -913, -906, -898, -891, -882, -874, -866, -857, -848, -838, -829, -819, -809, -798, -788, -777, -766, -754, -743, -731, -719, -707, -694, -681, -669, -656, -642, -629, -615, -601, -587, -573, -559, -544, -529, -515, -500, -484, -469, -453, -438, -422, -406, -390, -374, -358, -342, -325, -309, -292, -275, -258, -241, -224, -207, -190, -173, -156, -139, -121, -104, -87, -69, -52, -34, -17, 0, 17, 34, 52, 69, 87, 104, 121, 139, 156, 173, 190, 207, 224, 241, 258, 275, 292, 309, 325, 342, 358, 374, 390, 406, 422, 438, 453, 469, 484, 500, 515, 529, 544, 559, 573, 587, 601, 615, 629, 642, 656, 669, 681, 694, 707, 719, 731, 743, 754, 766, 777, 788, 798, 809, 819, 829, 838, 848, 857, 866, 874, 882, 891, 898, 906, 913, 920, 927, 933, 939, 945, 951, 956, 961, 965, 970, 974, 978, 981, 984, 987, 990, 992, 994, 996, 997, 998, 999, 999, }; public static int Sin(int angle) { angle = (360 + angle % 360) % 360; return s_Sin[angle]; } public static int Cos(int angle) { angle = (360 + angle % 360) % 360; return s_Cos[angle]; } #endif private static readonly int[] s_ATan = new int[960] { 0,1,1,2,2,3,4,4,5,5,6,6,7,7,8,9,9,10,10,11,11,12,12,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21, 22,22,23,23,24,24,25,25,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,33,33,34,34,34,35,35,36,36,36,37,37,37,38,38, 39,39,39,40,40,40,41,41,41,41,42,42,42,43,43,43,44,44,44,45,45,45,45,46,46,46,46,47,47,47,47,48,48,48,48,49,49,49,49,50, 50,50,50,51,51,51,51,52,52,52,52,52,53,53,53,53,53,54,54,54,54,54,55,55,55,55,55,55,56,56,56,56,56,57,57,57,57,57,57,57, 58,58,58,58,58,58,59,59,59,59,59,59,59,60,60,60,60,60,60,60,61,61,61,61,61,61,61,61,62,62,62,62,62,62,62,62,63,63,63,63, 63,63,63,63,63,64,64,64,64,64,64,64,64,64,65,65,65,65,65,65,65,65,65,65,66,66,66,66,66,66,66,66,66,66,66,67,67,67,67,67, 67,67,67,67,67,67,67,68,68,68,68,68,68,68,68,68,68,68,68,68,69,69,69,69,69,69,69,69,69,69,69,69,69,69,70,70,70,70,70,70, 70,70,70,70,70,70,70,70,70,70,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,72,72,72,72,72,72,72,72,72,72,72,72,72, 72,72,72,72,72,72,72,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,74,74,74,74,74,74,74,74,74,74,74,74, 74,74,74,74,74,74,74,74,74,74,74,74,74,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, 75,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,77,77,77,77,77,77,77, 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,78,78,78,78,78,78,78,78,78,78, 78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,79,79,79,79,79,79, 79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, 79,79,79,79,79,79,79,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,81,81,81,81,81,81,81,81,81, 81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, 81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,82,82,82,82,82,82,82,82,82, 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, 82,82,82,82,82,82,82,82,82,82,82,82,82,82,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, 83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, 83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, 83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,84,84,84,84,84,84,84,84,84 }; private static readonly int[] s_ACos = new int[1001] { 90,90,90,90,90,90,90,90,90,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,88,88,88,88,88,88,88,88,88,88,88,88,88, 88,88,88,88,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,85, 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,83,83,83,83,83,83, 83,83,83,83,83,83,83,83,83,83,83,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,81,81,81,81,81,81,81,81,81,81,81,81, 81,81,81,81,81,81,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, 78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,76,76,76,76,76,76, 76,76,76,76,76,76,76,76,76,76,76,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,74,74,74,74,74,74,74,74,74,74,74,74, 74,74,74,74,74,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,71,71, 71,71,71,71,71,71,71,71,71,71,71,71,71,71,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,69,69,69,69,69,69,69,69,69, 69,69,69,69,69,69,69,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,66, 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,59,59,59,59,59,59,59,59,59,59,59,59, 59,59,59,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,57,57,57,57,57,57,57,57,57,57,57,57,57,57,56,56,56,56,56,56,56,56, 56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,53,53,53,53, 53,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,51,51,51,51,50,50,50, 50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47, 47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44, 44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41, 41,40,40,40,40,40,40,40,40,40,40,40,39,39,39,39,39,39,39,39,39,39,39,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37, 37,37,37,37,36,36,36,36,36,36,36,36,36,36,36,35,35,35,35,35,35,35,35,35,35,34,34,34,34,34,34,34,34,34,33,33,33,33,33,33, 33,33,33,33,32,32,32,32,32,32,32,32,32,31,31,31,31,31,31,31,31,31,30,30,30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,28, 28,28,28,28,28,28,28,28,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,25,25,25,25,25,25,25,24,24,24,24,24,24,24,24,23,23, 23,23,23,23,22,22,22,22,22,22,22,21,21,21,21,21,21,20,20,20,20,20,20,19,19,19,19,19,19,18,18,18,18,18,17,17,17,17,17,16, 16,16,16,16,15,15,15,15,15,14,14,14,14,13,13,13,13,12,12,12,11,11,11,11,10,10,10,9,9,9,8,8,7,7,6,6,5,4,4,3,0 }; public static int GetAngle(int x1, int y1, int x2, int y2) { int angle = 0; if (x1 == x2) { if (y2 >= y1) { angle = 90; } else { angle = 270; } } else { int tan = (y2 - y1) * 100 / (x2 - x1); int idx = tan; if (idx < 0) { idx = -idx; } if (idx < 960) { angle = s_ATan[idx]; } else if (idx >= 960 && idx < 1143) { angle = 84; } else if (idx >= 1143 && idx < 1430) { angle = 85; } else if (idx >= 1430 && idx < 1908) { angle = 86; } else if (idx >= 1908 && idx < 2863) { angle = 87; } else if (idx >= 2863 && idx < 5728) { angle = 88; } else if (idx >= 5728) { angle = 89; } if (tan >= 0) { if (x2 < x1) // 第三坐标系 { angle += 180; } } else { if (y2 >= y1) // 第二坐标系 { angle = 180 - angle; } else //第四坐标系 { angle = 360 - angle; } } } return angle; } public static int GetAngleACos(int acos) { if (acos >= 0) { if (acos > 1000) { acos = 1000; } return s_ACos[acos]; } if (acos < -1000) { acos = -1000; } return 180 - s_ACos[-acos]; } // 角度为笛卡尔坐标(水平为0度,逆时针为正向) public static bool IsCollisionCircleRect(int circleX, int circleY, int radius, int rectX, int rectY, int length, int width, int angle) { //TraceLog.Trace("ILMath.IsCollisionCircleRect circle {0} {1} radius {2} rect {3} {4} length {5} width {6} angle {7}" // , circleX, circleY, radius, rectX, rectY, length, width, angle); Vector2IntFloat circlePos = new Vector2IntFloat {x = circleX, y = circleY}; Vector2IntFloat rectPos = new Vector2IntFloat {x = rectX, y = rectY}; //将坐标按矩形中心点旋转 Vector2IntFloat newCPos = CalcNewPointOnCoordinate(circlePos, rectPos, -1 * angle); int halfLen = length / 2; int halfWid = width / 2; //TraceLog.Trace("ILMath.IsCollisionCircleRect newCPos {0} {1} halfLen {2} halfWid {3}", // newCPos.x, newCPos.y, halfLen, halfWid); // 圆心所在的位置,分9个区块判断 if (newCPos.x >= halfLen && newCPos.y >= halfWid) { // 右上角 return IsCollisionCircleCircle(newCPos.x, newCPos.y, radius, halfLen, halfWid, 0); } else if (newCPos.x >= halfLen && newCPos.y <= -halfWid) { // 右下角 return IsCollisionCircleCircle(newCPos.x, newCPos.y, radius, halfLen, -halfWid, 0); } else if (newCPos.x <= -halfLen && newCPos.y <= -halfWid) { // 左下角 return IsCollisionCircleCircle(newCPos.x, newCPos.y, radius, -halfLen, -halfWid, 0); } else if (newCPos.x <= -halfLen && newCPos.y >= halfWid) { // 左上角 return IsCollisionCircleCircle(newCPos.x, newCPos.y, radius, -halfLen, halfWid, 0); } if (newCPos.x > -halfLen - radius && newCPos.x < halfLen + radius && newCPos.y > -halfWid - radius && newCPos.y < halfWid + radius) { return true; } return false; } public static Vector2IntFloat CalcNewPointOnCoordinate(Vector2IntFloat pos, Vector2IntFloat origin, int angle) { int sin = ILMath.Sin(angle); int cos = ILMath.Cos(angle); int basenum = 1000;//(cos * cos + sin * sin); int dx = pos.x - origin.x; int dy = pos.y - origin.y; var newPos = new Vector2IntFloat { x = (cos * dx - sin * dy) / basenum, y = (sin * dx + cos * dy) / basenum, }; //TraceLog.Trace("ILMath.CalcNewPointOnCoordinate angle {0} sin {1} cos {2} basenum {3} dx {4} dy {5} pos {6} {7} origin {8} {9} pos new {10} {11}", // angle, sin, cos, basenum, dx, dy, pos.x, pos.y, origin.x, origin.y, newPos.x, newPos.y); return newPos; } //判断圆和圆,圆和点之间的位置关系,交集大于0则返回true public static bool IsCollisionCircleCircle(int x1, int y1, int radius1, int x2, int y2, int radius2) { long disX = x1 - x2; long disY = y1 - y2; long disSquare1 = disX * disX + disY * disY; long disRadius = radius1 + radius2; long disSquare2 = disRadius * disRadius; return disSquare1 < disSquare2; } //判断圆是否和扇形碰撞,sx,sy扇形中心,半径,朝向,夹角 public static bool IsCollisionCircleSector(int cx, int cy, int radius1, int sx, int sy, int radius2, int angle, int sectorAngle) { long dx = cx - sx; long dy = cy - sy; long dr = radius1 + radius2; //先判断圆的碰撞 if (dx * dx + dy * dy > dr * dr) { return false; } //圆心和扇形圆形的角度在夹角内 int circleAngle = GetAngle(sx, sy, cx, cy); if (circleAngle > angle - sectorAngle / 2 && circleAngle < angle + sectorAngle / 2) { return true; } if (angle - sectorAngle / 2 < 0 && angle + 360 - sectorAngle / 2 < circleAngle && circleAngle < 360) { return true; } if (angle + sectorAngle / 2 > 360 && angle + sectorAngle / 2 - 360 > circleAngle && circleAngle > 0) { return true; } if (radius1 == 0) { return false; } int angle1 = angle - sectorAngle / 2; int angle2 = angle + sectorAngle / 2; int x1 = sx + ILMath.Cos(angle1) * radius2 / 1000; int y1 = sy + ILMath.Sin(angle1) * radius2 / 1000; int x2 = sx + ILMath.Cos(angle2) * radius2 / 1000; int y2 = sy + ILMath.Sin(angle2) * radius2 / 1000; #if false if (IsCircleIntersectLineSegement(cx, cy, radius1, sx, sy, x1, y1)) { return true; } if (IsCircleIntersectLineSegement(cx, cy, radius1, sx, sy, x2, y2)) { return true; } #else if(IsCircleIntersectLine(cx, cy, radius1, sx, sy, x1, y1)) { return true; } if (IsCircleIntersectLine(cx, cy, radius1, sx, sy, x2, y2)) { return true; } #endif return false; } //判断圆是否和线段相交 //这个有问题,换IsCircleIntersectLine public static bool IsCircleIntersectLineSegement(long centerX, long centerY, long radius, long lineStartX, long lineStartY, long lineEndX, long lineEndY) { long centerVectorX = centerX - lineStartX; long centerVectorY = centerY - lineStartY; long lineVectorX = lineEndX - lineStartX; long lineVectorY = lineEndY - lineStartY; // 当线段是点时,判断点是否在圆内 if (lineVectorX == 0 && lineVectorY == 0) { long squareLength = centerVectorX * centerVectorX + centerVectorY * centerVectorY; return squareLength <= radius * radius; } long lineLength = reckon_sqrt(lineVectorX * lineVectorX + lineVectorY * lineVectorY); //normalize,单位化 lineVectorX = lineVectorX / lineLength; lineVectorY = lineVectorY / lineLength; // 投影长度,向量A在B上的投影长度 d = (A dot B) / |B| long projectionLength = centerVectorX * lineVectorX + centerVectorY * lineVectorY; long nearestPointX = 0; long nearestPointY = 0; if (projectionLength <= 0) { nearestPointX = lineStartX; nearestPointY = lineStartY; } else if (projectionLength >= lineLength) { nearestPointX = lineEndX; nearestPointY = lineEndY; } else { nearestPointX = lineStartX + lineVectorX * projectionLength; nearestPointY = lineStartY + lineVectorY * projectionLength; } long dx = centerX - nearestPointX; long dy = centerY - nearestPointY; long dist2 = dx * dx + dy * dy; return dist2 <= radius * radius; } public static Fixed64Vector2 ClosestPoint(Fixed64Vector2 start, Fixed64Vector2 end, Fixed64Vector2 point) { Fixed64Vector2 direction = end - start; Fixed64 t = direction.SqrMagnitude; if (t == 0) return start; t = FixedMath.Clamp01(Fixed64Vector2.Dot(point - start, direction) / t); return start + direction * t; } public static bool IsCircleIntersectLine(Fixed64Vector2 start, Fixed64Vector2 end, Fixed64Vector2 center, Fixed64 radius) { Fixed64 sqrDistance = (ClosestPoint(start, end, center) - center).SqrMagnitude; return sqrDistance < radius * radius; } public static bool IsCircleIntersectLine(int centerX, int centerY, int radius, int lineStartX, int lineStartY, int lineEndX, int lineEndY) { Fixed64Vector2 start = new Fixed64Vector2((Fixed64)lineStartX / 1000, (Fixed64)lineStartY / 1000); Fixed64Vector2 end = new Fixed64Vector2((Fixed64)lineEndX / 1000, (Fixed64)lineEndY / 1000); Fixed64Vector2 center = new Fixed64Vector2((Fixed64)centerX / 1000, (Fixed64)centerY / 1000); Fixed64 fradius = (Fixed64)radius / 1000; #if false return IsCircleIntersectLine(center.x, center.y, fradius, start, end); #else return IsCircleIntersectLine(start, end, center,fradius); #endif } public static bool IsCircleIntersectLine(Fixed64 x, Fixed64 y, Fixed64 radius, Fixed64Vector2 vStart, Fixed64Vector2 vEnd) { Fixed64Vector2 vNearest = new Fixed64Vector2(); // 线段上到圆心最近的点 Fixed64Vector2 vDis = vEnd - vStart; if (vDis.x == 0 && vDis.y == 0) { vNearest = vStart; } else { // 求圆心在直线上的投影点 Fixed64Vector2 upright; { // 直线的长度与方向 Fixed64 length = Fixed64Vector2.Distance(vStart, vEnd); Fixed64Vector2 dir = vDis / length; // 直线法向 Fixed64Vector2 normal = new Fixed64Vector2(-dir.y, dir.x); Fixed64 distance = -(vStart.x * normal.x + vStart.y * normal.y); // 圆心到直线的距离 Fixed64 disToCenter = normal.x * x + normal.y * y + distance; if (disToCenter > radius) { return false; } upright = normal * (-disToCenter); upright.x += x; upright.y += y; } Fixed64 radio; if (vDis.x != 0) // 是否为0 { radio = (upright.x - vStart.x) / vDis.x; } else { radio = (upright.y - vStart.y) / vDis.y; } if (radio < 0) { vNearest = vStart; } else if (radio > 1) { vNearest = vEnd; } else { vNearest.x = upright.x; vNearest.y = upright.y; } } return Fixed64Vector2.DistanceSquared(vNearest, new Fixed64Vector2(x, y)) < radius * radius; } public static void BubbleSortList(List list, Func compare) { for (int i = list.Count; i > 0; i--) { for (int j = 0; j < i - 1; j++) { if (compare(list[j], list[j + 1]) > 0) { T temp = list[j]; list[j] = list[j + 1]; list[j + 1] = temp; } } } } //预估迭代法 public static int reckon_sqrt( long x) { int y; //初始估计值,太大对这个项目也没啥意义了,应该不会用到 if (x > 4294967296L) { if (x > 17592186044416) y = 6291456; else if (x > 4398046511104) y = 3145728; else if (x > 1099511627776) y = 1572864; else if (x > 274877906944) y = 786432; else if (x > 68719476736) y = 393216; else if (x > 17179869184) y = 196608; else y = 98304; } else if( x > 262144) { if (x > 1073741824) y = 49152; else if (x > 268435456) y = 24576; else if (x > 67108864) y = 12288; else if (x > 16777216) y = 6144; else if (x > 4194304) y = 3072; else if (x > 1048576) y = 1536; else y = 768; } else { if (x > 65536) y = 384; else if (x > 16384) y = 192; else if (x > 4096) y = 96; else if (x > 1024) y = 48; else if (x > 256) y = 24; else if (x > 64) y = 12; else y = 6; } y = (y + (int)(x / y)) >> 1; y = (y + (int)(x / y)) >> 1; y = (y + (int)(x / y)) >> 1; return y; } public static int shift_sqrt(long val) { long r = 0; for (int shift = 0; shift < 64; shift += 2) { long x = 0x4000000000000000L >> shift; if (x + r <= val) { val -= x + r; r = (r >> 1) | x; } else { r >>= 1; } } //if(r < val) ++r; return (int)r; } public static bool IsInCameraView(int[,] viewMat4x4, int posX, int posZ) { int x = viewMat4x4[0, 0] * posX / 1000 + viewMat4x4[0, 2] * posZ / 1000 + viewMat4x4[0, 3]; int z = viewMat4x4[2, 0] * posX / 1000 + viewMat4x4[2, 2] * posZ / 1000 + viewMat4x4[2, 3]; int num = viewMat4x4[3, 0] * posX / 1000 + viewMat4x4[3, 2] * posZ / 1000 + viewMat4x4[3, 3]; // 乘以1000来表示小数 x = x * 1000 / num; z = z * 1000 / num; return -1000 <= x && x <= 1000 && -1000 <= z && z <= 1000; //Fixed64[,] fixViewMat = new Fixed64[4,4]; //for (int i = 0; i < 4; i++) //{ // for (int j = 0; j < 4; j++) // { // fixViewMat[i, j] = (Fixed64) viewMat4x4[i, j] / 1000; // } //} //Fixed64 fixPosX = (Fixed64) posX / (Fixed64)1000; //Fixed64 fixPosZ = (Fixed64) posZ / (Fixed64)1000; //Fixed64 x1 = fixViewMat[0, 0] * fixPosX + fixViewMat[0, 2] * fixPosZ + fixViewMat[0, 3]; //Fixed64 z1 = fixViewMat[2, 0] * fixPosX + fixViewMat[2, 2] * fixPosZ + fixViewMat[2, 3]; //Fixed64 num1 = fixViewMat[3, 0] * fixPosX + fixViewMat[3, 2] * fixPosZ + fixViewMat[3, 3]; //x1 = x1 / num1; //z1 = z1 / num1; } public static bool IsInPolygon(int[,] v, long posX, long posZ) { long a = (v[1, 0] - v[0, 0]) * (posZ - v[0, 1]) - (v[1, 1] - v[0, 1]) * (posX - v[0, 0]); long b = (v[2, 0] - v[1, 0]) * (posZ - v[1, 1]) - (v[2, 1] - v[1, 1]) * (posX - v[1, 0]); long c = (v[3, 0] - v[2, 0]) * (posZ - v[2, 1]) - (v[3, 1] - v[2, 1]) * (posX - v[2, 0]); long d = (v[0, 0] - v[3, 0]) * (posZ - v[3, 1]) - (v[0, 1] - v[3, 1]) * (posX - v[3, 0]); if ((a >= 0 && b >= 0 && c >= 0 && d >= 0) || (a <= 0 && b <= 0 && c <= 0 & d <= 0)) { return true; } return false; } //算立方根 public static long CalCubeRoot(long num) { //精度太高了,项目用不到。实测release模式下效率不如下面的二分法,涉及到小数,跨平台还会有问题 //return (long)Math.Pow((double)num, (double)1 / 3); if (num == 1000000000) { return 1000; } long left, right; if (num < 1000000000) { left = 0; right = 1000; } else { left = 1000; right = 2 * left; while (right * right * right <= num) { left *= 2; right = 2 * left; } } while (right - left > 4) { long mid = left + (right - left) / 2; long midCube = mid * mid * mid; if (midCube == num) { return mid; } if (mid * mid * mid < num) { left = mid; } else { right = mid; } } long res = left; for (var i = left + 1; i <= right; ++i) { if (i * i * i <= num) { res = i; } else { break; } } return res; } } }