diff --git a/Cargo.toml b/Cargo.toml index a237641..4d84df0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,3 +60,7 @@ harness = false [[bench]] name = "triangulation" harness = false + +[[bench]] +name = "merger" +harness = false diff --git a/benches/merger.rs b/benches/merger.rs new file mode 100644 index 0000000..4e47218 --- /dev/null +++ b/benches/merger.rs @@ -0,0 +1,1983 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use glam::{vec2, Vec2}; +use polyanya::{Mesh, Triangulation}; + +const ARENA_OUTER_EDGE: [Vec2; 82] = [ + vec2(1., 3.), + vec2(2., 3.), + vec2(2., 2.), + vec2(3., 2.), + vec2(3., 1.), + vec2(15., 1.), + vec2(15., 3.), + vec2(18., 3.), + vec2(18., 2.), + vec2(19., 2.), + vec2(19., 1.), + vec2(20., 1.), + vec2(20., 2.), + vec2(23., 2.), + vec2(23., 1.), + vec2(26., 1.), + vec2(26., 3.), + vec2(29., 3.), + vec2(29., 2.), + vec2(30., 2.), + vec2(30., 1.), + vec2(31., 1.), + vec2(31., 3.), + vec2(34., 3.), + vec2(34., 2.), + vec2(35., 2.), + vec2(35., 1.), + vec2(47., 1.), + vec2(47., 3.), + vec2(48., 3.), + vec2(48., 15.), + vec2(47., 15.), + vec2(47., 19.), + vec2(48., 19.), + vec2(48., 31.), + vec2(47., 31.), + vec2(47., 35.), + vec2(48., 35.), + vec2(48., 47.), + vec2(47., 47.), + vec2(47., 48.), + vec2(35., 48.), + vec2(35., 47.), + vec2(31., 47.), + vec2(31., 48.), + vec2(30., 48.), + vec2(30., 47.), + vec2(29., 47.), + vec2(29., 46.), + vec2(26., 46.), + vec2(26., 48.), + vec2(24., 48.), + vec2(24., 47.), + vec2(23., 47.), + vec2(23., 46.), + vec2(20., 46.), + vec2(20., 48.), + vec2(19., 48.), + vec2(19., 47.), + vec2(15., 47.), + vec2(15., 48.), + vec2(3., 48.), + vec2(3., 47.), + vec2(1., 47.), + vec2(1., 35.), + vec2(2., 35.), + vec2(2., 34.), + vec2(3., 34.), + vec2(3., 31.), + vec2(1., 31.), + vec2(1., 30.), + vec2(3., 30.), + vec2(3., 27.), + vec2(2., 27.), + vec2(2., 26.), + vec2(1., 26.), + vec2(1., 23.), + vec2(2., 23.), + vec2(2., 18.), + vec2(3., 18.), + vec2(3., 15.), + vec2(1., 15.), +]; + +const ARENA_OBSTACLES: [[Vec2; 6]; 5] = [ + [ + vec2(15., 15.), + vec2(19., 15.), + vec2(19., 18.), + vec2(18., 18.), + vec2(18., 19.), + vec2(15., 19.), + ], + [ + vec2(31., 15.), + vec2(35., 15.), + vec2(35., 18.), + vec2(34., 18.), + vec2(34., 19.), + vec2(31., 19.), + ], + [ + vec2(15., 31.), + vec2(19., 31.), + vec2(19., 34.), + vec2(18., 34.), + vec2(18., 35.), + vec2(15., 35.), + ], + [ + vec2(31., 31.), + vec2(35., 31.), + vec2(35., 34.), + vec2(34., 34.), + vec2(34., 35.), + vec2(31., 35.), + ], + [ + vec2(23., 10.), + vec2(23., 8.), + vec2(24., 8.), + vec2(24., 7.), + vec2(26., 7.), + vec2(26., 10.), + ], +]; + +fn merger(c: &mut Criterion) { + c.bench_function(&"merger arena".to_string(), |b| { + b.iter(|| { + // Equivalent to the arena mesh + let mut triangulation = Triangulation::from_outer_edges(ARENA_OUTER_EDGE.to_vec()); + + triangulation.add_obstacle(ARENA_OBSTACLES[0].to_vec()); + triangulation.add_obstacle(ARENA_OBSTACLES[1].to_vec()); + triangulation.add_obstacle(ARENA_OBSTACLES[2].to_vec()); + triangulation.add_obstacle(ARENA_OBSTACLES[3].to_vec()); + triangulation.add_obstacle(ARENA_OBSTACLES[4].to_vec()); + + let mut mesh: Mesh = triangulation.as_navmesh().unwrap(); + while mesh.merge_polygons() {} + black_box(mesh); + }) + }); +} + +fn random_with_many_obstacles() -> Triangulation { + let mut triangulation = Triangulation::from_outer_edges(vec![ + vec2(-5., -5.), + vec2(5., -5.), + vec2(5., 5.), + vec2(-5., 5.), + ]); + triangulation.add_obstacles(vec![ + vec![ + vec2(-4.263351, 4.6476426), + vec2(-4.152357, 4.263351), + vec2(-4.5366488, 4.152357), + vec2(-4.6476426, 4.5366488), + ], + vec![ + vec2(-4.427729, 3.96148), + vec2(-4.1185193, 3.7077286), + vec2(-4.372271, 3.3985198), + vec2(-4.6814804, 3.6522713), + ], + vec![ + vec2(-4.6110992, 2.9482472), + vec2(-4.2117524, 2.971099), + vec2(-4.1889005, 2.5717525), + vec2(-4.5882473, 2.5489008), + ], + vec![ + vec2(-4.6811337, 1.8710448), + vec2(-4.368955, 2.1211336), + vec2(-4.1188664, 1.8089547), + vec2(-4.4310446, 1.5588659), + ], + vec![ + vec2(-4.3769755, 0.6380959), + vec2(-4.681904, 0.8969751), + vec2(-4.423024, 1.2019038), + vec2(-4.1180964, 0.9430246), + ], + vec![ + vec2(-4.1334233, -0.09453427), + vec2(-4.4945345, -0.26657695), + vec2(-4.6665764, 0.09453427), + vec2(-4.3054657, 0.26657695), + ], + vec![ + vec2(-4.2677712, -0.66996914), + vec2(-4.1499686, -1.052229), + vec2(-4.532229, -1.1700312), + vec2(-4.650031, -0.7877712), + ], + vec![ + vec2(-4.4619017, -2.1159856), + vec2(-4.675986, -1.7780981), + vec2(-4.3380985, -1.5640138), + vec2(-4.124014, -1.9019012), + ], + vec![ + vec2(-4.1345353, -2.8576133), + vec2(-4.4976134, -3.025465), + vec2(-4.665465, -2.6623864), + vec2(-4.3023868, -2.494535), + ], + vec![ + vec2(-4.2514873, -3.9207146), + vec2(-4.6407156, -3.8285124), + vec2(-4.548513, -3.4392843), + vec2(-4.1592846, -3.5314865), + ], + vec![ + vec2(-4.180103, -4.577891), + vec2(-4.577891, -4.619897), + vec2(-4.619897, -4.222109), + vec2(-4.222109, -4.180103), + ], + vec![ + vec2(-3.829504, 4.1598988), + vec2(-3.920101, 4.5495043), + vec2(-3.530496, 4.640101), + vec2(-3.439899, 4.250496), + ], + vec![ + vec2(-3.9623792, 3.6638126), + vec2(-3.6961873, 3.9623792), + vec2(-3.397621, 3.6961873), + vec2(-3.6638126, 3.397621), + ], + vec![ + vec2(-3.8170958, 2.512604), + vec2(-3.927396, 2.8970954), + vec2(-3.5429041, 3.0073957), + vec2(-3.4326038, 2.6229043), + ], + vec![ + vec2(-3.5746205, 2.1024787), + vec2(-3.417521, 1.7346205), + vec2(-3.7853794, 1.5775207), + vec2(-3.942479, 1.945379), + ], + vec![ + vec2(-3.828707, 0.6794044), + vec2(-3.9205956, 1.0687071), + vec2(-3.531293, 1.1605954), + vec2(-3.4394042, 0.7712926), + ], + vec![ + vec2(-3.9441833, -0.101030946), + vec2(-3.7810311, 0.26418316), + vec2(-3.4158165, 0.101030946), + vec2(-3.578969, -0.26418316), + ], + vec![ + vec2(-3.9602757, -0.9580192), + vec2(-3.718019, -0.6397243), + vec2(-3.3997242, -0.8819812), + vec2(-3.641981, -1.200276), + ], + vec![ + vec2(-3.9508991, -1.9213247), + vec2(-3.761325, -1.5691009), + vec2(-3.409101, -1.7586749), + vec2(-3.5986748, -2.1108987), + ], + vec![ + vec2(-3.5584362, -3.0153863), + vec2(-3.9353864, -2.8815634), + vec2(-3.8015637, -2.5046134), + vec2(-3.4246135, -2.638436), + ], + vec![ + vec2(-3.3983495, -3.6540565), + vec2(-3.6540568, -3.9616497), + vec2(-3.9616504, -3.7059426), + vec2(-3.705943, -3.3983493), + ], + vec![ + vec2(-3.4161878, -4.298004), + vec2(-3.5780041, -4.663812), + vec2(-3.9438121, -4.5019956), + vec2(-3.7819958, -4.136188), + ], + vec![ + vec2(-2.680174, 4.6713448), + vec2(-2.4886556, 4.3201737), + vec2(-2.8398256, 4.1286554), + vec2(-3.0313442, 4.479826), + ], + vec![ + vec2(-2.709742, 3.9583416), + vec2(-2.4816582, 3.6297421), + vec2(-2.8102577, 3.4016583), + vec2(-3.0383418, 3.730258), + ], + vec![ + vec2(-2.663323, 3.0258071), + vec2(-2.4941924, 2.663323), + vec2(-2.8566768, 2.4941924), + vec2(-3.0258071, 2.8566768), + ], + vec![ + vec2(-2.4795141, 1.8764364), + vec2(-2.7235634, 1.5595138), + vec2(-3.0404856, 1.8035632), + vec2(-2.7964365, 2.1204855), + ], + vec![ + vec2(-3.0221653, 1.0261567), + vec2(-2.653843, 1.1821654), + vec2(-2.4978342, 0.8138431), + vec2(-2.8661566, 0.6578344), + ], + vec![ + vec2(-2.6797504, -0.2712196), + vec2(-3.0312195, -0.080249235), + vec2(-2.840249, 0.2712196), + vec2(-2.4887805, 0.080249235), + ], + vec![ + vec2(-2.5601428, -1.120143), + vec2(-2.9601426, -1.1198572), + vec2(-2.9598567, -0.7198573), + vec2(-2.5598571, -0.72014314), + ], + vec![ + vec2(-3.038027, -1.7880286), + vec2(-2.7080288, -1.5619729), + vec2(-2.481973, -1.891971), + vec2(-2.8119712, -2.1180267), + ], + vec![ + vec2(-3.0326872, -2.68489), + vec2(-2.68489, -2.4873123), + vec2(-2.4873123, -2.83511), + vec2(-2.83511, -3.0326872), + ], + vec![ + vec2(-2.8651178, -3.4174159), + vec2(-2.4974163, -3.5748818), + vec2(-2.654882, -3.942583), + vec2(-3.0225837, -3.7851174), + ], + vec![ + vec2(-2.517898, -4.5462418), + vec2(-2.9062417, -4.6421022), + vec2(-3.0021017, -4.2537584), + vec2(-2.613758, -4.157898), + ], + vec![ + vec2(-2.10501, 4.4988403), + vec2(-1.7411594, 4.6650105), + vec2(-1.5749891, 4.30116), + vec2(-1.9388402, 4.1349893), + ], + vec![ + vec2(-2.0362585, 3.4763274), + vec2(-2.0436723, 3.8762589), + vec2(-1.643741, 3.8836725), + vec2(-1.6363271, 3.483741), + ], + vec![ + vec2(-1.5571609, 2.7614672), + vec2(-1.8385323, 2.477161), + vec2(-2.1228385, 2.7585325), + vec2(-1.8414671, 3.0428388), + ], + vec![ + vec2(-1.8670475, 2.1215463), + vec2(-1.5584532, 1.8670475), + vec2(-1.812952, 1.5584532), + vec2(-2.1215463, 1.812952), + ], + vec![ + vec2(-1.5587149, 0.94964373), + vec2(-1.8103558, 0.63871485), + vec2(-2.1212845, 0.89035594), + vec2(-1.8696436, 1.2012849), + ], + vec![ + vec2(-1.9379233, -0.26535064), + vec2(-2.1053503, 0.09792368), + vec2(-1.742076, 0.26535064), + vec2(-1.5746491, -0.09792368), + ], + vec![ + vec2(-1.6349723, -1.1148431), + vec2(-2.0348427, -1.1250275), + vec2(-2.0450273, -0.7251573), + vec2(-1.6451569, -0.71497273), + ], + vec![ + vec2(-1.9895724, -2.080058), + vec2(-2.080058, -1.690427), + vec2(-1.690427, -1.5999414), + vec2(-1.5999414, -1.9895724), + ], + vec![ + vec2(-1.9857452, -3.002401), + vec2(-2.0824008, -2.6142547), + vec2(-1.6942544, -2.5175989), + vec2(-1.5975987, -2.9057453), + ], + vec![ + vec2(-1.6515998, -3.4690363), + vec2(-1.6290365, -3.8683991), + vec2(-2.0283997, -3.8909626), + vec2(-2.050963, -3.4915996), + ], + vec![ + vec2(-1.934342, -4.666645), + vec2(-2.1066446, -4.3056574), + vec2(-1.7456573, -4.1333547), + vec2(-1.5733548, -4.4943423), + ], + vec![ + vec2(-0.68528, 4.242182), + vec2(-1.0778182, 4.1652803), + vec2(-1.1547197, 4.557818), + vec2(-0.7621816, 4.6347194), + ], + vec![ + vec2(-1.124355, 3.8755476), + vec2(-0.7244521, 3.8843553), + vec2(-0.7156446, 3.4844522), + vec2(-1.1155477, 3.4756448), + ], + vec![ + vec2(-0.80328894, 2.5023594), + vec2(-1.1776402, 2.6432889), + vec2(-1.0367107, 3.01764), + vec2(-0.6623595, 2.876711), + ], + vec![ + vec2(-0.9716875, 1.5619198), + vec2(-1.1980798, 1.8916873), + vec2(-0.8683123, 2.1180797), + vec2(-0.64192003, 1.7883122), + ], + vec![ + vec2(-1.125711, 0.7258789), + vec2(-1.114121, 1.125711), + vec2(-0.71428883, 1.114121), + vec2(-0.7258789, 0.71428883), + ], + vec![ + vec2(-0.8923389, -0.2814869), + vec2(-1.2014867, -0.027661024), + vec2(-0.9476609, 0.2814869), + vec2(-0.63851297, 0.027661024), + ], + vec![ + vec2(-0.88825315, -1.2010556), + vec2(-1.2010553, -0.9517469), + vec2(-0.95174664, -0.63894475), + vec2(-0.6389445, -0.8882534), + ], + vec![ + vec2(-1.0583366, -2.086704), + vec2(-1.1667039, -1.7016631), + vec2(-0.7816632, -1.5932955), + vec2(-0.67329574, -1.9783365), + ], + vec![ + vec2(-1.1769633, -2.6418061), + vec2(-0.8018063, -2.5030365), + vec2(-0.66303635, -2.8781934), + vec2(-1.0381935, -3.0169635), + ], + vec![ + vec2(-1.2025884, -3.6680148), + vec2(-0.9080153, -3.3974109), + vec2(-0.6374111, -3.691984), + vec2(-0.93198436, -3.9625883), + ], + vec![ + vec2(-0.67998445, -4.549641), + vec2(-1.0696414, -4.6400156), + vec2(-1.1600152, -4.2503586), + vec2(-0.7703584, -4.1599846), + ], + vec![ + vec2(0.256111, 4.52003), + vec2(0.12002976, 4.143889), + vec2(-0.256111, 4.2799697), + vec2(-0.12002976, 4.656111), + ], + vec![ + vec2(0.11028748, 3.4195454), + vec2(-0.2604547, 3.5697126), + vec2(-0.11028748, 3.9404545), + vec2(0.2604547, 3.7902873), + ], + vec![ + vec2(0.27981675, 2.7187376), + vec2(-0.04126247, 2.4801831), + vec2(-0.27981675, 2.8012621), + vec2(0.04126247, 3.0398169), + ], + vec![ + vec2(0.061002146, 2.116186), + vec2(0.27618605, 1.7789975), + vec2(-0.061002146, 1.5638136), + vec2(-0.27618605, 1.9010019), + ], + vec![ + vec2(-0.15598473, 1.1559421), + vec2(0.23594229, 1.0759846), + vec2(0.15598473, 0.6840576), + vec2(-0.23594229, 0.76401514), + ], + vec![ + vec2(0.2693349, -0.08636378), + vec2(-0.08636378, -0.2693349), + vec2(-0.2693349, 0.08636378), + vec2(0.08636378, 0.2693349), + ], + vec![ + vec2(0.06291218, -1.1957573), + vec2(-0.27575722, -0.98291236), + vec2(-0.06291218, -0.64424294), + vec2(0.27575722, -0.857088), + ], + vec![ + vec2(-0.04765154, -2.1187997), + vec2(-0.27879983, -1.7923481), + vec2(0.04765154, -1.5611998), + vec2(0.27879983, -1.8876513), + ], + vec![ + vec2(0.18287854, -2.9757671), + vec2(-0.21576709, -2.9428782), + vec2(-0.18287854, -2.5442328), + vec2(0.21576709, -2.5771215), + ], + vec![ + vec2(-0.06433048, -3.955429), + vec2(-0.2754298, -3.6156688), + vec2(0.06433048, -3.4045699), + vec2(0.2754298, -3.74433), + ], + vec![ + vec2(0.2609423, -4.5091286), + vec2(-0.109128736, -4.6609426), + vec2(-0.2609423, -4.290871), + vec2(0.109128736, -4.1390576), + ], + vec![ + vec2(0.7794531, 4.6454515), + vec2(1.1654519, 4.5405474), + vec2(1.0605472, 4.1545486), + vec2(0.6745485, 4.259453), + ], + vec![ + vec2(1.0829749, 3.4488306), + vec2(0.68883085, 3.5170252), + vec2(0.7570255, 3.911169), + vec2(1.1511695, 3.8429744), + ], + vec![ + vec2(0.692718, 2.9283533), + vec2(1.0883535, 2.9872818), + vec2(1.1472822, 2.5916467), + vec2(0.7516469, 2.532718), + ], + vec![ + vec2(0.6514566, 1.9287937), + vec2(1.0087942, 2.1085434), + vec2(1.1885437, 1.7512057), + vec2(0.8312062, 1.5714562), + ], + vec![ + vec2(0.6665098, 0.79453003), + vec2(0.7945304, 1.1734902), + vec2(1.1734905, 1.0454698), + vec2(1.0454699, 0.6665096), + ], + vec![ + vec2(0.68057686, 0.15058722), + vec2(1.0705874, 0.23942326), + vec2(1.1594235, -0.15058722), + vec2(0.76941293, -0.23942326), + ], + vec![ + vec2(1.0525298, -0.6701284), + vec2(1.1698719, -1.0525298), + vec2(0.7874705, -1.1698719), + vec2(0.6701284, -0.7874705), + ], + vec![ + vec2(0.9435564, -2.1218598), + vec2(0.6381401, -1.8635559), + vec2(0.8964439, -1.5581397), + vec2(1.2018603, -1.8164434), + ], + vec![ + vec2(1.2027237, -2.7682083), + vec2(0.91179156, -3.0427237), + vec2(0.6372766, -2.7517915), + vec2(0.9282087, -2.4772763), + ], + vec![ + vec2(0.6979306, -3.504828), + vec2(1.0951718, -3.45793), + vec2(1.1420697, -3.8551712), + vec2(0.7448285, -3.9020689), + ], + vec![ + vec2(0.65383595, -4.3043094), + vec2(1.0156903, -4.133836), + vec2(1.1861644, -4.4956903), + vec2(0.82431006, -4.6661644), + ], + vec![ + vec2(1.9881046, 4.640967), + vec2(2.0809665, 4.2518954), + vec2(1.691895, 4.1590333), + vec2(1.599033, 4.5481043), + ], + vec![ + vec2(2.091941, 3.808552), + vec2(1.9685518, 3.4280586), + vec2(1.5880585, 3.5514479), + vec2(1.7114476, 3.931941), + ], + vec![ + vec2(1.5581572, 2.7837646), + vec2(1.8637643, 3.0418422), + vec2(2.1218421, 2.7362351), + vec2(1.8162353, 2.4781575), + ], + vec![ + vec2(2.081463, 1.9872934), + vec2(1.9872934, 1.5985364), + vec2(1.5985364, 1.6927061), + vec2(1.6927061, 2.081463), + ], + vec![ + vec2(1.8426138, 0.63716924), + vec2(1.5571691, 0.9173858), + vec2(1.8373858, 1.2028304), + vec2(2.1228304, 0.92261386), + ], + vec![ + vec2(1.7041372, 0.24807528), + vec2(2.0880752, 0.13586262), + vec2(1.9758623, -0.24807528), + vec2(1.5919245, -0.13586262), + ], + vec![ + vec2(1.8548687, -1.2024517), + vec2(1.557548, -0.934869), + vec2(1.8251308, -0.63754857), + vec2(2.1224513, -0.9051313), + ], + vec![ + vec2(2.1225505, -1.8528517), + vec2(1.8271476, -2.1225505), + vec2(1.5574491, -1.8271476), + vec2(1.8528517, -1.5574491), + ], + vec![ + vec2(1.7416242, -3.0251834), + vec2(1.5748163, -2.6616244), + vec2(1.9383751, -2.4948163), + vec2(2.1051831, -2.8583755), + ], + vec![ + vec2(2.0998917, -3.5683918), + vec2(1.9516072, -3.939891), + vec2(1.5801079, -3.791607), + vec2(1.7283921, -3.4201078), + ], + vec![ + vec2(1.5573889, -4.411449), + vec2(1.8285506, -4.1173887), + vec2(2.1226106, -4.3885508), + vec2(1.8514488, -4.682611), + ], + vec![ + vec2(3.0301287, 4.3161516), + vec2(2.6761518, 4.1298714), + vec2(2.4898713, 4.4838486), + vec2(2.843848, 4.670129), + ], + vec![ + vec2(2.9774394, 3.8608866), + vec2(2.9408867, 3.4625604), + vec2(2.54256, 3.4991133), + vec2(2.5791132, 3.8974397), + ], + vec![ + vec2(2.6968, 3.0356915), + vec2(3.0356915, 2.8231997), + vec2(2.8231997, 2.4843082), + vec2(2.4843082, 2.6968), + ], + vec![ + vec2(2.5042295, 1.7192457), + vec2(2.639246, 2.0957701), + vec2(3.0157704, 1.9607538), + vec2(2.880754, 1.5842294), + ], + vec![ + vec2(2.4821923, 0.97313017), + vec2(2.81313, 1.1978076), + vec2(3.0378075, 0.8668696), + vec2(2.7068696, 0.6421921), + ], + vec![ + vec2(2.7812557, 0.28204292), + vec2(3.0420427, -0.021255895), + vec2(2.738744, -0.28204292), + vec2(2.477957, 0.021255895), + ], + vec![ + vec2(2.8697863, -1.1806666), + vec2(2.4993336, -1.0297863), + vec2(2.6502137, -0.6593338), + vec2(3.0206664, -0.81021386), + ], + vec![ + vec2(2.531705, -2.0069773), + vec2(2.5930223, -1.6117051), + vec2(2.9882948, -1.6730222), + vec2(2.9269776, -2.0682945), + ], + vec![ + vec2(2.477169, -2.7574255), + vec2(2.7625742, -2.477169), + vec2(3.0428307, -2.7625742), + vec2(2.7574255, -3.0428307), + ], + vec![ + vec2(2.7293923, -3.3988175), + vec2(3.0411816, -3.6493917), + vec2(2.7906075, -3.9611812), + vec2(2.4788182, -3.710607), + ], + vec![ + vec2(2.8878596, -4.1477065), + vec2(3.012293, -4.5278597), + vec2(2.6321402, -4.6522937), + vec2(2.5077066, -4.2721405), + ], + vec![ + vec2(3.4877353, 4.6074476), + vec2(3.8874469, 4.5922637), + vec2(3.872264, 4.192552), + vec2(3.472552, 4.207736), + ], + vec![ + vec2(3.567413, 3.4205306), + vec2(3.4205303, 3.7925866), + vec2(3.792586, 3.9394693), + vec2(3.9394686, 3.5674133), + ], + vec![ + vec2(3.934355, 2.6362936), + vec2(3.5562932, 2.5056443), + vec2(3.425644, 2.8837059), + vec2(3.8037055, 3.0143557), + ], + vec![ + vec2(3.3973434, 1.8297321), + vec2(3.6697319, 2.122656), + vec2(3.9626558, 1.8502674), + vec2(3.690267, 1.5573434), + ], + vec![ + vec2(3.9493175, 1.0064168), + vec2(3.7664163, 0.650682), + vec2(3.4106817, 0.833583), + vec2(3.5935826, 1.1893176), + ], + vec![ + vec2(3.6335428, -0.27900138), + vec2(3.400998, 0.04645682), + vec2(3.7264564, 0.27900138), + vec2(3.959001, -0.04645682), + ], + vec![ + vec2(3.564062, -0.66201067), + vec2(3.9379888, -0.8040629), + vec2(3.7959366, -1.1779896), + vec2(3.4220102, -1.0359374), + ], + vec![ + vec2(3.4038944, -1.9013683), + vec2(3.618631, -1.5638949), + vec2(3.9561045, -1.7786312), + vec2(3.7413678, -2.1161046), + ], + vec![ + vec2(3.9628024, -2.7647529), + vec2(3.6752462, -3.0428028), + vec2(3.3971968, -2.7552469), + vec2(3.6847525, -2.4771972), + ], + vec![ + vec2(3.7649236, -3.410207), + vec2(3.949792, -3.7649236), + vec2(3.5950751, -3.949792), + vec2(3.410207, -3.5950751), + ], + vec![ + vec2(3.6979578, -4.117728), + vec2(3.9622717, -4.417958), + vec2(3.6620412, -4.6822715), + vec2(3.3977275, -4.382042), + ], + vec![ + vec2(4.118, 4.378175), + vec2(4.378175, 4.6819997), + vec2(4.6819997, 4.4218254), + vec2(4.4218254, 4.118), + ], + vec![ + vec2(4.5819893, 3.4634826), + vec2(4.1834826, 3.4980104), + vec2(4.2180104, 3.8965173), + vec2(4.6165175, 3.8619895), + ], + vec![ + vec2(4.4758363, 3.0324862), + vec2(4.6724863, 2.6841636), + vec2(4.324164, 2.4875135), + vec2(4.1275134, 2.8358362), + ], + vec![ + vec2(4.2744765, 1.5865362), + vec2(4.1465364, 1.9655235), + vec2(4.5255237, 2.0934634), + vec2(4.653464, 1.7144761), + ], + vec![ + vec2(4.662967, 1.024155), + vec2(4.504155, 0.65703267), + vec2(4.137033, 0.8158447), + vec2(4.2958446, 1.1829671), + ], + vec![ + vec2(4.134743, 0.098177366), + vec2(4.498177, 0.26525682), + vec2(4.665257, -0.098177366), + vec2(4.3018227, -0.26525682), + ], + vec![ + vec2(4.148867, -1.0501243), + vec2(4.269876, -0.6688673), + vec2(4.651133, -0.7898761), + vec2(4.5301237, -1.171133), + ], + vec![ + vec2(4.130434, -1.754359), + vec2(4.485641, -1.570434), + vec2(4.6695657, -1.9256405), + vec2(4.314359, -2.1095655), + ], + vec![ + vec2(4.427379, -3.0415144), + vec2(4.1184855, -2.787379), + vec2(4.3726206, -2.4784856), + vec2(4.6815147, -2.732621), + ], + vec![ + vec2(4.563257, -3.9109693), + vec2(4.1690307, -3.8432572), + vec2(4.2367425, -3.44903), + vec2(4.6309695, -3.5167418), + ], + vec![ + vec2(4.3327265, -4.125274), + vec2(4.6747255, -4.3327265), + vec2(4.4672737, -4.6747255), + vec2(4.125274, -4.4672737), + ], + vec![ + vec2(-3.5150332, 1.5162468), + vec2(-3.8845587, 1.6693836), + vec2(-3.731422, 2.038909), + vec2(-3.3618963, 1.8857723), + ], + vec![ + vec2(-0.84695613, 1.8264455), + vec2(-0.49091333, 2.0087461), + vec2(-0.30861288, 1.6527032), + vec2(-0.6646557, 1.4704027), + ], + vec![ + vec2(-3.6769612, 4.4442267), + vec2(-3.9120982, 4.1206365), + vec2(-4.235688, 4.355773), + vec2(-4.0005517, 4.6793637), + ], + vec![ + vec2(1.6671764, 4.1948338), + vec2(2.046261, 4.067182), + vec2(1.9186093, 3.6880972), + vec2(1.5395247, 3.815749), + ], + vec![ + vec2(-2.2387946, 2.816307), + vec2(-2.1361823, 2.4296925), + vec2(-2.5227969, 2.3270807), + vec2(-2.6254091, 2.7136948), + ], + vec![ + vec2(3.439594, -1.5301329), + vec2(3.1386585, -1.2666227), + vec2(3.402169, -0.965687), + vec2(3.7031047, -1.2291973), + ], + vec![ + vec2(0.035513967, -1.7485503), + vec2(0.3720012, -1.5322719), + vec2(0.5882796, -1.868759), + vec2(0.2517924, -2.0850377), + ], + vec![ + vec2(-2.8200495, -3.952715), + vec2(-2.5788922, -3.633586), + vec2(-2.2597635, -3.8747435), + vec2(-2.5009205, -4.1938725), + ], + vec![ + vec2(0.8458586, -1.3304079), + vec2(0.56510526, -1.6153245), + vec2(0.2801885, -1.3345711), + vec2(0.5609418, -1.0496545), + ], + vec![ + vec2(0.052798774, 0.18420385), + vec2(0.38818237, 0.4021897), + vec2(0.6061682, 0.06680607), + vec2(0.27078462, -0.15117975), + ], + vec![ + vec2(-4.681675, -4.0779963), + vec2(-4.425678, -3.7706442), + vec2(-4.1183248, -4.0266414), + vec2(-4.3743224, -4.333994), + ], + vec![ + vec2(-2.0561688, -2.0903986), + vec2(-1.6787479, -1.9579085), + vec2(-1.5462581, -2.3353293), + vec2(-1.9236789, -2.4678192), + ], + vec![ + vec2(-0.72201663, 2.6978326), + vec2(-0.33244365, 2.7885675), + vec2(-0.24170844, 2.398995), + vec2(-0.63128144, 2.3082597), + ], + vec![ + vec2(1.9792082, -3.4885156), + vec2(2.1107907, -3.1107776), + vec2(2.488529, -3.2423604), + vec2(2.3569462, -3.6200984), + ], + vec![ + vec2(2.268873, 0.503277), + vec2(2.4744108, 0.16012368), + vec2(2.1312573, -0.04541415), + vec2(1.9257195, 0.29773918), + ], + vec![ + vec2(2.3676, 4.499037), + vec2(2.6144915, 4.1843233), + vec2(2.2997782, 3.9374313), + vec2(2.0528867, 4.2521443), + ], + vec![ + vec2(-2.002075, 2.216849), + vec2(-1.9779172, 1.8175794), + vec2(-2.377187, 1.7934217), + vec2(-2.4013445, 2.1926913), + ], + vec![ + vec2(-2.898599, 1.5674753), + vec2(-3.2985418, 1.5606971), + vec2(-3.30532, 1.9606398), + vec2(-2.9053774, 1.9674181), + ], + vec![ + vec2(-3.6658778, 3.7377105), + vec2(-3.278858, 3.636639), + vec2(-3.379929, 3.249619), + vec2(-3.7669494, 3.3506906), + ], + vec![ + vec2(-3.4791856, -0.19036616), + vec2(-3.737217, -0.49601272), + vec2(-4.0428634, -0.2379814), + vec2(-3.784832, 0.06766516), + ], + vec![ + vec2(2.028548, -0.22697431), + vec2(2.4241495, -0.28612867), + vec2(2.3649952, -0.6817304), + vec2(1.9693934, -0.62257606), + ], + vec![ + vec2(2.7216203, -3.5814712), + vec2(2.4826834, -3.9022653), + vec2(2.161889, -3.6633282), + vec2(2.400826, -3.342534), + ], + vec![ + vec2(-1.6055247, -3.761999), + vec2(-1.9850434, -3.8883543), + vec2(-2.1113985, -3.5088356), + vec2(-1.7318797, -3.3824804), + ], + vec![ + vec2(-1.1461321, 3.5126424), + vec2(-0.76023304, 3.4073713), + vec2(-0.86550367, 3.0214725), + vec2(-1.2514027, 3.126743), + ], + vec![ + vec2(4.27322, 4.180889), + vec2(4.6528378, 4.054831), + vec2(4.5267797, 3.6752138), + vec2(4.147162, 3.801271), + ], + vec![ + vec2(-2.559426, 0.90662664), + vec2(-2.8736513, 0.6591137), + vec2(-3.1211643, 0.97333854), + vec2(-2.8069394, 1.2208517), + ], + vec![ + vec2(1.7154748, -3.1478624), + vec2(2.1107044, -3.2094553), + vec2(2.0491114, -3.6046846), + vec2(1.6538819, -3.543092), + ], + vec![ + vec2(1.4003272, -3.805389), + vec2(1.7493309, -4.000828), + vec2(1.5538915, -4.349832), + vec2(1.204888, -4.1543927), + ], + vec![ + vec2(4.181054, 4.220939), + vec2(4.220939, 4.618946), + vec2(4.618946, 4.5790606), + vec2(4.5790606, 4.181054), + ], + vec![ + vec2(2.223229, 2.6019614), + vec2(2.6023645, 2.4744616), + vec2(2.4748645, 2.0953264), + vec2(2.0957286, 2.222826), + ], + vec![ + vec2(-3.3142784, -1.1612484), + vec2(-3.1989467, -0.778236), + vec2(-2.8159342, -0.89356774), + vec2(-2.931266, -1.2765801), + ], + vec![ + vec2(-3.375918, -4.0279417), + vec2(-3.1834671, -4.378601), + vec2(-3.5341275, -4.5710526), + vec2(-3.7265785, -4.2203927), + ], + vec![ + vec2(-0.018120548, -4.2959514), + vec2(-0.34451056, -4.0647163), + vec2(-0.113275744, -3.7383263), + vec2(0.21311429, -3.969561), + ], + vec![ + vec2(3.4660833, 2.2862937), + vec2(3.864601, 2.2518883), + vec2(3.8301952, 1.8533707), + vec2(3.431678, 1.8877761), + ], + vec![ + vec2(4.307914, 1.169636), + vec2(4.0204782, 1.4478099), + vec2(4.2986526, 1.7352453), + vec2(4.5860877, 1.4570713), + ], + vec![ + vec2(4.155402, -2.1009412), + vec2(3.8325589, -2.3371027), + vec2(3.5963972, -2.0142598), + vec2(3.9192405, -1.7780981), + ], + vec![ + vec2(-2.7641213, -4.0451703), + vec2(-2.8033822, -3.6471024), + vec2(-2.4053137, -3.6078413), + vec2(-2.3660526, -4.00591), + ], + vec![ + vec2(-0.024371505, -1.5055562), + vec2(0.036052406, -1.9009663), + vec2(-0.35935748, -1.9613903), + vec2(-0.4197814, -1.5659803), + ], + vec![ + vec2(2.6928153, 1.2868178), + vec2(2.574551, 0.90470046), + vec2(2.1924338, 1.0229647), + vec2(2.3106978, 1.4050819), + ], + vec![ + vec2(1.6961488, 0.5137852), + vec2(2.0715587, 0.65186983), + vec2(2.2096431, 0.27645987), + vec2(1.8342334, 0.13837521), + ], + vec![ + vec2(2.623683, 4.256034), + vec2(3.002729, 4.3838), + vec2(3.1304948, 4.004754), + vec2(2.751449, 3.8769877), + ], + vec![ + vec2(4.118722, -3.6192436), + vec2(4.4297066, -3.3676717), + vec2(4.681278, -3.6786563), + vec2(4.370293, -3.9302282), + ], + vec![ + vec2(1.3311435, -1.1307809), + vec2(1.0249426, -0.8734076), + vec2(1.2823159, -0.5672067), + vec2(1.5885168, -0.8245799), + ], + vec![ + vec2(1.5911984, 1.0867586), + vec2(1.5489167, 1.4845177), + vec2(1.9466758, 1.5267996), + vec2(1.9889574, 1.1290405), + ], + vec![ + vec2(1.9633765, -4.1145453), + vec2(1.8822151, -3.7228653), + vec2(2.2738948, -3.641704), + vec2(2.355056, -4.033384), + ], + vec![ + vec2(-2.6730902, -2.7919335), + vec2(-2.406983, -2.4932916), + vec2(-2.108341, -2.7593987), + vec2(-2.3744483, -3.0580409), + ], + vec![ + vec2(-0.9259661, -4.0762806), + vec2(-0.77038425, -4.4447837), + vec2(-1.1388869, -4.6003656), + vec2(-1.2944689, -4.2318625), + ], + vec![ + vec2(3.3316753, -2.7265093), + vec2(3.1944556, -2.3507822), + vec2(3.5701826, -2.2135627), + vec2(3.7074022, -2.5892897), + ], + vec![ + vec2(-1.6701653, -0.6678227), + vec2(-1.6632051, -0.26788327), + vec2(-1.2632657, -0.27484334), + vec2(-1.2702259, -0.67478275), + ], + vec![ + vec2(0.8095447, 3.4134054), + vec2(0.46816865, 3.621882), + vec2(0.67664516, 3.9632576), + vec2(1.018021, 3.754781), + ], + vec![ + vec2(1.3344805, -3.751489), + vec2(1.3600299, -3.3523057), + vec2(1.7592131, -3.377855), + vec2(1.7336637, -3.7770383), + ], + vec![ + vec2(-0.20239033, 2.449249), + vec2(-0.21821077, 2.848936), + vec2(0.18147624, 2.8647563), + vec2(0.19729668, 2.465069), + ], + vec![ + vec2(2.9816794, -2.940067), + vec2(2.7907808, -2.5885592), + vec2(3.1422882, -2.3976603), + vec2(3.333187, -2.7491682), + ], + vec![ + vec2(-4.5001493, 3.0226138), + vec2(-4.627337, 3.4018543), + vec2(-4.248097, 3.5290418), + vec2(-4.120909, 3.1498015), + ], + vec![ + vec2(-0.24229676, 0.6416171), + vec2(-0.5006157, 0.33621365), + vec2(-0.8060192, 0.5945326), + vec2(-0.5477003, 0.8999361), + ], + vec![ + vec2(2.3512564, -1.0494084), + vec2(2.7458296, -1.1150758), + vec2(2.680162, -1.5096487), + vec2(2.2855892, -1.4439814), + ], + vec![ + vec2(-2.4360368, -4.4638944), + vec2(-2.7754624, -4.6755314), + vec2(-2.9870992, -4.336106), + vec2(-2.6476738, -4.124469), + ], + vec![ + vec2(3.0562267, -1.6828562), + vec2(3.3959877, -1.471758), + vec2(3.607086, -1.8115189), + vec2(3.2673252, -2.0226173), + ], + vec![ + vec2(-0.7033755, -2.567961), + vec2(-1.0724094, -2.722279), + vec2(-1.2267271, -2.353245), + vec2(-0.8576933, -2.1989274), + ], + vec![ + vec2(4.4166813, -1.5235447), + vec2(4.270859, -1.8960171), + vec2(3.8983865, -1.7501942), + vec2(4.044209, -1.3777217), + ], + vec![ + vec2(-4.2460012, 3.9092233), + vec2(-4.1181183, 4.2882295), + vec2(-3.7391117, 4.1603465), + vec2(-3.8669949, 3.7813396), + ], + vec![ + vec2(1.0434484, -3.924111), + vec2(0.83951026, -3.5800045), + vec2(1.1836166, -3.3760664), + vec2(1.3875548, -3.720173), + ], + vec![ + vec2(-1.7612346, -0.19883052), + vec2(-1.7492812, -0.5986518), + vec2(-2.1491027, -0.6106053), + vec2(-2.161056, -0.21078393), + ], + vec![ + vec2(-4.102183, 0.8988698), + vec2(-4.352711, 1.210696), + vec2(-4.0408845, 1.4612243), + vec2(-3.7903566, 1.1493979), + ], + vec![ + vec2(-4.072771, 1.7785612), + vec2(-3.803393, 2.0742557), + vec2(-3.507698, 1.804877), + vec2(-3.7770767, 1.5091827), + ], + vec![ + vec2(0.33374876, 4.3002305), + vec2(0.37842906, 3.9027338), + vec2(-0.019067718, 3.8580537), + vec2(-0.06374799, 4.2555504), + ], + vec![ + vec2(-0.5611257, -0.789984), + vec2(-0.41760278, -0.41661927), + vec2(-0.04423809, -0.5601423), + vec2(-0.18776107, -0.9335069), + ], + vec![ + vec2(2.5657632, 2.6364577), + vec2(2.8314123, 2.935507), + vec2(3.130462, 2.6698577), + vec2(2.8648126, 2.3708081), + ], + vec![ + vec2(-3.9313865, 3.9336827), + vec2(-3.7208912, 3.5935478), + vec2(-4.0610266, 3.3830526), + vec2(-4.271521, 3.7231874), + ], + vec![ + vec2(3.3961515, -4.529219), + vec2(3.518532, -4.1484003), + vec2(3.899351, -4.270781), + vec2(3.7769701, -4.6515994), + ], + vec![ + vec2(1.1684326, 1.8706946), + vec2(1.2850312, 1.4880657), + vec2(0.90240246, 1.371467), + vec2(0.78580385, 1.7540958), + ], + vec![ + vec2(3.8783748, -2.655234), + vec2(4.265663, -2.5551949), + vec2(4.365702, -2.9424832), + vec2(3.9784136, -3.042522), + ], + vec![ + vec2(-3.6924844, -4.332816), + vec2(-3.9000487, -4.6747475), + vec2(-4.24198, -4.4671836), + vec2(-4.0344157, -4.1252522), + ], + vec![ + vec2(-2.001854, 3.2675118), + vec2(-1.7280954, 2.9758682), + vec2(-2.0197394, 2.7021093), + vec2(-2.293498, 2.9937532), + ], + vec![ + vec2(-0.7142694, -3.285861), + vec2(-0.99460095, -3.0005293), + vec2(-0.7092692, -2.7201974), + vec2(-0.42893764, -3.0055292), + ], + vec![ + vec2(2.9745681, 3.0028448), + vec2(3.3736775, 2.9761686), + vec2(3.3470013, 2.5770595), + vec2(2.9478917, 2.6037357), + ], + vec![ + vec2(1.9226195, -2.4180276), + vec2(2.3164823, -2.3482265), + vec2(2.3862832, -2.7420895), + vec2(1.9924204, -2.8118904), + ], + vec![ + vec2(2.6112053, -1.086945), + vec2(2.7204742, -0.70215887), + vec2(3.1052604, -0.81142753), + vec2(2.9959915, -1.1962137), + ], + vec![ + vec2(-0.5853797, 3.226305), + vec2(-0.9313953, 3.025623), + vec2(-1.1320771, 3.371639), + vec2(-0.78606147, 3.572321), + ], + vec![ + vec2(4.2018204, 2.9194832), + vec2(3.9100983, 3.1931584), + vec2(4.183774, 3.4848804), + vec2(4.4754953, 3.2112048), + ], + vec![ + vec2(2.5392964, 1.0357101), + vec2(2.931117, 0.95523244), + vec2(2.8506398, 0.56341195), + vec2(2.4588192, 0.64388955), + ], + vec![ + vec2(0.016501606, 0.6112583), + vec2(-0.362275, 0.4826961), + vec2(-0.49083725, 0.8614727), + vec2(-0.11206066, 0.99003494), + ], + vec![ + vec2(2.661672, -2.0251331), + vec2(2.7427993, -2.4168198), + vec2(2.3511126, -2.4979467), + vec2(2.2699857, -2.10626), + ], + vec![ + vec2(-0.23420843, -3.9337575), + vec2(-0.6294689, -3.9951513), + vec2(-0.6908623, -3.5998907), + vec2(-0.29560181, -3.538497), + ], + vec![ + vec2(-1.6506042, -0.6596654), + vec2(-1.3863161, -0.3594126), + vec2(-1.0860633, -0.6237008), + vec2(-1.3503516, -0.9239536), + ], + vec![ + vec2(-2.906919, 0.6128648), + vec2(-2.6844432, 0.28044257), + vec2(-3.0168657, 0.05796686), + vec2(-3.2393413, 0.39038908), + ], + vec![ + vec2(-1.1037694, 0.7719937), + vec2(-0.7271632, 0.6372062), + vec2(-0.86195064, 0.2605999), + vec2(-1.238557, 0.39538747), + ], + vec![ + vec2(2.2328417, -0.11027161), + vec2(2.4886782, 0.19721441), + vec2(2.7961643, -0.058622193), + vec2(2.5403278, -0.3661082), + ], + vec![ + vec2(-2.4285138, -4.0629616), + vec2(-2.5812924, -4.4326353), + vec2(-2.9509661, -4.2798567), + vec2(-2.7981875, -3.910183), + ], + vec![ + vec2(-4.377455, 2.515392), + vec2(-3.977455, 2.515331), + vec2(-3.9775157, 2.1153314), + vec2(-4.377516, 2.1153922), + ], + vec![ + vec2(0.86034167, -1.2785602), + vec2(0.5971378, -1.579764), + vec2(0.29593405, -1.3165601), + vec2(0.55913794, -1.0153564), + ], + vec![ + vec2(-0.9588823, 3.1817734), + vec2(-1.3546844, 3.1239738), + vec2(-1.4124837, 3.5197759), + vec2(-1.0166816, 3.5775752), + ], + vec![ + vec2(-1.2916353, -3.0243657), + vec2(-1.4458708, -2.6552975), + vec2(-1.0768025, -2.501062), + vec2(-0.922567, -2.8701303), + ], + vec![ + vec2(-3.8740246, -1.22484), + vec2(-4.070707, -1.5731449), + vec2(-4.419011, -1.3764628), + vec2(-4.2223296, -1.0281582), + ], + vec![ + vec2(2.3663282, 2.1620064), + vec2(2.140607, 1.8317789), + vec2(1.8103799, 2.0575), + vec2(2.0361006, 2.3877273), + ], + vec![ + vec2(-1.6043513, -0.5271133), + vec2(-1.9524715, -0.3301048), + vec2(-1.7554628, 0.018015325), + vec2(-1.4073426, -0.17899325), + ], + vec![ + vec2(-3.1294487, -1.4113996), + vec2(-2.7405066, -1.3179954), + vec2(-2.6471026, -1.7069371), + vec2(-3.0360441, -1.8003412), + ], + vec![ + vec2(-0.06702503, 2.0077152), + vec2(0.011278748, 2.3999758), + vec2(0.4035395, 2.321672), + vec2(0.32523572, 1.9294112), + ], + vec![ + vec2(4.3478785, 3.6414893), + vec2(4.1653295, 3.2855737), + vec2(3.809414, 3.4681227), + vec2(3.9919627, 3.8240385), + ], + vec![ + vec2(2.2500658, -2.278749), + vec2(2.4453342, -2.6278481), + vec2(2.0962353, -2.8231168), + vec2(1.9009666, -2.4740176), + ], + vec![ + vec2(1.3886787, 2.8374543), + vec2(1.3333963, 3.2336154), + vec2(1.7295578, 3.288898), + vec2(1.7848401, 2.8927364), + ], + vec![ + vec2(3.3289957, -1.1572955), + vec2(3.7276554, -1.1900105), + vec2(3.6949403, -1.5886705), + vec2(3.2962804, -1.5559554), + ], + vec![ + vec2(2.7721572, 0.8132945), + vec2(2.8369381, 1.208014), + vec2(3.2316575, 1.1432332), + vec2(3.1668763, 0.7485137), + ], + vec![ + vec2(1.2092078, -0.5468887), + vec2(1.1311216, -0.15458463), + vec2(1.5234258, -0.07649855), + vec2(1.601512, -0.46880266), + ], + vec![ + vec2(-3.1647396, -0.88782024), + vec2(-3.558305, -0.9592791), + vec2(-3.6297638, -0.5657139), + vec2(-3.2361984, -0.49425495), + ], + vec![ + vec2(1.7434317, 3.7476957), + vec2(1.4804827, 3.4462695), + vec2(1.1790564, 3.709219), + vec2(1.4420055, 4.010645), + ], + vec![ + vec2(2.2508903, -2.0424201), + vec2(1.9212081, -1.8159039), + vec2(2.1477244, -1.4862214), + vec2(2.4774067, -1.7127378), + ], + vec![ + vec2(0.9017378, -1.4739388), + vec2(0.77897733, -1.0932423), + vec2(1.1596739, -0.9704818), + vec2(1.2824345, -1.3511784), + ], + vec![ + vec2(-3.6082106, 1.7456683), + vec2(-3.2153556, 1.820936), + vec2(-3.1400878, 1.4280815), + vec2(-3.5329428, 1.3528137), + ], + vec![ + vec2(-3.8245897, -2.6074111), + vec2(-3.4447708, -2.732862), + vec2(-3.5702217, -3.1126807), + vec2(-3.9500403, -2.9872296), + ], + vec![ + vec2(0.5273855, -1.4845475), + vec2(0.7897888, -1.182646), + vec2(1.0916903, -1.4450494), + vec2(0.82928693, -1.7469507), + ], + vec![ + vec2(4.104112, -3.8416586), + vec2(3.7080388, -3.7857459), + vec2(3.7639518, -3.389673), + vec2(4.160025, -3.4455857), + ], + vec![ + vec2(2.214073, 0.7610699), + vec2(2.412146, 0.41355452), + vec2(2.0646305, 0.21548113), + vec2(1.8665575, 0.5629965), + ], + vec![ + vec2(1.3554491, 1.9471403), + vec2(1.4285458, 2.3404047), + vec2(1.8218101, 2.267308), + vec2(1.7487135, 1.8740436), + ], + vec![ + vec2(-2.39153, -3.2586439), + vec2(-2.2486553, -3.6322575), + vec2(-2.6222687, -3.775132), + vec2(-2.7651432, -3.4015186), + ], + vec![ + vec2(2.5025706, 1.3170445), + vec2(2.8986342, 1.2610664), + vec2(2.8426566, 0.8650029), + vec2(2.4465926, 0.92098075), + ], + vec![ + vec2(4.4588747, -3.8780866), + vec2(4.0956473, -3.710558), + vec2(4.263176, -3.3473303), + vec2(4.6264033, -3.514859), + ], + vec![ + vec2(2.2490873, -3.1018465), + vec2(1.8922087, -3.2825055), + vec2(1.7115498, -2.9256268), + vec2(2.0684283, -2.744968), + ], + vec![ + vec2(3.5703475, 2.8030298), + vec2(3.8843648, 3.0508063), + vec2(4.132141, 2.736789), + vec2(3.818124, 2.4890125), + ], + vec![ + vec2(-1.0475037, -2.437724), + vec2(-0.86449003, -2.7934008), + vec2(-1.2201668, -2.9764144), + vec2(-1.4031806, -2.6207378), + ], + vec![ + vec2(4.533532, 3.6290996), + vec2(4.387495, 3.2567112), + vec2(4.015106, 3.4027483), + vec2(4.1611433, 3.7751367), + ], + vec![ + vec2(-0.23522753, 1.3622632), + vec2(-0.58639526, 1.5537868), + vec2(-0.39487174, 1.9049544), + vec2(-0.04370406, 1.7134309), + ], + vec![ + vec2(2.9785063, -3.1797025), + vec2(3.111923, -2.802608), + vec2(3.4890172, -2.936025), + vec2(3.3556006, -3.3131192), + ], + vec![ + vec2(-2.420229, -2.7211292), + vec2(-2.5456872, -2.3413131), + vec2(-2.1658711, -2.215855), + vec2(-2.040413, -2.5956707), + ], + vec![ + vec2(-3.0654373, -0.23127693), + vec2(-3.4420164, -0.36614066), + vec2(-3.5768802, 0.0104383975), + vec2(-3.2003012, 0.14530212), + ], + vec![ + vec2(1.0580047, -0.95849854), + vec2(1.4260973, -1.1150488), + vec2(1.2695471, -1.4831413), + vec2(0.90145457, -1.3265911), + ], + vec![ + vec2(2.835532, -1.8119024), + vec2(3.2204542, -1.7031138), + vec2(3.3292425, -2.0880358), + vec2(2.9443204, -2.1968246), + ], + vec![ + vec2(-0.7421962, 3.3487377), + vec2(-0.9005469, 3.7160592), + vec2(-0.5332254, 3.87441), + vec2(-0.3748747, 3.5070884), + ], + vec![ + vec2(4.284425, 0.2660268), + vec2(4.6001925, 0.020484915), + vec2(4.3546505, -0.29528266), + vec2(4.0388827, -0.049740784), + ], + vec![ + vec2(-0.31201565, 4.018868), + vec2(-0.25097322, 4.414183), + vec2(0.14434159, 4.3531404), + vec2(0.08329914, 3.9578257), + ], + vec![ + vec2(1.5382829, 4.2111964), + vec2(1.9344722, 4.1561136), + vec2(1.87939, 3.7599247), + vec2(1.4832007, 3.8150072), + ], + vec![ + vec2(-0.19826482, 1.9264033), + vec2(0.08303911, 2.2107766), + vec2(0.36741233, 1.9294726), + vec2(0.08610837, 1.6450994), + ], + vec![ + vec2(-0.26971877, 3.7154288), + vec2(-0.6684065, 3.7478037), + vec2(-0.6360315, 4.1464915), + vec2(-0.2373438, 4.1141167), + ], + vec![ + vec2(-0.63075006, 2.0381746), + vec2(-0.77693963, 1.6658459), + vec2(-1.1492683, 1.8120354), + vec2(-1.0030786, 2.1843643), + ], + vec![ + vec2(0.002819687, 2.3339512), + vec2(-0.1319337, 1.9573326), + vec2(-0.5085522, 2.092086), + vec2(-0.3737988, 2.4687045), + ], + vec![ + vec2(0.23268521, 0.66436905), + vec2(0.6322293, 0.683461), + vec2(0.6513213, 0.28391695), + vec2(0.25177714, 0.264825), + ], + vec![ + vec2(0.25033614, -2.962078), + vec2(0.5989675, -3.1581807), + vec2(0.4028649, -3.5068119), + vec2(0.05423361, -3.3107095), + ], + vec![ + vec2(1.9291582, -0.13998222), + vec2(1.5691465, -0.31431434), + vec2(1.3948145, 0.045697205), + vec2(1.754826, 0.22002932), + ], + vec![ + vec2(1.9728415, 3.5470345), + vec2(1.5793806, 3.6190662), + vec2(1.6514126, 4.0125275), + vec2(2.0448732, 3.9404953), + ], + vec![ + vec2(-1.7771595, 3.7097204), + vec2(-2.152066, 3.8491657), + vec2(-2.012621, 4.2240725), + vec2(-1.6377144, 4.084627), + ], + vec![ + vec2(0.8546944, -0.25843418), + vec2(1.2359363, -0.1373778), + vec2(1.3569927, -0.51861966), + vec2(0.9757508, -0.63967603), + ], + vec![ + vec2(2.4020236, -2.987236), + vec2(2.2313104, -3.3489778), + vec2(1.8695686, -3.1782644), + vec2(2.0402818, -2.8165228), + ], + vec![ + vec2(2.8845232, -3.3224623), + vec2(3.2648547, -3.198576), + vec2(3.3887415, -3.5789073), + vec2(3.00841, -3.702794), + ], + vec![ + vec2(3.261488, 3.91493), + vec2(3.4112732, 4.2858267), + vec2(3.7821698, 4.136042), + vec2(3.632385, 3.7651448), + ], + vec![ + vec2(2.3899553, -1.402079), + vec2(2.0459905, -1.1979026), + vec2(2.2501667, -0.8539376), + vec2(2.594132, -1.0581139), + ], + vec![ + vec2(-1.3158509, -1.6491333), + vec2(-1.1006925, -1.9863378), + vec2(-1.4378968, -2.2014964), + vec2(-1.6530553, -1.8642918), + ], + vec![ + vec2(-2.9889169, -3.9328153), + vec2(-2.7498817, -4.253536), + vec2(-3.070603, -4.492572), + vec2(-3.3096378, -4.17185), + ], + vec![ + vec2(3.9298162, -3.7948089), + vec2(4.2996926, -3.6425207), + vec2(4.45198, -4.0123973), + vec2(4.0821037, -4.1646852), + ], + vec![ + vec2(-2.8788252, 4.1217346), + vec2(-2.6741412, 4.465398), + vec2(-2.330478, 4.2607136), + vec2(-2.535162, 3.9170501), + ], + vec![ + vec2(3.374551, 2.036242), + vec2(3.7520986, 2.1683702), + vec2(3.8842273, 1.790823), + vec2(3.5066798, 1.6586944), + ], + vec![ + vec2(3.2406218, -1.7795225), + vec2(2.9155345, -1.5464603), + vec2(3.1485972, -1.2213728), + vec2(3.4736845, -1.4544351), + ], + vec![ + vec2(-3.998845, -3.0502574), + vec2(-4.3780212, -2.9228785), + vec2(-4.250643, -2.5437024), + vec2(-3.8714662, -2.6710808), + ], + vec![ + vec2(3.7402084, 2.3001368), + vec2(3.459676, 2.585271), + vec2(3.74481, 2.8658035), + vec2(4.025343, 2.5806696), + ], + vec![ + vec2(-3.2102606, 3.0372488), + vec2(-3.2400804, 2.6383622), + vec2(-3.6389673, 2.6681817), + vec2(-3.6091475, 3.0670686), + ], + vec![ + vec2(4.337696, -3.2055826), + vec2(4.675895, -3.4191742), + vec2(4.462304, -3.7573736), + vec2(4.124105, -3.5437822), + ], + vec![ + vec2(1.5170972, -4.1187043), + vec2(1.8279334, -4.3704596), + vec2(1.5761778, -4.6812954), + vec2(1.2653416, -4.4295406), + ], + vec![ + vec2(4.033746, -3.7101707), + vec2(3.7096317, -3.9445848), + vec2(3.4752173, -3.6204705), + vec2(3.7993317, -3.3860564), + ], + vec![ + vec2(4.672353, 3.9223657), + vec2(4.323686, 3.7263262), + vec2(4.127647, 4.074993), + vec2(4.4763136, 4.271033), + ], + vec![ + vec2(0.23392914, -1.4729688), + vec2(-0.06686239, -1.7366437), + vec2(-0.33053732, -1.4358523), + vec2(-0.029745772, -1.1721773), + ], + vec![ + vec2(2.8173628, 2.0093107), + vec2(3.1417387, 2.2433624), + vec2(3.3757906, 1.9189864), + vec2(3.0514143, 1.6849345), + ], + vec![ + vec2(3.9131753, 1.8646393), + vec2(4.1242166, 2.2044358), + vec2(4.464013, 1.9933952), + vec2(4.252972, 1.6535985), + ], + vec![ + vec2(2.0805779, 0.967355), + vec2(2.4776733, 1.0154736), + vec2(2.525792, 0.61837834), + vec2(2.1286967, 0.5702598), + ], + vec![ + vec2(0.59528774, 0.17733029), + vec2(0.63643533, -0.22054769), + vec2(0.23855731, -0.2616952), + vec2(0.19740981, 0.1361828), + ], + vec![ + vec2(4.4299984, -2.14759), + vec2(4.148588, -2.4318583), + vec2(3.86432, -2.1504486), + vec2(4.1457295, -1.8661802), + ], + vec![ + vec2(-3.884689, 3.0713224), + vec2(-4.268665, 2.9592385), + vec2(-4.3807487, 3.343214), + vec2(-3.996773, 3.4552977), + ], + vec![ + vec2(1.1660812, 3.189234), + vec2(0.8165291, 2.9947777), + vec2(0.6220724, 3.3443298), + vec2(0.97162443, 3.5387862), + ], + vec![ + vec2(2.5958276, -1.5515352), + vec2(2.9624085, -1.3914785), + vec2(3.1224654, -1.7580599), + vec2(2.7558842, -1.9181166), + ], + vec![ + vec2(-1.9623736, 2.4449158), + vec2(-1.6250243, 2.2299845), + vec2(-1.8399559, 1.8926352), + vec2(-2.177305, 2.1075664), + ], + vec![ + vec2(1.4817696, 1.1946073), + vec2(1.086514, 1.1331816), + vec2(1.0250883, 1.528437), + vec2(1.4203439, 1.5898627), + ], + vec![ + vec2(1.6650318, -1.1029725), + vec2(2.0453405, -1.2269297), + vec2(1.9213833, -1.6072382), + vec2(1.5410748, -1.4832811), + ], + vec![ + vec2(0.7905762, 3.5384831), + vec2(0.461371, 3.3112743), + vec2(0.23416203, 3.6404796), + vec2(0.5633673, 3.8676884), + ], + vec![ + vec2(-3.4068162, 0.0540159), + vec2(-3.0090744, 0.09645831), + vec2(-2.9666324, -0.30128363), + vec2(-3.3643742, -0.34372604), + ], + vec![ + vec2(4.333241, 3.6467104), + vec2(4.125149, 3.9883204), + vec2(4.4667587, 4.196413), + vec2(4.674851, 3.8548036), + ], + vec![ + vec2(1.44738, 3.6965122), + vec2(1.1909692, 3.389505), + vec2(0.8839618, 3.6459155), + vec2(1.1403725, 3.9529228), + ], + vec![ + vec2(-2.4577372, -1.9219222), + vec2(-2.1057959, -2.1120207), + vec2(-2.2958941, -2.463962), + vec2(-2.6478355, -2.2738633), + ], + vec![ + vec2(-3.2051764, 0.19755654), + vec2(-2.8483112, 0.016870394), + vec2(-3.0289972, -0.33999446), + vec2(-3.3858624, -0.15930831), + ], + vec![ + vec2(-4.1301947, 2.2054644), + vec2(-4.5132127, 2.0901506), + vec2(-4.628526, 2.4731684), + vec2(-4.2455087, 2.5884821), + ], + vec![ + vec2(1.6151105, -2.8370898), + vec2(1.5588076, -2.441072), + vec2(1.954825, -2.3847692), + vec2(2.011128, -2.7807868), + ], + vec![ + vec2(-3.6252747, 4.1172156), + vec2(-3.9137933, 4.3942657), + vec2(-3.6367433, 4.6827846), + vec2(-3.3482244, 4.4057345), + ], + vec![ + vec2(3.1491888, 2.8123102), + vec2(3.297538, 2.4408367), + vec2(2.9260645, 2.2924879), + vec2(2.7777152, 2.6639614), + ], + ]); + triangulation +} + +fn merger_many_overlapping(c: &mut Criterion) { + c.bench_function(&"merger many overlapping".to_string(), |b| { + b.iter(|| { + let mut triangulation = random_with_many_obstacles(); + triangulation.merge_overlapping_obstacles(); + let mut mesh: Mesh = triangulation.as_navmesh().unwrap(); + while mesh.merge_polygons() {} + black_box(mesh); + }) + }); +} + +criterion_group!(benches, merger, merger_many_overlapping); +criterion_main!(benches); diff --git a/src/lib.rs b/src/lib.rs index e68bfe3..e897804 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ mod async_helpers; mod helpers; mod input; mod instance; +mod merger; mod primitives; #[cfg(feature = "async")] diff --git a/src/merger.rs b/src/merger.rs new file mode 100644 index 0000000..686eaa5 --- /dev/null +++ b/src/merger.rs @@ -0,0 +1,303 @@ +use geo::IsConvex; +use hashbrown::HashMap; +#[cfg(feature = "tracing")] +use tracing::instrument; + +use crate::Mesh; + +impl Mesh { + /// Merge polygons. + /// + /// This merge neighbouring polygons when possible, keeping them convex. + #[cfg_attr(feature = "tracing", instrument(skip_all))] + pub fn merge_polygons(&mut self) -> bool { + // println!("merge_polygons"); + self.unbake(); + let mut area = self + .polygons + .iter() + .enumerate() + .map(|(i, poly)| (i, poly.area(self))) + .collect::>(); + let mut union_polygons = UnionFind::new(self.polygons.len() as i32); + + area.sort_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap().reverse()); + + for (poly_index, _area) in area.iter() { + // println!("poly_index: {}", poly_index); + if union_polygons.find(*poly_index as i32) != *poly_index as i32 { + // println!(" already merged"); + // already merged + continue; + } + let poly = self.polygons[*poly_index].clone(); + for edge in poly.edges_index() { + let start = if let Some(v) = self.vertices.get(edge.0 as usize) { + v + } else { + continue; + }; + let end = if let Some(v) = self.vertices.get(edge.1 as usize) { + v + } else { + continue; + }; + let other_side = *start + .polygons + .iter() + .find(|i| **i != -1 && **i != *poly_index as isize && end.polygons.contains(*i)) + .unwrap_or(&-1); + if other_side == -1 { + // nothing on the other side + continue; + } + if union_polygons.find(other_side as i32) != other_side as i32 { + // already merged + continue; + } + // println!(" edge {:?} -> {}", edge, other_side); + + let mut joined_vertices = vec![]; + let mut start = false; + for i in poly.vertices.iter().chain(poly.vertices.iter()) { + if *i == edge.1 { + start = true; + } + if !start { + continue; + } + if *i == edge.0 { + break; + } + joined_vertices.push(*i); + } + start = false; + let other_vertices = self.polygons[other_side as usize].vertices.clone(); + // let other_vertices = &self.polygons[other_side as usize].vertices; + for i in other_vertices.iter().chain(other_vertices.iter()) { + if *i == edge.0 { + start = true; + } + if !start { + continue; + } + if *i == edge.1 { + break; + } + joined_vertices.push(*i); + } + let mut line = geo::LineString( + joined_vertices + .iter() + .map(|i| { + let c = self.vertices[*i as usize].coords; + geo::Coord::from((c.x, c.y)) + }) + .collect(), + ); + line.close(); + if line.is_convex() { + union_polygons.union(*poly_index as i32, other_side as i32); + self.polygons[*poly_index].vertices = joined_vertices; + // println!(" merged"); + break; + } else { + // println!(" not convex"); + } + } + } + + let mut new_indexes: HashMap = HashMap::new(); + let mut kept = 0; + // println!( + // "union: {:?}", + // union_polygons.parent.iter().enumerate().collect::>() + // ); + for i in 0..union_polygons.parent.len() { + union_polygons.find(i as i32); + } + // println!( + // "union-bis: {:?}", + // union_polygons.parent.iter().enumerate().collect::>() + // ); + for (i, p) in union_polygons.parent.iter().enumerate() { + // println!("poly {} -> {}", i, p); + if !new_indexes.contains_key(p) { + new_indexes.insert(*p, kept); + // println!(" -> {}", kept); + kept += 1; + } + + if i as i32 == *p { + let j = *new_indexes.get(p).unwrap() as usize; + if i != j { + self.polygons.swap(i, j); + } + } else { + new_indexes.insert(i as i32, *new_indexes.get(p).unwrap()); + } + // println!(" -> {}", new_indexes.get(p).unwrap()); + } + self.polygons.resize_with(kept as usize, || unreachable!()); + // for (i, p) in union_polygons.parent.iter().enumerate().rev() { + // if i as i32 != *p { + // self.polygons.remove(i); + // } + // } + + for vertex in self.vertices.iter_mut() { + for p in vertex.polygons.iter_mut() { + *p = *new_indexes.get(&(*p as i32)).unwrap_or(&-1) as isize; + } + } + // e// println!("{} -> {}", new_indexes.len(), kept); + // println!("{:?}", new_indexes); + new_indexes.len() as i32 != kept + } +} + +#[derive(Debug)] +pub struct UnionFind { + pub parent: Vec, +} + +impl UnionFind { + fn new(length: i32) -> Self { + Self { + parent: (0..length).collect(), + } + } + + fn find(&mut self, x: i32) -> i32 { + if x == -1 { + return -1; + } + if self.parent[x as usize] != x { + self.parent[x as usize] = self.find(self.parent[x as usize]); + } + self.parent[x as usize] + } + + fn union(&mut self, x: i32, y: i32) { + let x = self.find(x); + let y = self.find(y); + self.parent[y as usize] = x; + } +} + +#[cfg(test)] +mod test { + use glam::{vec2, Vec2}; + + use crate::{Mesh, Polygon, Triangulation, Vertex}; + + fn mesh_u_grid() -> Mesh { + Mesh { + vertices: vec![ + Vertex::new(Vec2::new(0., 0.), vec![0, -1]), + Vertex::new(Vec2::new(1., 0.), vec![0, 1, -1]), + Vertex::new(Vec2::new(2., 0.), vec![1, 2, -1]), + Vertex::new(Vec2::new(3., 0.), vec![2, -1]), + Vertex::new(Vec2::new(0., 1.), vec![3, 0, -1]), + Vertex::new(Vec2::new(1., 1.), vec![3, 1, 0, -1]), + Vertex::new(Vec2::new(2., 1.), vec![4, 2, 1, -1]), + Vertex::new(Vec2::new(3., 1.), vec![4, 2, -1]), + Vertex::new(Vec2::new(0., 2.), vec![5, 3, -1]), + Vertex::new(Vec2::new(1., 2.), vec![5, 3, -1]), + Vertex::new(Vec2::new(2., 2.), vec![6, 4, -1]), + Vertex::new(Vec2::new(3., 2.), vec![6, 4, -1]), + Vertex::new(Vec2::new(0., 3.), vec![5, -1]), + Vertex::new(Vec2::new(1., 3.), vec![5, -1]), + Vertex::new(Vec2::new(2., 3.), vec![6, -1]), + Vertex::new(Vec2::new(3., 3.), vec![6, -1]), + ], + polygons: vec![ + Polygon::new(vec![0, 1, 5, 4], false), + Polygon::new(vec![1, 2, 6, 5], false), + Polygon::new(vec![2, 3, 7, 6], false), + Polygon::new(vec![4, 5, 9, 8], false), + Polygon::new(vec![6, 7, 11, 10], false), + Polygon::new(vec![8, 9, 13, 12], false), + Polygon::new(vec![10, 11, 15, 14], false), + ], + ..Default::default() + } + } + + #[test] + fn merge_u() { + let mut mesh = mesh_u_grid(); + while mesh.merge_polygons() {} + mesh.bake(); + assert_eq!(mesh.polygons.len(), 3); + } + + #[test] + fn merge_and_path() { + let mut mesh = mesh_u_grid(); + while mesh.merge_polygons() {} + mesh.bake(); + assert_eq!(mesh.polygons.len(), 3); + dbg!(mesh.path(Vec2::new(0.5, 0.5), Vec2::new(2.5, 1.5))); + dbg!(mesh.path(Vec2::new(0.5, 1.5), Vec2::new(2.5, 1.5))); + } + + #[test] + fn merge_and_path_from_triangulation() { + let mut triangulation = Triangulation::from_outer_edges(vec![ + Vec2::new(-5., -5.), + Vec2::new(5., -5.), + Vec2::new(5., 5.), + Vec2::new(-5., 5.), + ]); + triangulation.add_obstacle(vec![ + Vec2::new(-1., -1.), + Vec2::new(-1., 1.), + Vec2::new(1., 1.), + Vec2::new(1., -1.), + ]); + let mut mesh = triangulation.as_navmesh().unwrap(); + // println!("{:#?}", mesh); + while mesh.merge_polygons() { + // println!("{:#?}", mesh); + } + mesh.bake(); + assert_eq!(mesh.polygons.len(), 4); + dbg!(mesh.path(Vec2::new(0.5, 0.5), Vec2::new(9.5, 9.5))); + } + + #[test] + fn merge_and_path_from_triangulation_2() { + let mut triangulation = Triangulation::from_outer_edges(vec![ + Vec2::new(-5., -5.), + Vec2::new(5., -5.), + Vec2::new(5., 5.), + Vec2::new(-5., 5.), + ]); + triangulation.add_obstacles(vec![ + vec![ + vec2(3.7, -3.3), + vec2(3.7, -3.7), + vec2(3.3, -3.7), + vec2(3.3, -3.3), + ], + vec![ + vec2(4.6, -1.3), + vec2(4.6, -1.7), + vec2(4.2, -1.7), + vec2(4.2, -1.3), + ], + ]); + triangulation.simplify(0.001); + let mut mesh = triangulation.as_navmesh().unwrap(); + + mesh.unbake(); + // println!("{:#?}", mesh); + while mesh.merge_polygons() { + // println!("{:#?}", mesh); + } + mesh.bake(); + assert_eq!(mesh.polygons.len(), 6); + dbg!(mesh.path(Vec2::new(-4.5, 4.0), Vec2::new(-4.0, -4.5))); + } +} diff --git a/src/primitives.rs b/src/primitives.rs index 9c1d03d..6987853 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -1,5 +1,6 @@ use std::ops::RangeInclusive; +use geo::{Area, Coord}; use smallvec::SmallVec; #[cfg(feature = "tracing")] use tracing::instrument; @@ -9,6 +10,8 @@ use glam::Vec2; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use crate::Mesh; + /// A point that lies on an edge of a polygon in the navigation mesh. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -146,6 +149,22 @@ impl Polygon { edges } + + pub(crate) fn area(&self, mesh: &Mesh) -> f32 { + geo::Polygon::new( + geo::LineString( + self.vertices + .iter() + .map(|v| { + let c = mesh.vertices[*v as usize].coords; + Coord::from((c.x, c.y)) + }) + .collect(), + ), + vec![], + ) + .unsigned_area() + } } #[cfg(test)]