From f2a375d8e2f7889eaad7115dafa582a59ffa7e7e Mon Sep 17 00:00:00 2001 From: huuhghhgyg Date: Mon, 27 Nov 2023 06:47:00 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20=20@=205b8d2?= =?UTF-8?q?07bdf0942a125f36903e027b6832813604e=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 8 +- ...1.1_what_microcity_can_do.html-BudeEahj.js | 1 + ...1.1_what_microcity_can_do.html-FdnWldjW.js | 1 - ...1.1_what_microcity_can_do.html-HcIFtvfI.js | 1 + ...1.1_what_microcity_can_do.html-XJqtRZkC.js | 1 - ...1.1_what_microcity_can_do.html-YHpuvmc-.js | 1 + ...1.1_what_microcity_can_do.html-m1yQS0yR.js | 1 + .../2.1_showing_a_world_map.html-6qnXe-uR.js | 1 + .../2.1_showing_a_world_map.html-F73HLlmh.js | 1 + .../2.1_showing_a_world_map.html-GZyM8T_I.js | 1 + .../2.1_showing_a_world_map.html-MkZfvyzh.js | 1 - .../2.1_showing_a_world_map.html-Ybz9X3FC.js | 1 + .../2.1_showing_a_world_map.html-nIk_uI4l.js | 1 - ...2_searching_for_countries.html-I1-AYfhY.js | 1 + ..._searching_for_countries.html-OCp2-Zt6.js} | 4 +- ...2_searching_for_countries.html-Y0QCK0Nw.js | 19 + ...2_searching_for_countries.html-eO0KcF_W.js | 1 - ...2_searching_for_countries.html-t7DQyHf7.js | 1 + assets/3.1_ui_overview.html-3VU9Yk9s.js | 1 + assets/3.1_ui_overview.html-6J3N08CW.js | 1 + assets/3.1_ui_overview.html-9iOHDqCk.js | 1 - assets/3.1_ui_overview.html-MdRgXeyu.js | 1 + assets/3.1_ui_overview.html-v38UIHQc.js | 1 + assets/3.1_ui_overview.html-w-bvZnF-.js | 1 - assets/3.2_vector_shapes.html-Ggy6120F.js | 1 + assets/3.2_vector_shapes.html-Ifn-q5O4.js | 1 - assets/3.2_vector_shapes.html-LHAJ_5Cg.js | 1 - assets/3.2_vector_shapes.html-hHGdBrtV.js | 1 + assets/3.2_vector_shapes.html-o5HA4H30.js | 1 + assets/3.2_vector_shapes.html-uMTzJRD1.js | 1 + assets/3.3_raster_grids.html-KMfHWMMp.js | 1 + assets/3.3_raster_grids.html-OMCyU_6r.js | 1 + assets/3.3_raster_grids.html-RHwKcATS.js | 1 - assets/3.3_raster_grids.html-_OMWjBic.js | 1 + assets/3.3_raster_grids.html-t2xEoSZE.js | 1 + assets/3.3_raster_grids.html-xKWq9pqo.js | 1 - assets/3.4_3d_scenes.html-2qe1Dffq.js | 1 + assets/3.4_3d_scenes.html-E-00tpZF.js | 1 + assets/3.4_3d_scenes.html-IfcyMMcw.js | 1 + assets/3.4_3d_scenes.html-Q6eGIaTn.js | 1 + assets/3.4_3d_scenes.html-SpQlhrPf.js | 1 - assets/3.4_3d_scenes.html-f5Qwa3ic.js | 1 - assets/3.5_tables.html-KMEBPMHz.js | 1 + assets/3.5_tables.html-LpE0kpTR.js | 1 + assets/3.5_tables.html-p-Cvt07d.js | 1 - assets/3.5_tables.html-p1nKqUcK.js | 1 + assets/3.5_tables.html-rfKSY5-v.js | 1 + assets/3.5_tables.html-zF8D9g8c.js | 1 - assets/3.6_maps_and_layers.html-0HlObXq2.js | 1 - assets/3.6_maps_and_layers.html-IZMNuK0Y.js | 1 + assets/3.6_maps_and_layers.html-KNvuRdkG.js | 1 + assets/3.6_maps_and_layers.html-T_p6rWde.js | 1 + assets/3.6_maps_and_layers.html-XuAmYobJ.js | 1 - assets/3.6_maps_and_layers.html-Zp7Na5N3.js | 1 + assets/3.7_modules.html-acS-BfiZ.js | 1 + assets/3.7_modules.html-d3BG3VZc.js | 1 + assets/3.7_modules.html-heS1MNUm.js | 1 - assets/3.7_modules.html-mmRRzoSK.js | 1 + assets/3.7_modules.html-q0PqEjdM.js | 1 - assets/3.7_modules.html-yzio17Ud.js | 1 + assets/3d-objects-en.html-rNfsYRE-.js | 1 - assets/3d-objects.html-0syC6c1Y.js | 1 - assets/3d-objects.html-AEqGn78x.js | 1 + ...KAwFYq5.js => 3d-objects.html-frmlnhRb.js} | 2 +- assets/3d-objects.html-jGytICR_.js | 1 + ...DC5k-lZ.js => 3d-objects.html-l7ht6tpD.js} | 8 +- assets/3d-scene-en.html-iUVl-UL0.js | 1 - assets/3d-scene.html-QeNNxNdQ.js | 1 + assets/3d-scene.html-_tzv6BUx.js | 1 - ...-A33RmZzw.js => 3d-scene.html-iJwBMXhE.js} | 2 +- ...-M1ONxEpk.js => 3d-scene.html-pmrdLLCG.js} | 4 +- assets/3d-scene.html-smFwVKZl.js | 1 + assets/4.1_si_overview.html-3JNy66LR.js | 2 + assets/4.1_si_overview.html-aQjVZ38p.js | 1 + assets/4.1_si_overview.html-iNqEh7u3.js | 2 - assets/4.1_si_overview.html-mGhzJSIB.js | 2 + assets/4.1_si_overview.html-niv4qRLq.js | 1 + assets/4.1_si_overview.html-umQYu3pM.js | 1 - assets/4.2_ui_control.html-P4QU671J.js | 1 - assets/4.2_ui_control.html-Zsu36Eou.js | 30 + ...ANV.js => 4.2_ui_control.html-it8dN_Kd.js} | 4 +- assets/4.2_ui_control.html-n4jA58yX.js | 1 + assets/4.2_ui_control.html-qgHwWAaN.js | 1 + ...=> 4.3_shapes_and_tables.html-9CbssTxf.js} | 4 +- assets/4.3_shapes_and_tables.html-Ix5omLFZ.js | 1 + assets/4.3_shapes_and_tables.html-SxckQf89.js | 40 + assets/4.3_shapes_and_tables.html-TBHhEBxq.js | 1 + assets/4.3_shapes_and_tables.html-ujzvaZYV.js | 1 - assets/4.4_grids.html-1OY5s52Z.js | 1 + ...7i5R0Lmo.js => 4.4_grids.html-H6iZCbel.js} | 4 +- assets/4.4_grids.html-JfxVQVat.js | 1 + assets/4.4_grids.html-exxRQ7PN.js | 14 + assets/4.4_grids.html-sbNpid1M.js | 1 - assets/4.5_3d_scenes.html-FkF6l2hE.js | 1 - ...q24g.js => 4.5_3d_scenes.html-IYlmTIee.js} | 4 +- assets/4.5_3d_scenes.html-I_su3OaS.js | 29 + assets/4.5_3d_scenes.html-rRFZU4Tx.js | 1 + assets/4.5_3d_scenes.html-wmTORBrk.js | 1 + assets/4.6_networks.html-0YdpivDj.js | 1 + assets/4.6_networks.html-HJVUieG0.js | 21 + assets/4.6_networks.html-O88jEbX0.js | 1 - ...mfd9Y.js => 4.6_networks.html-Z1GoybBX.js} | 2 +- assets/4.6_networks.html-kqO_isZV.js | 1 + assets/4.7_des_simulations.html-Ie9zDG_n.js | 17 + assets/4.7_des_simulations.html-JlfYhUg2.js | 1 + assets/4.7_des_simulations.html-W4OcSvr1.js | 1 + ...s => 4.7_des_simulations.html-WnzqINmi.js} | 2 +- assets/4.7_des_simulations.html-Ztj4rB4B.js | 1 - .../4.7_des_simulations_zh.html-PYbnXFlK.js | 17 + .../4.7_des_simulations_zh.html-dVopgWmS.js | 1 + ...mixed_integer_programming.html-MExXnfeH.js | 1 + ...mixed_integer_programming.html-TGfmzRJO.js | 1 + ...mixed_integer_programming.html-bEUkQ8el.js | 1 - ...ixed_integer_programming.html-ixWGOETF.js} | 4 +- ...mixed_integer_programming.html-spXsyES8.js | 15 + ....html-G5wmh19c.js => 404.html-tJ8VjSOS.js} | 2 +- assets/6-1trend-atJpgMOK.js | 1 + assets/A2hs-LwmLJR8r.js | 1 + assets/A2hs-xakqhU9I.js | 1 - assets/DL_Heatmap-RXB-9ZZK.js | 1 + assets/RMGObjects-PwARz0cG.js | 1 + assets/Result-All2-cnkq843b.js | 1 + assets/SearchBox-cTU2Stp4.js | 1567 ---------- assets/SearchBox-dgLZwYTI.js | 2621 +++++++++++++++++ assets/Subplot_Vertical-oXTmfxKU.js | 1 + assets/add_field-ZFhY51wb.js | 1 + assets/app-DaLjD81q.js | 16 - assets/app-LOf__QKq.js | 16 + assets/button_ruler-TjPjykp6.js | 1 + assets/cy-simulation.html-0hk7J5DH.js | 1 + assets/cy-simulation.html-5ddk20cl.js | 1 + assets/cy-simulation.html-YeLzi-Ut.js | 1 - assets/cy-simulation.html-bcA0fx8Y.js | 1 - assets/cy-simulation.html-ms-pVG5v.js | 1 + assets/cy-simulation.html-x04vq-Lr.js | 1 + assets/data_visualization-NDO9FqTF.js | 1 + assets/debug.html-80fcUM2q.js | 1 + assets/debug.html-Pj0zKe-s.js | 17 + assets/debug.html-YQ27enDU.js | 1 + assets/debug.html-mpPtl8CL.js | 1 - ...tml-yFg7dMCo.js => debug.html-vC47hElk.js} | 2 +- assets/edit_point-Z0R1Z63o.js | 1 + assets/event-scheduling-en.html-gy_6i2Mu.js | 1 - ...X.js => event-scheduling.html-3ysZ_CTt.js} | 2 +- ...n.js => event-scheduling.html-UZg_AtmL.js} | 4 +- assets/event-scheduling.html-_wHScoNu.js | 1 + assets/event-scheduling.html-o4tYPrMB.js | 1 - assets/event-scheduling.html-py4kt8T8.js | 1 + assets/fixed_increment_advance-iwDvqivb.js | 1 + assets/grid_attributes-xxRYXyrC.js | 1 + assets/index.html-2U8qpeQG.js | 1 + assets/index.html-8_XflqQA.js | 1 - assets/index.html-92lUUdK6.js | 1 + assets/index.html-HwGLrUxL.js | 1 - assets/index.html-IqC-sAFX.js | 1 + assets/index.html-NfP7JmCD.js | 1 + assets/index.html-WLZyFhZW.js | 1 + assets/index.html-WsgEQayQ.js | 1 + assets/index.html-YVKYSuDE.js | 1 + assets/index.html-a5Ef1Ykb.js | 1 + assets/index.html-b5l2JDLj.js | 1 + ...tml-ciQEBxId.js => index.html-c3NKfYSn.js} | 2 +- assets/index.html-dxC6HmKS.js | 2 + assets/index.html-hYpF9QHg.js | 1 + assets/index.html-hph7Dv3o.js | 1 - assets/index.html-ijEhgMTC.js | 1 - assets/index.html-lZExp6Yz.js | 2 - assets/index.html-nFm7KTWc.js | 1 - assets/index.html-nYDcqjx5.js | 1 + assets/index.html-ps9YKXkA.js | 1 - assets/index.html-rmW5MKDv.js | 2 + assets/lp.html-BGRyuCz8.js | 145 + assets/lp.html-NKzjcq8T.js | 1 - assets/lp.html-jETCO9wn.js | 1 + ...p.html-I7wRJlfF.js => lp.html-m-tLdpGS.js} | 2 +- assets/lp.html-yx0HpcA2.js | 1 + assets/lua.html--q1iToUD.js | 1 + assets/lua.html-B6d7gWD8.js | 1 + ....html-x5twFLDp.js => lua.html-JK5rP34K.js} | 2 +- assets/lua.html-bIzYAnJl.js | 209 ++ assets/lua.html-zCkaxI4j.js | 1 - assets/main_window-T08x4hNs.js | 1 + assets/mip-en.html-23DYx6JR.js | 1 - assets/mip.html-6_WAczY6.js | 1 + ....html-IS2AhQjv.js => mip.html-7cWhLBPI.js} | 4 +- assets/mip.html-B6IhijhB.js | 1 - assets/mip.html-EzteSB1w.js | 1 + ....html-Jt_OOSuJ.js => mip.html-KGIauE4D.js} | 2 +- assets/module_settings-yrsWXh8u.js | 1 + ...l-m23VzkXJ.js => network.html-IGA5rLvk.js} | 8 +- assets/network.html-l_dMxKkp.js | 1 + assets/network.html-qaPJNigq.js | 1 + assets/network.html-rimWgBRX.js | 70 + assets/network.html-td-Kb3D8.js | 1 - assets/oop.html-GH4Nnww4.js | 1 + assets/oop.html-QdhyUyOK.js | 68 + ....html-3LUP3-Yz.js => oop.html-VmjZry6A.js} | 4 +- assets/oop.html-azlXcYwP.js | 1 - assets/oop.html-lICjQDMc.js | 1 + assets/play-RaBYbg3m.js | 1 + assets/plots.html-6AeiZZxH.js | 258 ++ assets/plots.html-FPAlzRUf.js | 1 + assets/plots.html-JiB_VWcB.js | 1 - ...tml-ODP8nuzQ.js => plots.html-KiXIG1Oc.js} | 6 +- assets/plots.html-wJZ2mJax.js | 1 + assets/query_results-qHjDevxa.js | 1 + assets/scene_coordinate-_YCPy6or.js | 1 + assets/script_editor-a48-sxc_.js | 1 + assets/shot_parameter_id-roH75mzn.js | 1 + assets/shot_script_editor-VtQOeIXC.js | 1 + ...mpQRHhbv.js => timelapse.html-VDhH9cuD.js} | 4 +- assets/timelapse.html-ghI-6cF8.js | 1 + assets/timelapse.html-hdyuE7Lk.js | 1 - assets/timelapse.html-rfk9Tyut.js | 37 + assets/timelapse.html-xp-pHQoZ.js | 1 + ...tml-kWg64VtA.js => tools.html-LamHaYH8.js} | 2 +- assets/tools.html-PgdIJCR5.js | 1 + assets/tools.html-Tsv49Nwb.js | 1 + assets/tools.html-hzuhyAmn.js | 1 + assets/tools.html-zf97O5Kc.js | 1 - assets/two_way-xpspXH9g.js | 1 + assets/versions.html-1Kk-C1xB.js | 1 + assets/versions.html-8A5Y-n6r.js | 1 + assets/versions.html-HjNHjtrH.js | 1 - ...-9uZsLBnu.js => versions.html-aHfbE8Cr.js} | 2 +- assets/versions.html-diw0opQu.js | 1 + assets/visualization.html--w3hFG24.js | 4 - assets/visualization.html-2T-VgKWL.js | 4 + assets/visualization.html-URi_NNx7.js | 4 + assets/visualization.html-skftd09s.js | 1 + assets/visualization.html-t9WbOvdj.js | 1 + assets/visualization.html-xF8N-_EY.js | 1 - assets/warehouse-simulation.html-3NwF3MxT.js | 32 - assets/warehouse-simulation.html-5OK9wBKc.js | 32 + assets/warehouse-simulation.html-6ARLBksA.js | 1 + assets/warehouse-simulation.html-GfcmApNM.js | 1 - assets/warehouse-simulation.html-I2Ep6WY5.js | 32 + assets/warehouse-simulation.html-rJTy601K.js | 1 + assets/web-ui-en.html-FPAIksJ9.js | 1 - assets/web-ui.html--l1JvFq2.js | 1 + ...ml-9hWYZBEN.js => web-ui.html-MXj0sqtU.js} | 2 +- ...ml-zrAeLt4a.js => web-ui.html-Ub-X1RXi.js} | 2 +- assets/web-ui.html-cjOV8UTz.js | 1 - assets/web-ui.html-gL6LgUwH.js | 1 + docs/1.1_what_microcity_can_do.html | 8 +- docs/2.1_showing_a_world_map.html | 8 +- docs/2.2_searching_for_countries.html | 34 +- docs/3.1_ui_overview.html | 8 +- docs/3.2_vector_shapes.html | 8 +- docs/3.3_raster_grids.html | 8 +- docs/3.4_3d_scenes.html | 8 +- docs/3.5_tables.html | 8 +- docs/3.6_maps_and_layers.html | 8 +- docs/3.7_modules.html | 8 +- docs/4.1_si_overview.html | 10 +- docs/4.2_ui_control.html | 66 +- docs/4.3_shapes_and_tables.html | 86 +- docs/4.4_grids.html | 34 +- docs/4.5_3d_scenes.html | 64 +- docs/4.6_networks.html | 48 +- docs/4.7_des_simulations.html | 40 +- docs/4.8_mixed_integer_programming.html | 36 +- docs/imgs/index.html | 34 - docs/index.html | 8 +- en/docs/1.1_what_microcity_can_do.html | 34 + en/docs/2.1_showing_a_world_map.html | 34 + en/docs/2.2_searching_for_countries.html | 52 + en/docs/3.1_ui_overview.html | 34 + en/docs/3.2_vector_shapes.html | 34 + en/docs/3.3_raster_grids.html | 34 + en/docs/3.4_3d_scenes.html | 34 + en/docs/3.5_tables.html | 34 + en/docs/3.6_maps_and_layers.html | 34 + en/docs/3.7_modules.html | 34 + en/docs/4.1_si_overview.html | 35 + en/docs/4.2_ui_control.html | 63 + en/docs/4.3_shapes_and_tables.html | 73 + en/docs/4.4_grids.html | 47 + en/docs/4.5_3d_scenes.html | 62 + en/docs/4.6_networks.html | 54 + en/docs/4.7_des_simulations.html | 50 + en/docs/4.7_des_simulations_zh.html | 50 + en/docs/4.8_mixed_integer_programming.html | 48 + en/docs/index.html | 34 + en/index.html | 35 + .../notes/3d-objects.html | 14 +- en/notes/3d-scene.html | 39 + en/notes/cy-simulation.html | 34 + en/notes/debug.html | 50 + en/notes/event-scheduling.html | 95 + en/notes/index.html | 34 + en/notes/lp.html | 178 ++ en/notes/lua.html | 242 ++ notes/mip-en.html => en/notes/mip.html | 12 +- en/notes/network.html | 103 + en/notes/oop.html | 101 + en/notes/plots.html | 291 ++ en/notes/timelapse.html | 70 + en/notes/tools.html | 34 + en/notes/versions.html | 34 + en/notes/visualization.html | 37 + en/notes/warehouse-simulation.html | 65 + en/notes/web-ui.html | 34 + images/doc/index.html | 34 + index.html | 8 +- notes/3d-objects.html | 8 +- notes/3d-scene-en.html | 39 - notes/3d-scene.html | 8 +- notes/cy-simulation.html | 8 +- notes/debug.html | 8 +- notes/event-scheduling-en.html | 95 - notes/event-scheduling.html | 8 +- notes/index.html | 8 +- notes/lp.html | 8 +- notes/lua.html | 8 +- notes/mip.html | 8 +- notes/network.html | 8 +- notes/oop.html | 8 +- notes/plots.html | 8 +- notes/timelapse.html | 8 +- notes/tools.html | 8 +- notes/versions.html | 8 +- notes/visualization.html | 8 +- notes/warehouse-simulation.html | 8 +- notes/web-ui-en.html | 34 - notes/web-ui.html | 8 +- service-worker.js | 2 +- service-worker.js.map | 2 +- sitemap.xml | 2 +- 329 files changed, 6625 insertions(+), 2275 deletions(-) create mode 100644 assets/1.1_what_microcity_can_do.html-BudeEahj.js delete mode 100644 assets/1.1_what_microcity_can_do.html-FdnWldjW.js create mode 100644 assets/1.1_what_microcity_can_do.html-HcIFtvfI.js delete mode 100644 assets/1.1_what_microcity_can_do.html-XJqtRZkC.js create mode 100644 assets/1.1_what_microcity_can_do.html-YHpuvmc-.js create mode 100644 assets/1.1_what_microcity_can_do.html-m1yQS0yR.js create mode 100644 assets/2.1_showing_a_world_map.html-6qnXe-uR.js create mode 100644 assets/2.1_showing_a_world_map.html-F73HLlmh.js create mode 100644 assets/2.1_showing_a_world_map.html-GZyM8T_I.js delete mode 100644 assets/2.1_showing_a_world_map.html-MkZfvyzh.js create mode 100644 assets/2.1_showing_a_world_map.html-Ybz9X3FC.js delete mode 100644 assets/2.1_showing_a_world_map.html-nIk_uI4l.js create mode 100644 assets/2.2_searching_for_countries.html-I1-AYfhY.js rename assets/{2.2_searching_for_countries.html-JlV76Wlp.js => 2.2_searching_for_countries.html-OCp2-Zt6.js} (70%) create mode 100644 assets/2.2_searching_for_countries.html-Y0QCK0Nw.js delete mode 100644 assets/2.2_searching_for_countries.html-eO0KcF_W.js create mode 100644 assets/2.2_searching_for_countries.html-t7DQyHf7.js create mode 100644 assets/3.1_ui_overview.html-3VU9Yk9s.js create mode 100644 assets/3.1_ui_overview.html-6J3N08CW.js delete mode 100644 assets/3.1_ui_overview.html-9iOHDqCk.js create mode 100644 assets/3.1_ui_overview.html-MdRgXeyu.js create mode 100644 assets/3.1_ui_overview.html-v38UIHQc.js delete mode 100644 assets/3.1_ui_overview.html-w-bvZnF-.js create mode 100644 assets/3.2_vector_shapes.html-Ggy6120F.js delete mode 100644 assets/3.2_vector_shapes.html-Ifn-q5O4.js delete mode 100644 assets/3.2_vector_shapes.html-LHAJ_5Cg.js create mode 100644 assets/3.2_vector_shapes.html-hHGdBrtV.js create mode 100644 assets/3.2_vector_shapes.html-o5HA4H30.js create mode 100644 assets/3.2_vector_shapes.html-uMTzJRD1.js create mode 100644 assets/3.3_raster_grids.html-KMfHWMMp.js create mode 100644 assets/3.3_raster_grids.html-OMCyU_6r.js delete mode 100644 assets/3.3_raster_grids.html-RHwKcATS.js create mode 100644 assets/3.3_raster_grids.html-_OMWjBic.js create mode 100644 assets/3.3_raster_grids.html-t2xEoSZE.js delete mode 100644 assets/3.3_raster_grids.html-xKWq9pqo.js create mode 100644 assets/3.4_3d_scenes.html-2qe1Dffq.js create mode 100644 assets/3.4_3d_scenes.html-E-00tpZF.js create mode 100644 assets/3.4_3d_scenes.html-IfcyMMcw.js create mode 100644 assets/3.4_3d_scenes.html-Q6eGIaTn.js delete mode 100644 assets/3.4_3d_scenes.html-SpQlhrPf.js delete mode 100644 assets/3.4_3d_scenes.html-f5Qwa3ic.js create mode 100644 assets/3.5_tables.html-KMEBPMHz.js create mode 100644 assets/3.5_tables.html-LpE0kpTR.js delete mode 100644 assets/3.5_tables.html-p-Cvt07d.js create mode 100644 assets/3.5_tables.html-p1nKqUcK.js create mode 100644 assets/3.5_tables.html-rfKSY5-v.js delete mode 100644 assets/3.5_tables.html-zF8D9g8c.js delete mode 100644 assets/3.6_maps_and_layers.html-0HlObXq2.js create mode 100644 assets/3.6_maps_and_layers.html-IZMNuK0Y.js create mode 100644 assets/3.6_maps_and_layers.html-KNvuRdkG.js create mode 100644 assets/3.6_maps_and_layers.html-T_p6rWde.js delete mode 100644 assets/3.6_maps_and_layers.html-XuAmYobJ.js create mode 100644 assets/3.6_maps_and_layers.html-Zp7Na5N3.js create mode 100644 assets/3.7_modules.html-acS-BfiZ.js create mode 100644 assets/3.7_modules.html-d3BG3VZc.js delete mode 100644 assets/3.7_modules.html-heS1MNUm.js create mode 100644 assets/3.7_modules.html-mmRRzoSK.js delete mode 100644 assets/3.7_modules.html-q0PqEjdM.js create mode 100644 assets/3.7_modules.html-yzio17Ud.js delete mode 100644 assets/3d-objects-en.html-rNfsYRE-.js delete mode 100644 assets/3d-objects.html-0syC6c1Y.js create mode 100644 assets/3d-objects.html-AEqGn78x.js rename assets/{3d-objects.html-lKAwFYq5.js => 3d-objects.html-frmlnhRb.js} (99%) create mode 100644 assets/3d-objects.html-jGytICR_.js rename assets/{3d-objects-en.html-7DC5k-lZ.js => 3d-objects.html-l7ht6tpD.js} (97%) delete mode 100644 assets/3d-scene-en.html-iUVl-UL0.js create mode 100644 assets/3d-scene.html-QeNNxNdQ.js delete mode 100644 assets/3d-scene.html-_tzv6BUx.js rename assets/{3d-scene.html-A33RmZzw.js => 3d-scene.html-iJwBMXhE.js} (99%) rename assets/{3d-scene-en.html-M1ONxEpk.js => 3d-scene.html-pmrdLLCG.js} (98%) create mode 100644 assets/3d-scene.html-smFwVKZl.js create mode 100644 assets/4.1_si_overview.html-3JNy66LR.js create mode 100644 assets/4.1_si_overview.html-aQjVZ38p.js delete mode 100644 assets/4.1_si_overview.html-iNqEh7u3.js create mode 100644 assets/4.1_si_overview.html-mGhzJSIB.js create mode 100644 assets/4.1_si_overview.html-niv4qRLq.js delete mode 100644 assets/4.1_si_overview.html-umQYu3pM.js delete mode 100644 assets/4.2_ui_control.html-P4QU671J.js create mode 100644 assets/4.2_ui_control.html-Zsu36Eou.js rename assets/{4.2_ui_control.html-PXdKdANV.js => 4.2_ui_control.html-it8dN_Kd.js} (92%) create mode 100644 assets/4.2_ui_control.html-n4jA58yX.js create mode 100644 assets/4.2_ui_control.html-qgHwWAaN.js rename assets/{4.3_shapes_and_tables.html-kM2JYXcO.js => 4.3_shapes_and_tables.html-9CbssTxf.js} (93%) create mode 100644 assets/4.3_shapes_and_tables.html-Ix5omLFZ.js create mode 100644 assets/4.3_shapes_and_tables.html-SxckQf89.js create mode 100644 assets/4.3_shapes_and_tables.html-TBHhEBxq.js delete mode 100644 assets/4.3_shapes_and_tables.html-ujzvaZYV.js create mode 100644 assets/4.4_grids.html-1OY5s52Z.js rename assets/{4.4_grids.html-7i5R0Lmo.js => 4.4_grids.html-H6iZCbel.js} (77%) create mode 100644 assets/4.4_grids.html-JfxVQVat.js create mode 100644 assets/4.4_grids.html-exxRQ7PN.js delete mode 100644 assets/4.4_grids.html-sbNpid1M.js delete mode 100644 assets/4.5_3d_scenes.html-FkF6l2hE.js rename assets/{4.5_3d_scenes.html-2AMaq24g.js => 4.5_3d_scenes.html-IYlmTIee.js} (92%) create mode 100644 assets/4.5_3d_scenes.html-I_su3OaS.js create mode 100644 assets/4.5_3d_scenes.html-rRFZU4Tx.js create mode 100644 assets/4.5_3d_scenes.html-wmTORBrk.js create mode 100644 assets/4.6_networks.html-0YdpivDj.js create mode 100644 assets/4.6_networks.html-HJVUieG0.js delete mode 100644 assets/4.6_networks.html-O88jEbX0.js rename assets/{4.6_networks.html-PK_mfd9Y.js => 4.6_networks.html-Z1GoybBX.js} (92%) create mode 100644 assets/4.6_networks.html-kqO_isZV.js create mode 100644 assets/4.7_des_simulations.html-Ie9zDG_n.js create mode 100644 assets/4.7_des_simulations.html-JlfYhUg2.js create mode 100644 assets/4.7_des_simulations.html-W4OcSvr1.js rename assets/{4.7_des_simulations.html-8bSUiGUz.js => 4.7_des_simulations.html-WnzqINmi.js} (90%) delete mode 100644 assets/4.7_des_simulations.html-Ztj4rB4B.js create mode 100644 assets/4.7_des_simulations_zh.html-PYbnXFlK.js create mode 100644 assets/4.7_des_simulations_zh.html-dVopgWmS.js create mode 100644 assets/4.8_mixed_integer_programming.html-MExXnfeH.js create mode 100644 assets/4.8_mixed_integer_programming.html-TGfmzRJO.js delete mode 100644 assets/4.8_mixed_integer_programming.html-bEUkQ8el.js rename assets/{4.8_mixed_integer_programming.html-E59_LnJJ.js => 4.8_mixed_integer_programming.html-ixWGOETF.js} (85%) create mode 100644 assets/4.8_mixed_integer_programming.html-spXsyES8.js rename assets/{404.html-G5wmh19c.js => 404.html-tJ8VjSOS.js} (63%) create mode 100644 assets/6-1trend-atJpgMOK.js create mode 100644 assets/A2hs-LwmLJR8r.js delete mode 100644 assets/A2hs-xakqhU9I.js create mode 100644 assets/DL_Heatmap-RXB-9ZZK.js create mode 100644 assets/RMGObjects-PwARz0cG.js create mode 100644 assets/Result-All2-cnkq843b.js delete mode 100644 assets/SearchBox-cTU2Stp4.js create mode 100644 assets/SearchBox-dgLZwYTI.js create mode 100644 assets/Subplot_Vertical-oXTmfxKU.js create mode 100644 assets/add_field-ZFhY51wb.js delete mode 100644 assets/app-DaLjD81q.js create mode 100644 assets/app-LOf__QKq.js create mode 100644 assets/button_ruler-TjPjykp6.js create mode 100644 assets/cy-simulation.html-0hk7J5DH.js create mode 100644 assets/cy-simulation.html-5ddk20cl.js delete mode 100644 assets/cy-simulation.html-YeLzi-Ut.js delete mode 100644 assets/cy-simulation.html-bcA0fx8Y.js create mode 100644 assets/cy-simulation.html-ms-pVG5v.js create mode 100644 assets/cy-simulation.html-x04vq-Lr.js create mode 100644 assets/data_visualization-NDO9FqTF.js create mode 100644 assets/debug.html-80fcUM2q.js create mode 100644 assets/debug.html-Pj0zKe-s.js create mode 100644 assets/debug.html-YQ27enDU.js delete mode 100644 assets/debug.html-mpPtl8CL.js rename assets/{debug.html-yFg7dMCo.js => debug.html-vC47hElk.js} (98%) create mode 100644 assets/edit_point-Z0R1Z63o.js delete mode 100644 assets/event-scheduling-en.html-gy_6i2Mu.js rename assets/{event-scheduling.html-7ezvA1AX.js => event-scheduling.html-3ysZ_CTt.js} (99%) rename assets/{event-scheduling-en.html-gRProVKn.js => event-scheduling.html-UZg_AtmL.js} (99%) create mode 100644 assets/event-scheduling.html-_wHScoNu.js delete mode 100644 assets/event-scheduling.html-o4tYPrMB.js create mode 100644 assets/event-scheduling.html-py4kt8T8.js create mode 100644 assets/fixed_increment_advance-iwDvqivb.js create mode 100644 assets/grid_attributes-xxRYXyrC.js create mode 100644 assets/index.html-2U8qpeQG.js delete mode 100644 assets/index.html-8_XflqQA.js create mode 100644 assets/index.html-92lUUdK6.js delete mode 100644 assets/index.html-HwGLrUxL.js create mode 100644 assets/index.html-IqC-sAFX.js create mode 100644 assets/index.html-NfP7JmCD.js create mode 100644 assets/index.html-WLZyFhZW.js create mode 100644 assets/index.html-WsgEQayQ.js create mode 100644 assets/index.html-YVKYSuDE.js create mode 100644 assets/index.html-a5Ef1Ykb.js create mode 100644 assets/index.html-b5l2JDLj.js rename assets/{index.html-ciQEBxId.js => index.html-c3NKfYSn.js} (76%) create mode 100644 assets/index.html-dxC6HmKS.js create mode 100644 assets/index.html-hYpF9QHg.js delete mode 100644 assets/index.html-hph7Dv3o.js delete mode 100644 assets/index.html-ijEhgMTC.js delete mode 100644 assets/index.html-lZExp6Yz.js delete mode 100644 assets/index.html-nFm7KTWc.js create mode 100644 assets/index.html-nYDcqjx5.js delete mode 100644 assets/index.html-ps9YKXkA.js create mode 100644 assets/index.html-rmW5MKDv.js create mode 100644 assets/lp.html-BGRyuCz8.js delete mode 100644 assets/lp.html-NKzjcq8T.js create mode 100644 assets/lp.html-jETCO9wn.js rename assets/{lp.html-I7wRJlfF.js => lp.html-m-tLdpGS.js} (99%) create mode 100644 assets/lp.html-yx0HpcA2.js create mode 100644 assets/lua.html--q1iToUD.js create mode 100644 assets/lua.html-B6d7gWD8.js rename assets/{lua.html-x5twFLDp.js => lua.html-JK5rP34K.js} (99%) create mode 100644 assets/lua.html-bIzYAnJl.js delete mode 100644 assets/lua.html-zCkaxI4j.js create mode 100644 assets/main_window-T08x4hNs.js delete mode 100644 assets/mip-en.html-23DYx6JR.js create mode 100644 assets/mip.html-6_WAczY6.js rename assets/{mip-en.html-IS2AhQjv.js => mip.html-7cWhLBPI.js} (99%) delete mode 100644 assets/mip.html-B6IhijhB.js create mode 100644 assets/mip.html-EzteSB1w.js rename assets/{mip.html-Jt_OOSuJ.js => mip.html-KGIauE4D.js} (99%) create mode 100644 assets/module_settings-yrsWXh8u.js rename assets/{network.html-m23VzkXJ.js => network.html-IGA5rLvk.js} (83%) create mode 100644 assets/network.html-l_dMxKkp.js create mode 100644 assets/network.html-qaPJNigq.js create mode 100644 assets/network.html-rimWgBRX.js delete mode 100644 assets/network.html-td-Kb3D8.js create mode 100644 assets/oop.html-GH4Nnww4.js create mode 100644 assets/oop.html-QdhyUyOK.js rename assets/{oop.html-3LUP3-Yz.js => oop.html-VmjZry6A.js} (71%) delete mode 100644 assets/oop.html-azlXcYwP.js create mode 100644 assets/oop.html-lICjQDMc.js create mode 100644 assets/play-RaBYbg3m.js create mode 100644 assets/plots.html-6AeiZZxH.js create mode 100644 assets/plots.html-FPAlzRUf.js delete mode 100644 assets/plots.html-JiB_VWcB.js rename assets/{plots.html-ODP8nuzQ.js => plots.html-KiXIG1Oc.js} (97%) create mode 100644 assets/plots.html-wJZ2mJax.js create mode 100644 assets/query_results-qHjDevxa.js create mode 100644 assets/scene_coordinate-_YCPy6or.js create mode 100644 assets/script_editor-a48-sxc_.js create mode 100644 assets/shot_parameter_id-roH75mzn.js create mode 100644 assets/shot_script_editor-VtQOeIXC.js rename assets/{timelapse.html-mpQRHhbv.js => timelapse.html-VDhH9cuD.js} (74%) create mode 100644 assets/timelapse.html-ghI-6cF8.js delete mode 100644 assets/timelapse.html-hdyuE7Lk.js create mode 100644 assets/timelapse.html-rfk9Tyut.js create mode 100644 assets/timelapse.html-xp-pHQoZ.js rename assets/{tools.html-kWg64VtA.js => tools.html-LamHaYH8.js} (93%) create mode 100644 assets/tools.html-PgdIJCR5.js create mode 100644 assets/tools.html-Tsv49Nwb.js create mode 100644 assets/tools.html-hzuhyAmn.js delete mode 100644 assets/tools.html-zf97O5Kc.js create mode 100644 assets/two_way-xpspXH9g.js create mode 100644 assets/versions.html-1Kk-C1xB.js create mode 100644 assets/versions.html-8A5Y-n6r.js delete mode 100644 assets/versions.html-HjNHjtrH.js rename assets/{versions.html-9uZsLBnu.js => versions.html-aHfbE8Cr.js} (98%) create mode 100644 assets/versions.html-diw0opQu.js delete mode 100644 assets/visualization.html--w3hFG24.js create mode 100644 assets/visualization.html-2T-VgKWL.js create mode 100644 assets/visualization.html-URi_NNx7.js create mode 100644 assets/visualization.html-skftd09s.js create mode 100644 assets/visualization.html-t9WbOvdj.js delete mode 100644 assets/visualization.html-xF8N-_EY.js delete mode 100644 assets/warehouse-simulation.html-3NwF3MxT.js create mode 100644 assets/warehouse-simulation.html-5OK9wBKc.js create mode 100644 assets/warehouse-simulation.html-6ARLBksA.js delete mode 100644 assets/warehouse-simulation.html-GfcmApNM.js create mode 100644 assets/warehouse-simulation.html-I2Ep6WY5.js create mode 100644 assets/warehouse-simulation.html-rJTy601K.js delete mode 100644 assets/web-ui-en.html-FPAIksJ9.js create mode 100644 assets/web-ui.html--l1JvFq2.js rename assets/{web-ui-en.html-9hWYZBEN.js => web-ui.html-MXj0sqtU.js} (98%) rename assets/{web-ui.html-zrAeLt4a.js => web-ui.html-Ub-X1RXi.js} (99%) delete mode 100644 assets/web-ui.html-cjOV8UTz.js create mode 100644 assets/web-ui.html-gL6LgUwH.js delete mode 100644 docs/imgs/index.html create mode 100644 en/docs/1.1_what_microcity_can_do.html create mode 100644 en/docs/2.1_showing_a_world_map.html create mode 100644 en/docs/2.2_searching_for_countries.html create mode 100644 en/docs/3.1_ui_overview.html create mode 100644 en/docs/3.2_vector_shapes.html create mode 100644 en/docs/3.3_raster_grids.html create mode 100644 en/docs/3.4_3d_scenes.html create mode 100644 en/docs/3.5_tables.html create mode 100644 en/docs/3.6_maps_and_layers.html create mode 100644 en/docs/3.7_modules.html create mode 100644 en/docs/4.1_si_overview.html create mode 100644 en/docs/4.2_ui_control.html create mode 100644 en/docs/4.3_shapes_and_tables.html create mode 100644 en/docs/4.4_grids.html create mode 100644 en/docs/4.5_3d_scenes.html create mode 100644 en/docs/4.6_networks.html create mode 100644 en/docs/4.7_des_simulations.html create mode 100644 en/docs/4.7_des_simulations_zh.html create mode 100644 en/docs/4.8_mixed_integer_programming.html create mode 100644 en/docs/index.html create mode 100644 en/index.html rename notes/3d-objects-en.html => en/notes/3d-objects.html (50%) create mode 100644 en/notes/3d-scene.html create mode 100644 en/notes/cy-simulation.html create mode 100644 en/notes/debug.html create mode 100644 en/notes/event-scheduling.html create mode 100644 en/notes/index.html create mode 100644 en/notes/lp.html create mode 100644 en/notes/lua.html rename notes/mip-en.html => en/notes/mip.html (80%) create mode 100644 en/notes/network.html create mode 100644 en/notes/oop.html create mode 100644 en/notes/plots.html create mode 100644 en/notes/timelapse.html create mode 100644 en/notes/tools.html create mode 100644 en/notes/versions.html create mode 100644 en/notes/visualization.html create mode 100644 en/notes/warehouse-simulation.html create mode 100644 en/notes/web-ui.html create mode 100644 images/doc/index.html delete mode 100644 notes/3d-scene-en.html delete mode 100644 notes/event-scheduling-en.html delete mode 100644 notes/web-ui-en.html diff --git a/404.html b/404.html index 917fa4ab..c916370a 100644 --- a/404.html +++ b/404.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - MicroCity笔记 + MicroCity笔记 - + -

404

There's nothing here.
Take me home
- +

404

How did we get here?
Take me home
+ diff --git a/assets/1.1_what_microcity_can_do.html-BudeEahj.js b/assets/1.1_what_microcity_can_do.html-BudeEahj.js new file mode 100644 index 00000000..15c730bc --- /dev/null +++ b/assets/1.1_what_microcity_can_do.html-BudeEahj.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-4ee3d2cc","path":"/docs/1.1_what_microcity_can_do.html","title":"1.1 MicroCity的功能","lang":"zh-CN","frontmatter":{"next":"./2.1_showing_a_world_map.md","description":"MicroCity被设计为一款方便的空间规划工具,具有便携、紧凑和快速的特点。 一个建模框架 基于GIS、网络和混合整数规划库,MicroCity可以作为一个建模框架来解决交通运输问题,例如城市物流和航运规划: city_logistic    shipping_planning 一个仿真平台 基于3D计算机图形和离散事件仿真引擎,...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/1.1_what_microcity_can_do.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/1.1_what_microcity_can_do.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"1.1 MicroCity的功能"}],["meta",{"property":"og:description","content":"MicroCity被设计为一款方便的空间规划工具,具有便携、紧凑和快速的特点。 一个建模框架 基于GIS、网络和混合整数规划库,MicroCity可以作为一个建模框架来解决交通运输问题,例如城市物流和航运规划: city_logistic    shipping_planning 一个仿真平台 基于3D计算机图形和离散事件仿真引擎,..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"1.1 MicroCity的功能\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"一个建模框架","slug":"一个建模框架","link":"#一个建模框架","children":[]},{"level":2,"title":"一个仿真平台","slug":"一个仿真平台","link":"#一个仿真平台","children":[]},{"level":2,"title":"通过脚本模块定制","slug":"通过脚本模块定制","link":"#通过脚本模块定制","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/1.1_what_microcity_can_do.md","autoDesc":true}');export{t as data}; diff --git a/assets/1.1_what_microcity_can_do.html-FdnWldjW.js b/assets/1.1_what_microcity_can_do.html-FdnWldjW.js deleted file mode 100644 index f309fd3d..00000000 --- a/assets/1.1_what_microcity_can_do.html-FdnWldjW.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as o,r as n,o as a,c as r,f as s,a as i,b as t,d as c}from"./app-DaLjD81q.js";const l="/MicroCityNotes/assets/city_logistics-8RxmuTB1.png",d="/MicroCityNotes/assets/shipping_planning-_Mkxb6xn.png",_="/MicroCityNotes/assets/warehouse_simulation-CPwzj5dU.gif",h="/MicroCityNotes/assets/terminal_simulation-rx4w_Kp0.gif",m="/MicroCityNotes/assets/modules-cY5Kwc-8.png",u="/MicroCityNotes/assets/shot_script_editor-_OW8Kkrd.png",g={},p=i("h1",{id:"_1-1-microcity能做什么",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#_1-1-microcity能做什么","aria-hidden":"true"},"#"),t(" 1.1 MicroCity能做什么")],-1),b=i("p",null,[t("MicroCity is designed to be a handy spatial planning tool, which is "),i("strong",null,"portable, compact and fast"),t(".")],-1),f=i("h2",{id:"a-modeling-framework",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#a-modeling-framework","aria-hidden":"true"},"#"),t(" A Modeling Framework")],-1),y=i("p",null,[t("Based on GIS, Networks and Mixed Integer Programming libraries, MicroCity can be used as a modeling framework to solve transporation problems, such as "),i("strong",null,"City Logistics and Shipping Planning:"),i("br")],-1),w=i("p",null,[i("img",{src:l,alt:"city_logistic"}),t("   ")],-1),C=i("p",null,[i("img",{src:d,alt:"shipping_planning"}),i("br")],-1),x=i("h2",{id:"a-simulation-platform",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#a-simulation-platform","aria-hidden":"true"},"#"),t(" A Simulation Platform")],-1),M=i("p",null,[t("Based on 3D CGI and Discrete Event Simulation Engine, MicroCity can be used as a simulation platform to evaluate logistic scenarios, such as "),i("strong",null,"Automated Warehouses and Container Terminals:"),i("br")],-1),k=i("p",null,[i("img",{src:_,alt:"warehouse_simulation"})],-1),N=i("p",null,[i("img",{src:h,alt:"terminal_simulation"}),i("br")],-1),S=i("h2",{id:"customized-by-scriptable-modules",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#customized-by-scriptable-modules","aria-hidden":"true"},"#"),t(" Customized by Scriptable Modules")],-1),v={href:"https://saga-gis.sourceforge.io",target:"_blank",rel:"noopener noreferrer"},B=i("strong",null,"Script Editor:",-1),E=i("br",null,null,-1),I=i("img",{src:m,alt:"modules"},null,-1),A=i("img",{src:u,alt:"shot"},null,-1),z=i("p",null,[t("Currently, MicroCity is mainly used in teaching and research. It can be freely distributed."),i("br")],-1);function P(V,G){const e=n("ExternalLinkIcon");return a(),r("div",null,[p,b,f,y,s(' '),w,s(' '),C,x,M,s(' '),k,s("    "),s(' '),N,S,i("p",null,[t("MicroCity can extend its functionality with modules which can be inherited from "),i("a",v,[t("SAGA"),c(e)]),t(" or scripted and debugged in "),B,E,I,t("    "),A]),z])}const L=o(g,[["render",P],["__file","1.1_what_microcity_can_do.html.vue"]]);export{L as default}; diff --git a/assets/1.1_what_microcity_can_do.html-HcIFtvfI.js b/assets/1.1_what_microcity_can_do.html-HcIFtvfI.js new file mode 100644 index 00000000..e8021b65 --- /dev/null +++ b/assets/1.1_what_microcity_can_do.html-HcIFtvfI.js @@ -0,0 +1 @@ +import{_ as n,a as r,b as _,c as a,d as c,e as l}from"./shot_script_editor-VtQOeIXC.js";import{_ as h,r as d,o as m,c as g,f as s,a as t,b as i,d as e}from"./app-LOf__QKq.js";const u={},p=t("h1",{id:"_1-1-microcity的功能",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-1-microcity的功能","aria-hidden":"true"},"#"),i(" 1.1 MicroCity的功能")],-1),f=t("p",null,[i("MicroCity被设计为一款方便的空间规划工具,具有"),t("strong",null,"便携、紧凑和快速"),i("的特点。")],-1),b=t("h2",{id:"一个建模框架",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#一个建模框架","aria-hidden":"true"},"#"),i(" 一个建模框架")],-1),y=t("p",null,[i("基于GIS、网络和混合整数规划库,MicroCity可以作为一个建模框架来解决交通运输问题,例如"),t("strong",null,"城市物流和航运规划"),i(":"),t("br")],-1),x=t("p",null,[t("img",{src:n,alt:"city_logistic"}),i("   ")],-1),C=t("p",null,[t("img",{src:r,alt:"shipping_planning"}),t("br")],-1),w=t("h2",{id:"一个仿真平台",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#一个仿真平台","aria-hidden":"true"},"#"),i(" 一个仿真平台")],-1),k=t("p",null,[i("基于3D计算机图形和离散事件仿真引擎,MicroCity可以作为一个仿真平台来评估物流场景,例如"),t("strong",null,"自动化仓库和集装箱码头"),i(":"),t("br")],-1),M=t("p",null,[t("img",{src:_,alt:"warehouse_simulation"})],-1),N=t("p",null,[t("img",{src:a,alt:"terminal_simulation"}),t("br")],-1),V=t("h2",{id:"通过脚本模块定制",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#通过脚本模块定制","aria-hidden":"true"},"#"),i(" 通过脚本模块定制")],-1),v={href:"https://saga-gis.sourceforge.io",target:"_blank",rel:"noopener noreferrer"},B=t("strong",null,"脚本编辑器",-1),E=t("br",null,null,-1),G=t("img",{src:c,alt:"modules"},null,-1),I=t("img",{src:l,alt:"shot"},null,-1),A=t("p",null,[i("目前,MicroCity主要用于教学和研究,可以自由分发。"),t("br")],-1),L={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},S=t("strong",null,"反馈",-1);function T(q,D){const o=d("ExternalLinkIcon");return m(),g("div",null,[p,f,b,y,s(' '),x,s(' '),C,w,k,s(' '),M,s("    "),s(' '),N,V,t("p",null,[i("MicroCity可以通过模块来扩展其功能,这些模块可以从"),t("a",v,[i("SAGA"),e(o)]),i("继承或在"),B,i("中进行脚本编写和调试:"),E,G,i("    "),I]),A,t("blockquote",null,[t("p",null,[i("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",L,[S,e(o)]),i("页面提交反馈。")])])])}const z=h(u,[["render",T],["__file","1.1_what_microcity_can_do.html.vue"]]);export{z as default}; diff --git a/assets/1.1_what_microcity_can_do.html-XJqtRZkC.js b/assets/1.1_what_microcity_can_do.html-XJqtRZkC.js deleted file mode 100644 index eedcfaf8..00000000 --- a/assets/1.1_what_microcity_can_do.html-XJqtRZkC.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-4ee3d2cc","path":"/docs/1.1_what_microcity_can_do.html","title":"1.1 MicroCity能做什么","lang":"zh-CN","frontmatter":{"next":"./2.1_showing_a_world_map.md","description":"MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast. A Modeling Framework Based on GIS, Networks and Mixed Integer Programming librari...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/1.1_what_microcity_can_do.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"1.1 MicroCity能做什么"}],["meta",{"property":"og:description","content":"MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast. A Modeling Framework Based on GIS, Networks and Mixed Integer Programming librari..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"1.1 MicroCity能做什么"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"1.1 MicroCity能做什么\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"A Modeling Framework","slug":"a-modeling-framework","link":"#a-modeling-framework","children":[]},{"level":2,"title":"A Simulation Platform","slug":"a-simulation-platform","link":"#a-simulation-platform","children":[]},{"level":2,"title":"Customized by Scriptable Modules","slug":"customized-by-scriptable-modules","link":"#customized-by-scriptable-modules","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/1.1_what_microcity_can_do.md","autoDesc":true}');export{t as data}; diff --git a/assets/1.1_what_microcity_can_do.html-YHpuvmc-.js b/assets/1.1_what_microcity_can_do.html-YHpuvmc-.js new file mode 100644 index 00000000..7cc652f0 --- /dev/null +++ b/assets/1.1_what_microcity_can_do.html-YHpuvmc-.js @@ -0,0 +1 @@ +import{_ as o,a as n,b as a,c as r,d as c,e as l}from"./shot_script_editor-VtQOeIXC.js";import{_ as d,r as _,o as h,c as m,f as e,a as i,b as t,d as u}from"./app-LOf__QKq.js";const g={},p=i("h1",{id:"_1-1-what-microcity-can-do",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#_1-1-what-microcity-can-do","aria-hidden":"true"},"#"),t(" 1.1 What MicroCity can Do")],-1),b=i("p",null,[t("MicroCity is designed to be a handy spatial planning tool, which is "),i("strong",null,"portable, compact and fast"),t(".")],-1),f=i("h2",{id:"a-modeling-framework",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#a-modeling-framework","aria-hidden":"true"},"#"),t(" A Modeling Framework")],-1),y=i("p",null,[t("Based on GIS, Networks and Mixed Integer Programming libraries, MicroCity can be used as a modeling framework to solve transporation problems, such as "),i("strong",null,"City Logistics and Shipping Planning:"),i("br")],-1),w=i("p",null,[i("img",{src:o,alt:"city_logistic"}),t("   ")],-1),C=i("p",null,[i("img",{src:n,alt:"shipping_planning"}),i("br")],-1),x=i("h2",{id:"a-simulation-platform",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#a-simulation-platform","aria-hidden":"true"},"#"),t(" A Simulation Platform")],-1),k=i("p",null,[t("Based on 3D CGI and Discrete Event Simulation Engine, MicroCity can be used as a simulation platform to evaluate logistic scenarios, such as "),i("strong",null,"Automated Warehouses and Container Terminals:"),i("br")],-1),M=i("p",null,[i("img",{src:a,alt:"warehouse_simulation"})],-1),S=i("p",null,[i("img",{src:r,alt:"terminal_simulation"}),i("br")],-1),v=i("h2",{id:"customized-by-scriptable-modules",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#customized-by-scriptable-modules","aria-hidden":"true"},"#"),t(" Customized by Scriptable Modules")],-1),E={href:"https://saga-gis.sourceforge.io",target:"_blank",rel:"noopener noreferrer"},I=i("strong",null,"Script Editor:",-1),A=i("br",null,null,-1),B=i("img",{src:c,alt:"modules"},null,-1),N=i("img",{src:l,alt:"shot"},null,-1),V=i("p",null,[t("Currently, MicroCity is mainly used in teaching and research. It can be freely distributed."),i("br")],-1);function z(D,G){const s=_("ExternalLinkIcon");return h(),m("div",null,[p,b,f,y,e(' '),w,e(' '),C,x,k,e(' '),M,e("    "),e(' '),S,v,i("p",null,[t("MicroCity can extend its functionality with modules which can be inherited from "),i("a",E,[t("SAGA"),u(s)]),t(" or scripted and debugged in "),I,A,B,t("    "),N]),V])}const T=d(g,[["render",z],["__file","1.1_what_microcity_can_do.html.vue"]]);export{T as default}; diff --git a/assets/1.1_what_microcity_can_do.html-m1yQS0yR.js b/assets/1.1_what_microcity_can_do.html-m1yQS0yR.js new file mode 100644 index 00000000..8d5da026 --- /dev/null +++ b/assets/1.1_what_microcity_can_do.html-m1yQS0yR.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-41d66a06","path":"/en/docs/1.1_what_microcity_can_do.html","title":"1.1 What MicroCity can Do","lang":"en-US","frontmatter":{"next":"./2.1_showing_a_world_map.md","description":"MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast. A Modeling Framework Based on GIS, Networks and Mixed Integer Programming librari...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/1.1_what_microcity_can_do.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/1.1_what_microcity_can_do.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"1.1 What MicroCity can Do"}],["meta",{"property":"og:description","content":"MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast. A Modeling Framework Based on GIS, Networks and Mixed Integer Programming librari..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"1.1 What MicroCity can Do\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"A Modeling Framework","slug":"a-modeling-framework","link":"#a-modeling-framework","children":[]},{"level":2,"title":"A Simulation Platform","slug":"a-simulation-platform","link":"#a-simulation-platform","children":[]},{"level":2,"title":"Customized by Scriptable Modules","slug":"customized-by-scriptable-modules","link":"#customized-by-scriptable-modules","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/1.1_what_microcity_can_do.md","autoDesc":true}');export{t as data}; diff --git a/assets/2.1_showing_a_world_map.html-6qnXe-uR.js b/assets/2.1_showing_a_world_map.html-6qnXe-uR.js new file mode 100644 index 00000000..a34fb16c --- /dev/null +++ b/assets/2.1_showing_a_world_map.html-6qnXe-uR.js @@ -0,0 +1 @@ +const t=JSON.parse(`{"key":"v-79ce9d5a","path":"/en/docs/2.1_showing_a_world_map.html","title":"2.1 Showing a World Map","lang":"en-US","frontmatter":{"prev":"./1.1_what_microcity_can_do.md","next":"./2.2_searching_for_countries.md","description":"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity. Loading Data and Creating a Map Download the countries.shp (https://github.com/microcity/micr...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/2.1_showing_a_world_map.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/2.1_showing_a_world_map.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"2.1 Showing a World Map"}],["meta",{"property":"og:description","content":"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity. Loading Data and Creating a Map Download the countries.shp (https://github.com/microcity/micr..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.1 Showing a World Map\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Loading Data and Creating a Map","slug":"loading-data-and-creating-a-map","link":"#loading-data-and-creating-a-map","children":[]},{"level":2,"title":"Visualizing Coutries' Properties","slug":"visualizing-coutries-properties","link":"#visualizing-coutries-properties","children":[]},{"level":2,"title":"Editing Shapes","slug":"editing-shapes","link":"#editing-shapes","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/2.1_showing_a_world_map.md","autoDesc":true}`);export{t as data}; diff --git a/assets/2.1_showing_a_world_map.html-F73HLlmh.js b/assets/2.1_showing_a_world_map.html-F73HLlmh.js new file mode 100644 index 00000000..d636b417 --- /dev/null +++ b/assets/2.1_showing_a_world_map.html-F73HLlmh.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-498b1a32","path":"/docs/2.1_showing_a_world_map.html","title":"2.1 显示世界地图","lang":"zh-CN","frontmatter":{"prev":"./1.1_what_microcity_can_do.md","next":"./2.2_searching_for_countries.md","description":"本教程将指导您在 MicroCity 中操作和可视化地理信息系统(GIS)数据。 加载数据和创建地图 下载 countries.shp (https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.shp)(ArcGIS shapefile)和 countr...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/2.1_showing_a_world_map.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/2.1_showing_a_world_map.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"2.1 显示世界地图"}],["meta",{"property":"og:description","content":"本教程将指导您在 MicroCity 中操作和可视化地理信息系统(GIS)数据。 加载数据和创建地图 下载 countries.shp (https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.shp)(ArcGIS shapefile)和 countr..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.1 显示世界地图\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"加载数据和创建地图","slug":"加载数据和创建地图","link":"#加载数据和创建地图","children":[]},{"level":2,"title":"可视化国家属性","slug":"可视化国家属性","link":"#可视化国家属性","children":[]},{"level":2,"title":"编辑形状","slug":"编辑形状","link":"#编辑形状","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/2.1_showing_a_world_map.md","autoDesc":true}');export{t as data}; diff --git a/assets/2.1_showing_a_world_map.html-GZyM8T_I.js b/assets/2.1_showing_a_world_map.html-GZyM8T_I.js new file mode 100644 index 00000000..44d2d7fe --- /dev/null +++ b/assets/2.1_showing_a_world_map.html-GZyM8T_I.js @@ -0,0 +1 @@ +import{_ as i}from"./icon_microcity-Je85-7MO.js";import{_ as r}from"./button_load-GOP3K2yO.js";import{_ as s,a}from"./data_visualization-NDO9FqTF.js";import{_ as c}from"./icon_shapes_polygon-5WS2EZQN.js";import{_ as l}from"./button_action-tmG_4IgV.js";import{_ as d,r as g,o as h,c as p,a as t,b as o,d as e,e as _}from"./app-LOf__QKq.js";const u={},m=t("h1",{id:"_2-1-showing-a-world-map",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-1-showing-a-world-map","aria-hidden":"true"},"#"),o(" 2.1 Showing a World Map")],-1),f=t("p",null,"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity.",-1),b=t("h2",{id:"loading-data-and-creating-a-map",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#loading-data-and-creating-a-map","aria-hidden":"true"},"#"),o(" Loading Data and Creating a Map")],-1),k=t("strong",null,"Download",-1),S={href:"https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.shp",target:"_blank",rel:"noopener noreferrer"},y={href:"https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.dbf",target:"_blank",rel:"noopener noreferrer"},w=t("img",{src:i,alt:"icon_microcity"},null,-1),x=t("strong",null,"MicroCity",-1),C=t("img",{src:r,alt:"button_load"},null,-1),T=t("strong",null,"Data Tab",-1),E=t("strong",null,"Data->Shapes->Polygon->01. countries",-1),I=t("img",{src:s,alt:"Screenshot"},null,-1),P=_('

Visualizing Coutries' Properties

Right click icon 01. countries in the Workspace panel. Click Attributes->Table->Show in the popup menu. In the Settings Panel, find the Colors->Type option and select Graduated Color. In its sub-option Attribute, select POP_EST which is population property of countries. In the Setting Panel, find the Chart option and click the ... button. In the popup dialog, select pie in Chart Type option and select GDP_MD_EST in Attribute (Size) option and select EXPORT and IMPORT checkboxs in Fields option and click Okay button. Screenshot

Editing Shapes

Select buttonAction button at toolbar. Left click some country and right click it and select Edit Selected Shape in the popup menu. Then the shape will be in editing mode. You can change its polygon points and finish your editing by right click and select Edit Selected Shape again.

',4);function D(M,v){const n=g("ExternalLinkIcon");return h(),p("div",null,[m,f,b,t("p",null,[k,o(" the "),t("a",S,[o("countries.shp"),e(n)]),o(" (ArcGIS shapefile) and the "),t("a",y,[o("countries.dbf"),e(n)]),o(" (dBase file) in a same folder. Open "),w,x,o(" and load "),C,o(" or drag the countries.shp into MicroCity and select "),T,o(" in Workspace panel. Double click "),E,o(" in Workspace panel. "),I]),P])}const L=d(u,[["render",D],["__file","2.1_showing_a_world_map.html.vue"]]);export{L as default}; diff --git a/assets/2.1_showing_a_world_map.html-MkZfvyzh.js b/assets/2.1_showing_a_world_map.html-MkZfvyzh.js deleted file mode 100644 index 695332c3..00000000 --- a/assets/2.1_showing_a_world_map.html-MkZfvyzh.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as i}from"./icon_microcity-Je85-7MO.js";import{_ as s}from"./button_load-GOP3K2yO.js";import{_ as r}from"./icon_shapes_polygon-5WS2EZQN.js";import{_ as a}from"./button_action-tmG_4IgV.js";import{_ as c,r as l,o as d,c as g,a as t,b as o,d as e,e as h}from"./app-DaLjD81q.js";const p="/MicroCityNotes/assets/world_countries-K0FhRM3K.png",_="/MicroCityNotes/assets/data_visualization-HBg0SLXW.png",u={},m=t("h1",{id:"_2-1-展示世界地图",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-1-展示世界地图","aria-hidden":"true"},"#"),o(" 2.1 展示世界地图")],-1),b=t("p",null,"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity.",-1),f=t("h2",{id:"loading-data-and-creating-a-map",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#loading-data-and-creating-a-map","aria-hidden":"true"},"#"),o(" Loading Data and Creating a Map")],-1),y=t("strong",null,"Download",-1),k={href:"https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.shp",target:"_blank",rel:"noopener noreferrer"},S={href:"https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.dbf",target:"_blank",rel:"noopener noreferrer"},C=t("img",{src:i,alt:"icon_microcity"},null,-1),w=t("strong",null,"MicroCity",-1),x=t("img",{src:s,alt:"button_load"},null,-1),T=t("strong",null,"Data Tab",-1),E=t("strong",null,"Data->Shapes->Polygon->01. countries",-1),I=t("img",{src:p,alt:"Screenshot"},null,-1),M=h('

Visualizing Coutries' Properties

Right click icon 01. countries in the Workspace panel. Click Attributes->Table->Show in the popup menu. In the Settings Panel, find the Colors->Type option and select Graduated Color. In its sub-option Attribute, select POP_EST which is population property of countries. In the Setting Panel, find the Chart option and click the ... button. In the popup dialog, select pie in Chart Type option and select GDP_MD_EST in Attribute (Size) option and select EXPORT and IMPORT checkboxs in Fields option and click Okay button. Screenshot

Editing Shapes

Select buttonAction button at toolbar. Left click some country and right click it and select Edit Selected Shape in the popup menu. Then the shape will be in editing mode. You can change its polygon points and finish your editing by right click and select Edit Selected Shape again.

',4);function P(v,D){const n=l("ExternalLinkIcon");return d(),g("div",null,[m,b,f,t("p",null,[y,o(" the "),t("a",k,[o("countries.shp"),e(n)]),o(" (ArcGIS shapefile) and the "),t("a",S,[o("countries.dbf"),e(n)]),o(" (dBase file) in a same folder. Open "),C,w,o(" and load "),x,o(" or drag the countries.shp into MicroCity and select "),T,o(" in Workspace panel. Double click "),E,o(" in Workspace panel. "),I]),M])}const O=c(u,[["render",P],["__file","2.1_showing_a_world_map.html.vue"]]);export{O as default}; diff --git a/assets/2.1_showing_a_world_map.html-Ybz9X3FC.js b/assets/2.1_showing_a_world_map.html-Ybz9X3FC.js new file mode 100644 index 00000000..71eba231 --- /dev/null +++ b/assets/2.1_showing_a_world_map.html-Ybz9X3FC.js @@ -0,0 +1 @@ +import{_ as e}from"./icon_microcity-Je85-7MO.js";import{_ as n}from"./button_load-GOP3K2yO.js";import{_ as i,a}from"./data_visualization-NDO9FqTF.js";import{_ as c}from"./icon_shapes_polygon-5WS2EZQN.js";import{_}from"./button_action-tmG_4IgV.js";import{_ as h,r as g,o as l,c as d,a as t,b as o,d as s,e as m}from"./app-LOf__QKq.js";const u={},p=t("h1",{id:"_2-1-显示世界地图",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-1-显示世界地图","aria-hidden":"true"},"#"),o(" 2.1 显示世界地图")],-1),f=t("p",null,"本教程将指导您在 MicroCity 中操作和可视化地理信息系统(GIS)数据。",-1),b=t("h2",{id:"加载数据和创建地图",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#加载数据和创建地图","aria-hidden":"true"},"#"),o(" 加载数据和创建地图")],-1),S=t("strong",null,"下载",-1),y={href:"https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.shp",target:"_blank",rel:"noopener noreferrer"},x={href:"https://github.com/microcity/microcity.github.io/raw/main/docs/data/countries.dbf",target:"_blank",rel:"noopener noreferrer"},k=t("img",{src:e,alt:"icon_microcity"},null,-1),C=t("strong",null,"MicroCity",-1),T=t("img",{src:n,alt:"button_load"},null,-1),w=t("strong",null,"Data Tab",-1),E=t("strong",null,"Data->Shapes->Polygon->01. countries",-1),P=t("img",{src:i,alt:"Screenshot"},null,-1),M=m('

可视化国家属性

右键点击 icon 01. countries工作区面板中。在弹出菜单中选择 Attributes->Table->Show。在 Settings 面板中,找到 Colors->Type 选项并选择 Graduated Color。在其子选项 Attribute 中,选择国家的人口属性 POP_EST。在 Settings 面板中,找到 Chart 选项并点击 ... 按钮。在弹出对话框中,选择饼图(pie)作为图表类型,选择 GDP_MD_EST 作为属性(大小),并在 Fields 选项中选择 EXPORTIMPORT 复选框,然后点击 Okay 按钮。 Screenshot

编辑形状

在工具栏上选择 buttonAction 按钮。左键点击某个国家,右键点击它并在弹出菜单中选择 Edit Selected Shape,然后该形状将进入编辑模式。您可以更改其多边形的点,并在右键点击并再次选择 Edit Selected Shape 来完成编辑。

',4),G={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},I=t("strong",null,"反馈",-1);function N(A,B){const r=g("ExternalLinkIcon");return l(),d("div",null,[p,f,b,t("p",null,[S,o(),t("a",y,[o("countries.shp"),s(r)]),o("(ArcGIS shapefile)和 "),t("a",x,[o("countries.dbf"),s(r)]),o("(dBase 文件)到同一个文件夹中。打开 "),k,C,o(",点击 "),T,o("或将 countries.shp 拖入 MicroCity,然后在工作区面板中选择 "),w,o("。双击工作区面板中的 "),E,o("。 "),P]),M,t("blockquote",null,[t("p",null,[o("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",G,[I,s(r)]),o("页面提交反馈。")])])])}const $=h(u,[["render",N],["__file","2.1_showing_a_world_map.html.vue"]]);export{$ as default}; diff --git a/assets/2.1_showing_a_world_map.html-nIk_uI4l.js b/assets/2.1_showing_a_world_map.html-nIk_uI4l.js deleted file mode 100644 index 4153257d..00000000 --- a/assets/2.1_showing_a_world_map.html-nIk_uI4l.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse(`{"key":"v-498b1a32","path":"/docs/2.1_showing_a_world_map.html","title":"2.1 展示世界地图","lang":"zh-CN","frontmatter":{"prev":"./1.1_what_microcity_can_do.md","next":"./2.2_searching_for_countries.md","description":"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity. Loading Data and Creating a Map Download the countries.shp (https://github.com/microcity/micr...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/2.1_showing_a_world_map.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"2.1 展示世界地图"}],["meta",{"property":"og:description","content":"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity. Loading Data and Creating a Map Download the countries.shp (https://github.com/microcity/micr..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"2.1 展示世界地图"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.1 展示世界地图\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Loading Data and Creating a Map","slug":"loading-data-and-creating-a-map","link":"#loading-data-and-creating-a-map","children":[]},{"level":2,"title":"Visualizing Coutries' Properties","slug":"visualizing-coutries-properties","link":"#visualizing-coutries-properties","children":[]},{"level":2,"title":"Editing Shapes","slug":"editing-shapes","link":"#editing-shapes","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/2.1_showing_a_world_map.md","autoDesc":true}`);export{t as data}; diff --git a/assets/2.2_searching_for_countries.html-I1-AYfhY.js b/assets/2.2_searching_for_countries.html-I1-AYfhY.js new file mode 100644 index 00000000..81994b3b --- /dev/null +++ b/assets/2.2_searching_for_countries.html-I1-AYfhY.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-30ccfc90","path":"/en/docs/2.2_searching_for_countries.html","title":"2.2 Searching for Countries","lang":"en-US","frontmatter":{"prev":"./2.1_showing_a_world_map.md","next":"./3.1_ui_overview.md","description":"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed. GIS Data Structure In MicroCity, GIS data consists of t...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/2.2_searching_for_countries.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/2.2_searching_for_countries.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"2.2 Searching for Countries"}],["meta",{"property":"og:description","content":"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed. GIS Data Structure In MicroCity, GIS data consists of t..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.2 Searching for Countries\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"GIS Data Structure","slug":"gis-data-structure","link":"#gis-data-structure","children":[]},{"level":2,"title":"Making a Query","slug":"making-a-query","link":"#making-a-query","children":[]},{"level":2,"title":"Running the Script","slug":"running-the-script","link":"#running-the-script","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/2.2_searching_for_countries.md","autoDesc":true}');export{t as data}; diff --git a/assets/2.2_searching_for_countries.html-JlV76Wlp.js b/assets/2.2_searching_for_countries.html-OCp2-Zt6.js similarity index 70% rename from assets/2.2_searching_for_countries.html-JlV76Wlp.js rename to assets/2.2_searching_for_countries.html-OCp2-Zt6.js index 3a912caf..8fc8e8b5 100644 --- a/assets/2.2_searching_for_countries.html-JlV76Wlp.js +++ b/assets/2.2_searching_for_countries.html-OCp2-Zt6.js @@ -1,4 +1,4 @@ -import{_ as t}from"./icon_script_editor-ibm_2NsU.js";import{_ as e,r as o,o as p,c,a as n,b as s,d as i,w as r,e as l}from"./app-DaLjD81q.js";const u="/MicroCityNotes/assets/gis_data_structure-OyzSP1K_.png",d="/MicroCityNotes/assets/query_results-8DtTlPIZ.png",k={},h=n("h1",{id:"_2-2-寻找国家",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-2-寻找国家","aria-hidden":"true"},"#"),s(" 2.2 寻找国家")],-1),m=n("p",null,"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed.",-1),y=n("h2",{id:"gis-data-structure",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#gis-data-structure","aria-hidden":"true"},"#"),s(" GIS Data Structure")],-1),_=n("strong",null,"Shapes",-1),g=n("strong",null,"Shape",-1),f=n("strong",null,"Parts",-1),v=n("strong",null,"Part",-1),b=n("strong",null,"Points",-1),w=n("strong",null,"Shape",-1),S=n("strong",null,"Attributes Table",-1),C=n("img",{src:u,alt:"structure"},null,-1),P=l('

Making a Query

Suppose we want to find countries, each of which has a population of more than 100 million and is entirely in the northern hemisphere. So we need to check every point's coordinate in each shape and the population attribute of the shape. Open ScriptEditor icon_script_editor and type following codes:

local Countries = Open("countries.shp")                 --Try to open the shapes layer
+import{_ as t,a as e}from"./query_results-qHjDevxa.js";import{_ as o}from"./icon_script_editor-ibm_2NsU.js";import{_ as p,r as c,o as i,c as r,a as n,b as s,d as l,w as u,e as d}from"./app-LOf__QKq.js";const k={},h=n("h1",{id:"_2-2-searching-for-countries",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-2-searching-for-countries","aria-hidden":"true"},"#"),s(" 2.2 Searching for Countries")],-1),m=n("p",null,"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed.",-1),y=n("h2",{id:"gis-data-structure",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#gis-data-structure","aria-hidden":"true"},"#"),s(" GIS Data Structure")],-1),_=n("strong",null,"Shapes",-1),f=n("strong",null,"Shape",-1),g=n("strong",null,"Parts",-1),v=n("strong",null,"Part",-1),b=n("strong",null,"Points",-1),w=n("strong",null,"Shape",-1),S=n("strong",null,"Attributes Table",-1),C=n("img",{src:t,alt:"structure"},null,-1),G=d('

Making a Query

Suppose we want to find countries, each of which has a population of more than 100 million and is entirely in the northern hemisphere. So we need to check every point's coordinate in each shape and the population attribute of the shape. Open ScriptEditor icon_script_editor and type following codes:

local Countries = Open("countries.shp")                 --Try to open the shapes layer
 for i = 1, GetRecCount(Countries) do                    --Loop all the shape objects in the layer
     local country = GetShape(Countries, i)              --Get the shape object of a country
     local north = true                                  --Assume the country is in the northern hemisphere
@@ -16,4 +16,4 @@ import{_ as t}from"./icon_script_editor-ibm_2NsU.js";import{_ as e,r as o,o as p
         Print(name, ": ", pop/100000000)                --Print out the result
     end
 end
-

Running the Script

Save the script to query.mcs and open it with MicroCity or drag it to MicroCity. Then you will find a query item appears in Modules Tab in Workspace panel. Double click the sub-item main. If a dialog pops up, select 01. countries and click Okay. The results will be shown in Messages panel. results

',5);function G(q,x){const a=o("RouterLink");return p(),c("div",null,[h,m,y,n("p",null,[s("In MicroCity, GIS data consists of three types of "),_,s(": Point, Polyline and Polygon, each of which can be visualized as a Map Layer. In a layer, a "),g,s(" object consists of one or more "),f,s(", and every "),v,s(" consists of one or more "),b,s(". A "),w,s(" object is also associated to a record in the "),S,s(". You can also edit the shape or its attributes (see "),i(a,{to:"/docs/3.2_vector_shapes.html"},{default:r(()=>[s("3.2")]),_:1}),s("). "),C,s(" If you want perform a complex editing or handle a batch of shapes, you can use MicroCity Script, in which many built-in functions can be used.")]),P])}const I=e(k,[["render",G],["__file","2.2_searching_for_countries.html.vue"]]);export{I as default}; +

Running the Script

Save the script to query.mcs and open it with MicroCity or drag it to MicroCity. Then you will find a query item appears in Modules Tab in Workspace panel. Double click the sub-item main. If a dialog pops up, select 01. countries and click Okay. The results will be shown in Messages panel. results

',5);function P(q,x){const a=c("RouterLink");return i(),r("div",null,[h,m,y,n("p",null,[s("In MicroCity, GIS data consists of three types of "),_,s(": Point, Polyline and Polygon, each of which can be visualized as a Map Layer. In a layer, a "),f,s(" object consists of one or more "),g,s(", and every "),v,s(" consists of one or more "),b,s(". A "),w,s(" object is also associated to a record in the "),S,s(". You can also edit the shape or its attributes (see "),l(a,{to:"/en/docs/3.2_vector_shapes.html"},{default:u(()=>[s("3.2")]),_:1}),s("). "),C,s(" If you want perform a complex editing or handle a batch of shapes, you can use MicroCity Script, in which many built-in functions can be used.")]),G])}const I=p(k,[["render",P],["__file","2.2_searching_for_countries.html.vue"]]);export{I as default}; diff --git a/assets/2.2_searching_for_countries.html-Y0QCK0Nw.js b/assets/2.2_searching_for_countries.html-Y0QCK0Nw.js new file mode 100644 index 00000000..fb58278e --- /dev/null +++ b/assets/2.2_searching_for_countries.html-Y0QCK0Nw.js @@ -0,0 +1,19 @@ +import{_ as p,a as c}from"./query_results-qHjDevxa.js";import{_ as r}from"./icon_script_editor-ibm_2NsU.js";import{_ as l,r as a,o as i,c as u,a as n,b as s,d as t,w as k,e as d}from"./app-LOf__QKq.js";const m={},_=n("h1",{id:"_2-2-寻找国家",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-2-寻找国家","aria-hidden":"true"},"#"),s(" 2.2 寻找国家")],-1),h=n("p",null,"本教程将指导您使用 MicroCity Script 对GIS数据进行编码操作。您需要完成 2.1 内容以继续。",-1),g=n("h2",{id:"gis-数据结构",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#gis-数据结构","aria-hidden":"true"},"#"),s(" GIS 数据结构")],-1),v=n("strong",null,"形状",-1),y=n("strong",null,"形状",-1),b=n("strong",null,"部分",-1),f=n("strong",null,"部分",-1),w=n("strong",null,"点",-1),C=n("strong",null,"形状",-1),x=n("strong",null,"属性表",-1),q=d('

gis_data_structure

如果您想要执行复杂的编辑或处理一批形状,可以使用 MicroCity Script,其中包含许多内置函数可供使用。

进行查询

假设我们想要找出人口超过1亿且完全位于北半球的国家。因此,我们需要检查每个形状中每个点的坐标以及形状的人口属性。打开 ScriptEditor icon_script_editor,然后输入以下代码:

local Countries = Open("countries.shp")                 --尝试打开形状图层
+for i = 1, GetRecCount(Countries) do                    --循环遍历图层中的所有形状对象
+    local country = GetShape(Countries, i)              --获取一个国家的形状对象
+    local north = true                                  --假设该国家位于北半球
+    for j = 1, GetPartCount(country) do                 --循环遍历所有形状中的部分
+        for k = 1, GetPointCount(country, j) do         --循环遍历该部分中的所有点
+            local x, y = GetPointXY(country, k, j)      --获取点的坐标
+            if y < 0 then                               --如果纬度小于0
+                north = false                           --北半球的假设为假
+            end
+        end
+    end
+    local pop = GetValue(country, "POP_EST")            --获取人口属性
+    local name = GetValue(country, "NAME")              --获取国家名称
+    if pop > 100000000 and north  then                  --检查两个条件
+        Print(name, ": ", pop/100000000)                --打印结果
+    end
+end
+

运行脚本

将脚本保存为 query.mcs,并使用 MicroCity 打开它,或将其拖到 MicroCity。然后您将在 Workspace 面板的模块选项卡中找到一个名为query的项目。双击子项main。如果弹出对话框,请选择01. countries,然后点击确定。结果将显示在消息面板中。

query_results

',8),G={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},S=n("strong",null,"反馈",-1);function M(P,E){const o=a("RouterLink"),e=a("ExternalLinkIcon");return i(),u("div",null,[_,h,g,n("p",null,[s("在 MicroCity 中,GIS 数据由三种类型的"),v,s("组成:点、折线和多边形,每种类型都可以视为地图图层。在图层中,"),y,s("对象由一个或多个"),b,s("组成,而每个"),f,s("又由一个或多个"),w,s("组成。"),C,s("对象还与"),x,s("中的记录相关联。您还可以编辑形状或其属性(请参阅 "),t(o,{to:"/docs/3.2_vector_shapes.html"},{default:k(()=>[s("3.2")]),_:1}),s(")。")]),q,n("blockquote",null,[n("p",null,[s("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",G,[S,t(e)]),s("页面提交反馈。")])])])}const L=l(m,[["render",M],["__file","2.2_searching_for_countries.html.vue"]]);export{L as default}; diff --git a/assets/2.2_searching_for_countries.html-eO0KcF_W.js b/assets/2.2_searching_for_countries.html-eO0KcF_W.js deleted file mode 100644 index 686248f9..00000000 --- a/assets/2.2_searching_for_countries.html-eO0KcF_W.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-0f6857b8","path":"/docs/2.2_searching_for_countries.html","title":"2.2 寻找国家","lang":"zh-CN","frontmatter":{"prev":"./2.1_showing_a_world_map.md","next":"./3.1_ui_overview.md","description":"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed. GIS Data Structure In MicroCity, GIS data consists of t...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/2.2_searching_for_countries.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"2.2 寻找国家"}],["meta",{"property":"og:description","content":"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed. GIS Data Structure In MicroCity, GIS data consists of t..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"2.2 寻找国家"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.2 寻找国家\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"GIS Data Structure","slug":"gis-data-structure","link":"#gis-data-structure","children":[]},{"level":2,"title":"Making a Query","slug":"making-a-query","link":"#making-a-query","children":[]},{"level":2,"title":"Running the Script","slug":"running-the-script","link":"#running-the-script","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/2.2_searching_for_countries.md","autoDesc":true}');export{t as data}; diff --git a/assets/2.2_searching_for_countries.html-t7DQyHf7.js b/assets/2.2_searching_for_countries.html-t7DQyHf7.js new file mode 100644 index 00000000..2b23afce --- /dev/null +++ b/assets/2.2_searching_for_countries.html-t7DQyHf7.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-0f6857b8","path":"/docs/2.2_searching_for_countries.html","title":"2.2 寻找国家","lang":"zh-CN","frontmatter":{"prev":"./2.1_showing_a_world_map.md","next":"./3.1_ui_overview.md","description":"本教程将指导您使用 MicroCity Script 对GIS数据进行编码操作。您需要完成 2.1 内容以继续。 GIS 数据结构 在 MicroCity 中,GIS 数据由三种类型的形状组成:点、折线和多边形,每种类型都可以视为地图图层。在图层中,形状对象由一个或多个部分组成,而每个部分又由一个或多个点组成。形状对象还与属性表中的记录相关联。您还可以...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/2.2_searching_for_countries.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/2.2_searching_for_countries.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"2.2 寻找国家"}],["meta",{"property":"og:description","content":"本教程将指导您使用 MicroCity Script 对GIS数据进行编码操作。您需要完成 2.1 内容以继续。 GIS 数据结构 在 MicroCity 中,GIS 数据由三种类型的形状组成:点、折线和多边形,每种类型都可以视为地图图层。在图层中,形状对象由一个或多个部分组成,而每个部分又由一个或多个点组成。形状对象还与属性表中的记录相关联。您还可以..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.2 寻找国家\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"GIS 数据结构","slug":"gis-数据结构","link":"#gis-数据结构","children":[]},{"level":2,"title":"进行查询","slug":"进行查询","link":"#进行查询","children":[]},{"level":2,"title":"运行脚本","slug":"运行脚本","link":"#运行脚本","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"docs/2.2_searching_for_countries.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.1_ui_overview.html-3VU9Yk9s.js b/assets/3.1_ui_overview.html-3VU9Yk9s.js new file mode 100644 index 00000000..0f545cdb --- /dev/null +++ b/assets/3.1_ui_overview.html-3VU9Yk9s.js @@ -0,0 +1 @@ +import{_ as o}from"./main_window-T08x4hNs.js";import{_ as a,r as s,o as n,c as i,a as e,b as r,d as c,e as h}from"./app-LOf__QKq.js";const d={},_=h('

3.1 用户界面概览

MicroCity提供了一个简洁的图形窗口界面,以便于对数据和模块进行操作。

主窗口及其组件

截图

支持的文件类型

MicroCity可以打开ArcGIS shapefile文件(*.shp),Grids文件(*.sgrd),dBase文件(*.dbf),Tabular文本文件(*.csv, *.txt),Point clouds点云文件(*.spc),影像文件(*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx)以及MicroCity 3D场景文件(*.m3d)。这些数据文件可以在工作区面板的数据选项卡中进行管理。模块库文件(*.dll, *.mcs)可以在工作区面板的模块选项卡中进行管理和执行。

项目管理

已打开的数据文件、模块库文件、设置和子窗口信息可以通过文件->项目菜单保存或打开一个MicroCity项目(*.mprj)。mprj文件不包含任何文件数据。为方便维护,项目中的文件应放置在同一文件夹或mprj文件的子文件夹中。

',8),l={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},p=e("strong",null,"反馈",-1);function g(u,m){const t=s("ExternalLinkIcon");return n(),i("div",null,[_,e("blockquote",null,[e("p",null,[r("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),e("a",l,[p,c(t)]),r("页面提交反馈。")])])])}const b=a(d,[["render",g],["__file","3.1_ui_overview.html.vue"]]);export{b as default}; diff --git a/assets/3.1_ui_overview.html-6J3N08CW.js b/assets/3.1_ui_overview.html-6J3N08CW.js new file mode 100644 index 00000000..8414b670 --- /dev/null +++ b/assets/3.1_ui_overview.html-6J3N08CW.js @@ -0,0 +1 @@ +import{_ as e}from"./main_window-T08x4hNs.js";import{_ as a,o as t,c as n,e as o}from"./app-LOf__QKq.js";const i={},r=o('

3.1 UI Overview

MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules.

The Main Window and Components

Screenshot

Supported Files

MicroCity can open ArcGIS shapefile (*.shp), Grids file (*.sgrd), dBase file (*.dbf), Tabular text file (*.csv, *.txt), Point clouds (*.spc), Image file (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) and MicroCity 3D Scene (*.m3d). These data files are maintained in the Data Tab of the Workspace Panel. Module libraries (*.dll, *.mcs) are maintained and executed through the Modules Tab of the Workspace Panel.

Project Management

The information of opened data files, module libraries, settings and sub-windows can be saved or opened in a MicroCity Project (*.mprj) through the menu File->Project. The mprj file does not contain any file's data. For easy maintenance, files in a project should be put into the same folder or sub-folders of the mprj file.

',8),s=[r];function d(c,h){return t(),n("div",null,s)}const f=a(i,[["render",d],["__file","3.1_ui_overview.html.vue"]]);export{f as default}; diff --git a/assets/3.1_ui_overview.html-9iOHDqCk.js b/assets/3.1_ui_overview.html-9iOHDqCk.js deleted file mode 100644 index 69538a79..00000000 --- a/assets/3.1_ui_overview.html-9iOHDqCk.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-27daeef9","path":"/docs/3.1_ui_overview.html","title":"3.1 用户界面概览","lang":"zh-CN","frontmatter":{"prev":"./2.2_searching_for_countries.md","next":"./3.2_vector_shapes.md","description":"MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules. The Main Window and Components Screenshot Supported Files MicroCity c...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.1_ui_overview.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.1 用户界面概览"}],["meta",{"property":"og:description","content":"MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules. The Main Window and Components Screenshot Supported Files MicroCity c..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.1 用户界面概览"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.1 用户界面概览\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"The Main Window and Components","slug":"the-main-window-and-components","link":"#the-main-window-and-components","children":[]},{"level":2,"title":"Supported Files","slug":"supported-files","link":"#supported-files","children":[]},{"level":2,"title":"Project Management","slug":"project-management","link":"#project-management","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.1_ui_overview.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.1_ui_overview.html-MdRgXeyu.js b/assets/3.1_ui_overview.html-MdRgXeyu.js new file mode 100644 index 00000000..74980faf --- /dev/null +++ b/assets/3.1_ui_overview.html-MdRgXeyu.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-45e45965","path":"/en/docs/3.1_ui_overview.html","title":"3.1 UI Overview","lang":"en-US","frontmatter":{"prev":"./2.2_searching_for_countries.md","next":"./3.2_vector_shapes.md","description":"MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules. The Main Window and Components Screenshot Supported Files MicroCity c...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.1_ui_overview.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.1_ui_overview.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.1 UI Overview"}],["meta",{"property":"og:description","content":"MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules. The Main Window and Components Screenshot Supported Files MicroCity c..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.1 UI Overview\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"The Main Window and Components","slug":"the-main-window-and-components","link":"#the-main-window-and-components","children":[]},{"level":2,"title":"Supported Files","slug":"supported-files","link":"#supported-files","children":[]},{"level":2,"title":"Project Management","slug":"project-management","link":"#project-management","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.1_ui_overview.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.1_ui_overview.html-v38UIHQc.js b/assets/3.1_ui_overview.html-v38UIHQc.js new file mode 100644 index 00000000..63ebea77 --- /dev/null +++ b/assets/3.1_ui_overview.html-v38UIHQc.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-27daeef9","path":"/docs/3.1_ui_overview.html","title":"3.1 用户界面概览","lang":"zh-CN","frontmatter":{"prev":"./2.2_searching_for_countries.md","next":"./3.2_vector_shapes.md","description":"MicroCity提供了一个简洁的图形窗口界面,以便于对数据和模块进行操作。 主窗口及其组件 截图 支持的文件类型 MicroCity可以打开ArcGIS shapefile文件(\\\\*.shp),Grids文件(\\\\*.sgrd),dBase文件(\\\\*.dbf),Tabular文本文件(\\\\*.csv, \\\\*.txt),Point clouds点云文件(\\\\...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.1_ui_overview.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.1_ui_overview.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.1 用户界面概览"}],["meta",{"property":"og:description","content":"MicroCity提供了一个简洁的图形窗口界面,以便于对数据和模块进行操作。 主窗口及其组件 截图 支持的文件类型 MicroCity可以打开ArcGIS shapefile文件(\\\\*.shp),Grids文件(\\\\*.sgrd),dBase文件(\\\\*.dbf),Tabular文本文件(\\\\*.csv, \\\\*.txt),Point clouds点云文件(\\\\..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.1 用户界面概览\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"主窗口及其组件","slug":"主窗口及其组件","link":"#主窗口及其组件","children":[]},{"level":2,"title":"支持的文件类型","slug":"支持的文件类型","link":"#支持的文件类型","children":[]},{"level":2,"title":"项目管理","slug":"项目管理","link":"#项目管理","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.1_ui_overview.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.1_ui_overview.html-w-bvZnF-.js b/assets/3.1_ui_overview.html-w-bvZnF-.js deleted file mode 100644 index e615fefb..00000000 --- a/assets/3.1_ui_overview.html-w-bvZnF-.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,o as a,c as t,e as n}from"./app-DaLjD81q.js";const o="/MicroCityNotes/assets/main_window-kvL2HSJd.png",i={},r=n('

3.1 用户界面概览

MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules.

The Main Window and Components

Screenshot

Supported Files

MicroCity can open ArcGIS shapefile (*.shp), Grids file (*.sgrd), dBase file (*.dbf), Tabular text file (*.csv, *.txt), Point clouds (*.spc), Image file (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) and MicroCity 3D Scene (*.m3d). These data files are maintained in the Data Tab of the Workspace Panel. Module libraries (*.dll, *.mcs) are maintained and executed through the Modules Tab of the Workspace Panel.

Project Management

The information of opened data files, module libraries, settings and sub-windows can be saved or opened in a MicroCity Project (*.mprj) through the menu File->Project. The mprj file does not contain any file's data. For easy maintenance, files in a project should be put into the same folder or sub-folders of the mprj file.

',8),s=[r];function d(c,h){return a(),t("div",null,s)}const p=e(i,[["render",d],["__file","3.1_ui_overview.html.vue"]]);export{p as default}; diff --git a/assets/3.2_vector_shapes.html-Ggy6120F.js b/assets/3.2_vector_shapes.html-Ggy6120F.js new file mode 100644 index 00000000..7121f4b2 --- /dev/null +++ b/assets/3.2_vector_shapes.html-Ggy6120F.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0434254c","path":"/en/docs/3.2_vector_shapes.html","title":"3.2 Vector Shapes","lang":"en-US","frontmatter":{"prev":"./3.1_ui_overview.md","next":"./3.3_raster_grids.md","description":"MicroCity can open, create and edit ArcGIS shapefiles (\\\\*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7 (3.7_modu...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.2_vector_shapes.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.2_vector_shapes.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.2 Vector Shapes"}],["meta",{"property":"og:description","content":"MicroCity can open, create and edit ArcGIS shapefiles (\\\\*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7 (3.7_modu..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.2 Vector Shapes\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing Shapes","slug":"opening-creating-saving-and-closing-shapes","link":"#opening-creating-saving-and-closing-shapes","children":[]},{"level":2,"title":"Showing and Editing Shapes","slug":"showing-and-editing-shapes","link":"#showing-and-editing-shapes","children":[]},{"level":2,"title":"Display Settings and Data Visualization","slug":"display-settings-and-data-visualization","link":"#display-settings-and-data-visualization","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.2_vector_shapes.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.2_vector_shapes.html-Ifn-q5O4.js b/assets/3.2_vector_shapes.html-Ifn-q5O4.js deleted file mode 100644 index ba14f836..00000000 --- a/assets/3.2_vector_shapes.html-Ifn-q5O4.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as n}from"./button_load-GOP3K2yO.js";import{_ as i}from"./icon_shapes_polygon-5WS2EZQN.js";import{_ as r}from"./button_action-tmG_4IgV.js";import{_ as l,r as c,o as h,c as d,a as t,b as s,d as o,w as a,e as g}from"./app-DaLjD81q.js";const _="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARUlEQVR42mNkoBAwDjYD/v9HkmIkLI7NgP8wUTQDsIpT3wUDH4iEAKZXSDcALTAZcSpEs4lEF+CONiLDAHe0URiIg9EAAKjsHBHhPhnUAAAAAElFTkSuQmCC",p="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASUlEQVR42mNkoBAw0sCA//+RpAnKY1fwH2Y0YXlauABuPtweHPI4A5EiA9A1EeJT1wBCTsYqTw0DSIs27AaQkHBo4QLKAMUGAAAloi4RJpgTVwAAAABJRU5ErkJggg==",m="/MicroCityNotes/assets/new_shapes-RVv9IgwR.png",A="/MicroCityNotes/assets/shapes_files-ShfoHRZo.png",u="/MicroCityNotes/assets/shapes_menu-aime3jTY.png",f="/MicroCityNotes/assets/close_save_shapes-bnfKINWq.png",S="/MicroCityNotes/assets/edit_shape-3r72h2cB.png",w="/MicroCityNotes/assets/edit_point-krh9tqYD.png",b={},v=t("h1",{id:"_3-2-矢量图",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-2-矢量图","aria-hidden":"true"},"#"),s(" 3.2 矢量图")],-1),C=t("strong",null,"Shapes",-1),k=t("strong",null,"Data",-1),y=t("strong",null,"Workspace",-1),N=t("strong",null,"modules",-1),B=g('

Opening, Creating, Saving and Closing Shapes

Users can click buttonLoad button or File->Shapes->Load menu item to open an ArcGIS shapefile (*.shp) as a Shapes. Creating a new Shapes can be done from menu File->Shapes->New and the pop-up dialog as shown below. Users can choose one shapes type from icon_shapes_pointPoint, icon_shapes_lineLine and icon_shapes_polygonPolygon. The relationship between a ArcGIS shapefile (*.shp) and a same named dBase file (*.dbf) is also shown.

new shapes    shape_files

Saving a Shapes can be done from the right click context menu Save or Save As. You can also close a Shapes from the menu and get a prompt dialog to save it.

shapes menu    close and save

Showing and Editing Shapes

',6),E=t("strong",null,"Shapes",-1),T=t("strong",null,"Data",-1),x=t("img",{src:r,alt:"button"},null,-1),D=t("strong",null,"Action",-1),U=t("strong",null,"Shape",-1),R=t("strong",null,"Shapes",-1),I=t("strong",null,"Edit Selected Shape",-1),V=t("strong",null,"Editing Mode",-1),Y=t("strong",null,"Shapes",-1),H=t("strong",null,"Attributes->Table->Show",-1),L=t("p",null,[t("img",{src:S,alt:"edit shape"}),s("    "),t("img",{src:w,alt:"edit point"})],-1),M=t("h2",{id:"display-settings-and-data-visualization",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#display-settings-and-data-visualization","aria-hidden":"true"},"#"),s(" Display Settings and Data Visualization")],-1),P=t("strong",null,"Shapes",-1),Q=t("strong",null,"Settings",-1);function G(K,F){const e=c("RouterLink");return h(),d("div",null,[v,t("p",null,[s("MicroCity can open, create and edit ArcGIS shapefiles (*.shp) which are called "),C,s(" and maintained in the "),k,s(" Tab of the "),y,s(" Panel. By using "),N,s(" (see "),o(e,{to:"/docs/3.7_modules.html"},{default:a(()=>[s("3.7")]),_:1}),s(") other vector file formats, such like Scalable Vector Graphics (*.svg) and AutoCAD Drawing Exchange Format (*.dxf), can also be imported or exported.")]),B,t("p",null,[s("Double click a "),E,s(" from the "),T,s(" Tab will give you a map view (for maps and layers see "),o(e,{to:"/docs/3.6_maps_and_layers.html"},{default:a(()=>[s("3.6")]),_:1}),s("). Toggle "),x,D,s(" botton and right click a "),U,s(" in a "),R,s(" layer and choose "),I,s(" then go to the "),V,s(". In this mode users can add/delete parts and add/delete points in a shape (for data structure of a shape see "),o(e,{to:"/docs/2.2_searching_for_countries.html"},{default:a(()=>[s("2.2")]),_:1}),s("). The associated attributes table (*.dbf) of a "),Y,s(" can be accessed through right-clicking context menu "),H,s(" (see the tutorial "),o(e,{to:"/docs/2.1_showing_a_world_map.html"},{default:a(()=>[s("2.1")]),_:1}),s(").")]),L,M,t("p",null,[s("Users can change "),P,s(" outline, fill, labels and other display settins from the "),Q,s(" Panel. Some options can connect attribute data and give visualization functionalities (for example "),o(e,{to:"/docs/2.1_showing_a_world_map.html"},{default:a(()=>[s("2.1")]),_:1}),s(").")])])}const q=l(b,[["render",G],["__file","3.2_vector_shapes.html.vue"]]);export{q as default}; diff --git a/assets/3.2_vector_shapes.html-LHAJ_5Cg.js b/assets/3.2_vector_shapes.html-LHAJ_5Cg.js deleted file mode 100644 index 59b7dd08..00000000 --- a/assets/3.2_vector_shapes.html-LHAJ_5Cg.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-3c8d6dee","path":"/docs/3.2_vector_shapes.html","title":"3.2 矢量图","lang":"zh-CN","frontmatter":{"prev":"./3.1_ui_overview.md","next":"./3.3_raster_grids.md","description":"MicroCity can open, create and edit ArcGIS shapefiles (\\\\*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7 (3.7_modu...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.2_vector_shapes.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.2 矢量图"}],["meta",{"property":"og:description","content":"MicroCity can open, create and edit ArcGIS shapefiles (\\\\*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7 (3.7_modu..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.2 矢量图"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.2 矢量图\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing Shapes","slug":"opening-creating-saving-and-closing-shapes","link":"#opening-creating-saving-and-closing-shapes","children":[]},{"level":2,"title":"Showing and Editing Shapes","slug":"showing-and-editing-shapes","link":"#showing-and-editing-shapes","children":[]},{"level":2,"title":"Display Settings and Data Visualization","slug":"display-settings-and-data-visualization","link":"#display-settings-and-data-visualization","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.2_vector_shapes.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.2_vector_shapes.html-hHGdBrtV.js b/assets/3.2_vector_shapes.html-hHGdBrtV.js new file mode 100644 index 00000000..1ba52961 --- /dev/null +++ b/assets/3.2_vector_shapes.html-hHGdBrtV.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3c8d6dee","path":"/docs/3.2_vector_shapes.html","title":"3.2 矢量图","lang":"zh-CN","frontmatter":{"prev":"./3.1_ui_overview.md","next":"./3.3_raster_grids.md","description":"MicroCity可以打开、创建和编辑ArcGIS shapefiles(\\\\*.shp),即所谓的Shapes,并在Workspace面板的Data选项卡中进行维护。通过使用模块(参见3.7 (3.7_modules.md)),还可以导入或导出其他矢量文件格式,例如可伸缩矢量图形(\\\\*.svg)和AutoCAD绘图交换格式(\\\\*.dxf)。 打开、创建...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.2_vector_shapes.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.2_vector_shapes.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.2 矢量图"}],["meta",{"property":"og:description","content":"MicroCity可以打开、创建和编辑ArcGIS shapefiles(\\\\*.shp),即所谓的Shapes,并在Workspace面板的Data选项卡中进行维护。通过使用模块(参见3.7 (3.7_modules.md)),还可以导入或导出其他矢量文件格式,例如可伸缩矢量图形(\\\\*.svg)和AutoCAD绘图交换格式(\\\\*.dxf)。 打开、创建..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.2 矢量图\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"打开、创建、保存和关闭Shapes","slug":"打开、创建、保存和关闭shapes","link":"#打开、创建、保存和关闭shapes","children":[]},{"level":2,"title":"显示和编辑形状","slug":"显示和编辑形状","link":"#显示和编辑形状","children":[]},{"level":2,"title":"显示设置和数据可视化","slug":"显示设置和数据可视化","link":"#显示设置和数据可视化","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.2_vector_shapes.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.2_vector_shapes.html-o5HA4H30.js b/assets/3.2_vector_shapes.html-o5HA4H30.js new file mode 100644 index 00000000..3a583f85 --- /dev/null +++ b/assets/3.2_vector_shapes.html-o5HA4H30.js @@ -0,0 +1 @@ +import{_ as n}from"./button_load-GOP3K2yO.js";import{_ as i,a as r,b as l,c,d,e as h,f as _,g as p}from"./edit_point-Z0R1Z63o.js";import{_ as g}from"./icon_shapes_polygon-5WS2EZQN.js";import{_ as m}from"./button_action-tmG_4IgV.js";import{_ as u,r as f,o as S,c as b,a as s,b as e,d as a,w as o,e as v}from"./app-LOf__QKq.js";const w={},x=s("h1",{id:"_3-2-vector-shapes",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#_3-2-vector-shapes","aria-hidden":"true"},"#"),e(" 3.2 Vector Shapes")],-1),y=s("strong",null,"Shapes",-1),k=s("strong",null,"Data",-1),A=s("strong",null,"Workspace",-1),C=s("strong",null,"modules",-1),D=v('

Opening, Creating, Saving and Closing Shapes

Users can click buttonLoad button or File->Shapes->Load menu item to open an ArcGIS shapefile (*.shp) as a Shapes. Creating a new Shapes can be done from menu File->Shapes->New and the pop-up dialog as shown below. Users can choose one shapes type from icon_shapes_pointPoint, icon_shapes_lineLine and icon_shapes_polygonPolygon. The relationship between a ArcGIS shapefile (*.shp) and a same named dBase file (*.dbf) is also shown.

new shapes    shape_files

Saving a Shapes can be done from the right click context menu Save or Save As. You can also close a Shapes from the menu and get a prompt dialog to save it.

shapes menu    close and save

Showing and Editing Shapes

',6),T=s("strong",null,"Shapes",-1),V=s("strong",null,"Data",-1),B=s("img",{src:m,alt:"button"},null,-1),E=s("strong",null,"Action",-1),L=s("strong",null,"Shape",-1),N=s("strong",null,"Shapes",-1),z=s("strong",null,"Edit Selected Shape",-1),G=s("strong",null,"Editing Mode",-1),I=s("strong",null,"Shapes",-1),P=s("strong",null,"Attributes->Table->Show",-1),F=s("p",null,[s("img",{src:i,alt:"edit shape"}),e("    "),s("img",{src:r,alt:"edit point"})],-1),U=s("h2",{id:"display-settings-and-data-visualization",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#display-settings-and-data-visualization","aria-hidden":"true"},"#"),e(" Display Settings and Data Visualization")],-1),M=s("strong",null,"Shapes",-1),R=s("strong",null,"Settings",-1);function $(O,W){const t=f("RouterLink");return S(),b("div",null,[x,s("p",null,[e("MicroCity can open, create and edit ArcGIS shapefiles (*.shp) which are called "),y,e(" and maintained in the "),k,e(" Tab of the "),A,e(" Panel. By using "),C,e(" (see "),a(t,{to:"/en/docs/3.7_modules.html"},{default:o(()=>[e("3.7")]),_:1}),e(") other vector file formats, such like Scalable Vector Graphics (*.svg) and AutoCAD Drawing Exchange Format (*.dxf), can also be imported or exported.")]),D,s("p",null,[e("Double click a "),T,e(" from the "),V,e(" Tab will give you a map view (for maps and layers see "),a(t,{to:"/en/docs/3.6_maps_and_layers.html"},{default:o(()=>[e("3.6")]),_:1}),e("). Toggle "),B,E,e(" botton and right click a "),L,e(" in a "),N,e(" layer and choose "),z,e(" then go to the "),G,e(". In this mode users can add/delete parts and add/delete points in a shape (for data structure of a shape see "),a(t,{to:"/en/docs/2.2_searching_for_countries.html"},{default:o(()=>[e("2.2")]),_:1}),e("). The associated attributes table (*.dbf) of a "),I,e(" can be accessed through right-clicking context menu "),P,e(" (see the tutorial "),a(t,{to:"/en/docs/2.1_showing_a_world_map.html"},{default:o(()=>[e("2.1")]),_:1}),e(").")]),F,U,s("p",null,[e("Users can change "),M,e(" outline, fill, labels and other display settins from the "),R,e(" Panel. Some options can connect attribute data and give visualization functionalities (for example "),a(t,{to:"/en/docs/2.1_showing_a_world_map.html"},{default:o(()=>[e("2.1")]),_:1}),e(").")])])}const K=u(w,[["render",$],["__file","3.2_vector_shapes.html.vue"]]);export{K as default}; diff --git a/assets/3.2_vector_shapes.html-uMTzJRD1.js b/assets/3.2_vector_shapes.html-uMTzJRD1.js new file mode 100644 index 00000000..d9f9431c --- /dev/null +++ b/assets/3.2_vector_shapes.html-uMTzJRD1.js @@ -0,0 +1 @@ +import{_ as a}from"./button_load-GOP3K2yO.js";import{_ as l,a as i,b as h,c,d,e as p,f as g,g as m}from"./edit_point-Z0R1Z63o.js";import{_ as u}from"./icon_shapes_polygon-5WS2EZQN.js";import{_ as f}from"./button_action-tmG_4IgV.js";import{_ as b,r,o as x,c as S,a as t,b as s,d as o,w as n,e as k}from"./app-LOf__QKq.js";const w={},v=t("h1",{id:"_3-2-矢量图",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-2-矢量图","aria-hidden":"true"},"#"),s(" 3.2 矢量图")],-1),C=t("strong",null,"Shapes",-1),y=t("strong",null,"Workspace",-1),A=t("strong",null,"Data",-1),I=t("strong",null,"模块",-1),N=k('

打开、创建、保存和关闭Shapes

用户可以单击button加载按钮或文件->Shapes->加载菜单项来打开ArcGIS shapefile(*.shp)作为Shapes。从菜单中选择文件->Shapes->新建,弹出对话框如下所示,可以创建新的Shapes。用户可以从icon_shapes_pointicon_shapes_line线icon_shapes_polygon中选择其中一种形状类型。还显示了ArcGIS shapefile(*.shp)与同名dBase文件(*.dbf)之间的关系。

new shapes    shape_files

保存Shapes可以通过右键单击上下文菜单中的保存或另存为来完成。也可以从菜单中关闭Shapes并弹出提示对话框以保存它。

shapes menu    close and save

显示和编辑形状

',6),B=t("strong",null,"数据",-1),G=t("strong",null,"形状",-1),L=t("img",{src:f,alt:"按钮"},null,-1),V=t("strong",null,"操作",-1),E=t("strong",null,"形状",-1),D=t("strong",null,"形状",-1),M=t("strong",null,"编辑所选形状",-1),R=t("strong",null,"编辑模式",-1),T=t("strong",null,"属性->表格->显示",-1),$=t("strong",null,"形状",-1),q=t("p",null,[t("img",{src:l,alt:"编辑形状"}),s("    "),t("img",{src:i,alt:"编辑点"})],-1),P=t("h2",{id:"显示设置和数据可视化",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#显示设置和数据可视化","aria-hidden":"true"},"#"),s(" 显示设置和数据可视化")],-1),W=t("strong",null,"设置",-1),j=t("strong",null,"形状",-1),z={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},F=t("strong",null,"反馈",-1);function H(J,K){const e=r("RouterLink"),_=r("ExternalLinkIcon");return x(),S("div",null,[v,t("p",null,[s("MicroCity可以打开、创建和编辑ArcGIS shapefiles(*.shp),即所谓的"),C,s(",并在"),y,s("面板的"),A,s("选项卡中进行维护。通过使用"),I,s("(参见"),o(e,{to:"/docs/3.7_modules.html"},{default:n(()=>[s("3.7")]),_:1}),s("),还可以导入或导出其他矢量文件格式,例如可伸缩矢量图形(*.svg)和AutoCAD绘图交换格式(*.dxf)。")]),N,t("p",null,[s("在"),B,s("选项卡中双击一个"),G,s("将为您提供地图视图(有关地图和图层,请参见"),o(e,{to:"/docs/3.6_maps_and_layers.html"},{default:n(()=>[s("3.6")]),_:1}),s(")。切换到"),L,V,s("按钮,然后右键单击"),E,s("图层中的一个"),D,s(",选择"),M,s(",然后进入"),R,s("。在这个模式下,用户可以添加/删除部分以及添加/删除形状中的点(关于形状的数据结构,请参见"),o(e,{to:"/docs/2.2_searching_for_countries.html"},{default:n(()=>[s("2.2")]),_:1}),s(")。通过右键单击上下文菜单"),T,s("可以访问"),$,s("的相关属性表格(*.dbf)(请参见教程"),o(e,{to:"/docs/2.1_showing_a_world_map.html"},{default:n(()=>[s("2.1")]),_:1}),s(")。")]),q,P,t("p",null,[s("用户可以从"),W,s("面板中更改"),j,s("的轮廓、填充、标签和其他显示设置。一些选项可以连接属性数据并提供可视化功能(例如"),o(e,{to:"/docs/2.1_showing_a_world_map.html"},{default:n(()=>[s("2.1")]),_:1}),s(")。")]),t("blockquote",null,[t("p",null,[s("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",z,[F,o(_)]),s("页面提交反馈。")])])])}const Z=b(w,[["render",H],["__file","3.2_vector_shapes.html.vue"]]);export{Z as default}; diff --git a/assets/3.3_raster_grids.html-KMfHWMMp.js b/assets/3.3_raster_grids.html-KMfHWMMp.js new file mode 100644 index 00000000..3d96848e --- /dev/null +++ b/assets/3.3_raster_grids.html-KMfHWMMp.js @@ -0,0 +1 @@ +import{_ as r}from"./button_load-GOP3K2yO.js";import{_ as a,a as i,b as d,c as l,d as c,e as g}from"./grid_attributes-xxRYXyrC.js";import{_}from"./button_action-tmG_4IgV.js";import{_ as h}from"./button_3d-coWyniAs.js";import{_ as u,r as m,o as p,c as f,a as e,b as t,d as n,w as o,e as b}from"./app-LOf__QKq.js";const v={},G=e("h1",{id:"_3-3-raster-grids",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-3-raster-grids","aria-hidden":"true"},"#"),t(" 3.3 Raster Grids")],-1),w=e("strong",null,"Grid",-1),x=e("strong",null,"Data",-1),S=e("strong",null,"Workspace",-1),y=e("strong",null,"Grid",-1),k=e("strong",null,"modules",-1),C=b('

Opening, Creating, Saving and Closing Grids

Users can click buttonLoad button or File->Grid->Load menu item to open a Grid. Creating new Grid can be done from menu File->Grid->New and the pop-up dialog:

new grid    grid_structure The above right figure is the data structure and definitions of a Grid. A Grid starts from its bottom left corner which has coordinate (xMin, yMin), contains NX*NY Square Cells. Each cell has its own Integer Coordinate (X, Y), in the range of (0, 0) to (XMax, YMax).

Saving Grid can be done from the right click context menu Save or Save As. You can also close a Grid from the menu and get a prompt dialog to save it.

grid menu    close and save

Showing and Editing Grids

',6),A=e("strong",null,"Grid",-1),N=e("strong",null,"Data",-1),T=e("strong",null,"Action",-1),D=e("img",{src:_,alt:"button"},null,-1),M=e("strong",null,"Grid",-1),V=e("strong",null,"Attributes",-1),B=e("strong",null,"Settings",-1),E=e("p",null,[e("img",{src:a,alt:"grid selection"}),t("    "),e("img",{src:i,alt:"grid_attributes"})],-1),I=e("h2",{id:"display-settings-and-3d-view",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#display-settings-and-3d-view","aria-hidden":"true"},"#"),t(" Display Settings and 3D View")],-1),L=e("strong",null,"Grid",-1),R=e("strong",null,"Settings",-1),Y=e("img",{src:h,alt:"button"},null,-1),P=e("strong",null,"Grid",-1);function U(X,F){const s=m("RouterLink");return p(),f("div",null,[G,e("p",null,[t("MicroCity can open, create and edit SAGA Grid (*.sgrd) which is called "),w,t(" and maintained in the "),x,t(" Tab of the "),S,t(" Panel. Image files (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) can be opened as "),y,t(" as well. By using "),k,t(" (see "),n(s,{to:"/en/docs/3.7_modules.html"},{default:o(()=>[t("3.7")]),_:1}),t(") other raster file formats, such like ESRI Arc/Info Grid (*.adf) and Surfer Grid (*.grd), can also be imported or exported.")]),C,e("p",null,[t("Double click a "),A,t(" from the "),N,t(" Tab will give you a map view (for maps and layers see "),n(s,{to:"/en/docs/3.6_maps_and_layers.html"},{default:o(()=>[t("3.6")]),_:1}),t("). Toggle "),T,t(" botton "),D,t(" and select a range of cells in a "),M,t(". Then the value of these cells can be edited in the "),V,t(" Tab of the "),B,t(" Panel.")]),E,I,e("p",null,[t("Users can show cell values, change color and set transparency of a "),L,t(" by using "),R,t(" Panel. Using "),Y,t(" button can creat a 3D surface of a "),P,t(" in which cell values are translated to elevation (see "),n(s,{to:"/en/docs/3.6_maps_and_layers.html#controlling-map-views"},{default:o(()=>[t("3.6")]),_:1}),t(").")])])}const z=u(v,[["render",U],["__file","3.3_raster_grids.html.vue"]]);export{z as default}; diff --git a/assets/3.3_raster_grids.html-OMCyU_6r.js b/assets/3.3_raster_grids.html-OMCyU_6r.js new file mode 100644 index 00000000..d48f049d --- /dev/null +++ b/assets/3.3_raster_grids.html-OMCyU_6r.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-6a2d64ac","path":"/docs/3.3_raster_grids.html","title":"3.3 栅格图","lang":"zh-CN","frontmatter":{"prev":"./3.2_vector_shapes.md","next":"./3.4_3d_scenes.md","description":"MicroCity可以打开、创建和编辑SAGA Grid(\\\\*.sgrd),在工作空间面板的数据选项卡中被称为Grid并进行维护。图像文件(\\\\*.bmp、\\\\*.gif、\\\\*.jpg、\\\\*.png、\\\\*.tif、\\\\*.pcx)也可以被作为Grid打开。通过使用模块(参见[3.7](3.7_modules.md)),其他栅格文件格式,例如ESRI Arc/...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.3_raster_grids.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.3_raster_grids.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.3 栅格图"}],["meta",{"property":"og:description","content":"MicroCity可以打开、创建和编辑SAGA Grid(\\\\*.sgrd),在工作空间面板的数据选项卡中被称为Grid并进行维护。图像文件(\\\\*.bmp、\\\\*.gif、\\\\*.jpg、\\\\*.png、\\\\*.tif、\\\\*.pcx)也可以被作为Grid打开。通过使用模块(参见[3.7](3.7_modules.md)),其他栅格文件格式,例如ESRI Arc/..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.3 栅格图\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"打开、创建、保存和关闭Grid","slug":"打开、创建、保存和关闭grid","link":"#打开、创建、保存和关闭grid","children":[]},{"level":2,"title":"显示和编辑Grids","slug":"显示和编辑grids","link":"#显示和编辑grids","children":[]},{"level":2,"title":"显示设置和3D视图","slug":"显示设置和3d视图","link":"#显示设置和3d视图","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.3_raster_grids.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.3_raster_grids.html-RHwKcATS.js b/assets/3.3_raster_grids.html-RHwKcATS.js deleted file mode 100644 index 95f2fd86..00000000 --- a/assets/3.3_raster_grids.html-RHwKcATS.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as i}from"./button_load-GOP3K2yO.js";import{_ as r}from"./button_action-tmG_4IgV.js";import{_ as a}from"./button_3d-coWyniAs.js";import{_ as d,r as l,o as c,c as g,a as s,b as t,d as n,w as o,e as _}from"./app-DaLjD81q.js";const h="/MicroCityNotes/assets/new_grid-4i1mP770.png",u="/MicroCityNotes/assets/grid_structure-vhTlEgf-.png",m="/MicroCityNotes/assets/grid_menu-7jPQkAi1.png",p="/MicroCityNotes/assets/close_save_grid-mxdTfyrH.png",f="/MicroCityNotes/assets/grid_selection-bdt61Cd7.png",b="/MicroCityNotes/assets/grid_attributes-e5wa0ZGb.png",v={},w=s("h1",{id:"_3-3-栅格图",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#_3-3-栅格图","aria-hidden":"true"},"#"),t(" 3.3 栅格图")],-1),G=s("strong",null,"Grid",-1),y=s("strong",null,"Data",-1),x=s("strong",null,"Workspace",-1),C=s("strong",null,"Grid",-1),N=s("strong",null,"modules",-1),S=_('

Opening, Creating, Saving and Closing Grids

Users can click buttonLoad button or File->Grid->Load menu item to open a Grid. Creating new Grid can be done from menu File->Grid->New and the pop-up dialog:

new grid    grid_structure The above right figure is the data structure and definitions of a Grid. A Grid starts from its bottom left corner which has coordinate (xMin, yMin), contains NX*NY Square Cells. Each cell has its own Integer Coordinate (X, Y), in the range of (0, 0) to (XMax, YMax).

Saving Grid can be done from the right click context menu Save or Save As. You can also close a Grid from the menu and get a prompt dialog to save it.

grid menu    close and save

Showing and Editing Grids

',6),M=s("strong",null,"Grid",-1),k=s("strong",null,"Data",-1),T=s("strong",null,"Action",-1),A=s("img",{src:r,alt:"button"},null,-1),D=s("strong",null,"Grid",-1),E=s("strong",null,"Attributes",-1),P=s("strong",null,"Settings",-1),V=s("p",null,[s("img",{src:f,alt:"grid selection"}),t("    "),s("img",{src:b,alt:"grid_attributes"})],-1),B=s("h2",{id:"display-settings-and-3d-view",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#display-settings-and-3d-view","aria-hidden":"true"},"#"),t(" Display Settings and 3D View")],-1),I=s("strong",null,"Grid",-1),L=s("strong",null,"Settings",-1),Y=s("img",{src:a,alt:"button"},null,-1),R=s("strong",null,"Grid",-1);function U(X,j){const e=l("RouterLink");return c(),g("div",null,[w,s("p",null,[t("MicroCity can open, create and edit SAGA Grid (*.sgrd) which is called "),G,t(" and maintained in the "),y,t(" Tab of the "),x,t(" Panel. Image files (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) can be opened as "),C,t(" as well. By using "),N,t(" (see "),n(e,{to:"/docs/3.7_modules.html"},{default:o(()=>[t("3.7")]),_:1}),t(") other raster file formats, such like ESRI Arc/Info Grid (*.adf) and Surfer Grid (*.grd), can also be imported or exported.")]),S,s("p",null,[t("Double click a "),M,t(" from the "),k,t(" Tab will give you a map view (for maps and layers see "),n(e,{to:"/docs/3.6_maps_and_layers.html"},{default:o(()=>[t("3.6")]),_:1}),t("). Toggle "),T,t(" botton "),A,t(" and select a range of cells in a "),D,t(". Then the value of these cells can be edited in the "),E,t(" Tab of the "),P,t(" Panel.")]),V,B,s("p",null,[t("Users can show cell values, change color and set transparency of a "),I,t(" by using "),L,t(" Panel. Using "),Y,t(" button can creat a 3D surface of a "),R,t(" in which cell values are translated to elevation (see "),n(e,{to:"/docs/3.6_maps_and_layers.html#controlling-map-views"},{default:o(()=>[t("3.6")]),_:1}),t(").")])])}const O=d(v,[["render",U],["__file","3.3_raster_grids.html.vue"]]);export{O as default}; diff --git a/assets/3.3_raster_grids.html-_OMWjBic.js b/assets/3.3_raster_grids.html-_OMWjBic.js new file mode 100644 index 00000000..862413b2 --- /dev/null +++ b/assets/3.3_raster_grids.html-_OMWjBic.js @@ -0,0 +1 @@ +import{_ as a}from"./button_load-GOP3K2yO.js";import{_ as d,a as _,b as l,c,d as g,e as h}from"./grid_attributes-xxRYXyrC.js";import{_ as m}from"./button_action-tmG_4IgV.js";import{_ as p}from"./button_3d-coWyniAs.js";import{_ as u,r as n,o as f,c as G,a as t,b as r,d as s,w as e,e as x}from"./app-LOf__QKq.js";const b={},k=x('

3.3 栅格图

MicroCity可以打开、创建和编辑SAGA Grid(*.sgrd),在工作空间面板数据选项卡中被称为Grid并进行维护。图像文件(*.bmp、*.gif、*.jpg、*.png、*.tif、*.pcx)也可以被作为Grid打开。通过使用模块(参见[3.7](3.7_modules.md)),其他栅格文件格式,例如ESRI Arc/Info Grid(*.adf)和Surfer Grid(*.grd),也可以被导入或导出。

打开、创建、保存和关闭Grid

用户可以点击按钮Load按钮或File->Grid->Load菜单项来打开一个Grid。从菜单File->Grid->New中可以创建一个新的Grid,然后弹出对话框:

new grid    grid_structure

上图是一个Grid的数据结构和定义。Grid从其左下角开始,具有坐标**(xMin, yMin),包含NX*NY个方形单元格**。每个单元格有自己的整数坐标(X, Y),范围从(0, 0)到(XMax, YMax)。

保存Grid可通过右键上下文菜单Save or Save As来完成。也可以通过菜单关闭Grid,并获得一个提示对话框来保存它。

grid menu    close and save

显示和编辑Grids

',9),N=t("strong",null,"数据",-1),v=t("strong",null,"Grid",-1),w=t("strong",null,"Action",-1),y=t("img",{src:m,alt:"按钮"},null,-1),L=t("strong",null,"Grid",-1),M=t("strong",null,"设置面板",-1),S=t("strong",null,"属性",-1),A=t("p",null,[t("img",{src:d,alt:"grid selection"}),r("    "),t("img",{src:_,alt:"grid_attributes"})],-1),C=t("h2",{id:"显示设置和3d视图",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#显示设置和3d视图","aria-hidden":"true"},"#"),r(" 显示设置和3D视图")],-1),E=t("strong",null,"设置",-1),I=t("strong",null,"网格",-1),V=t("img",{src:p,alt:"button"},null,-1),B=t("strong",null,"网格",-1),R={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},X=t("strong",null,"反馈",-1);function Y(D,F){const o=n("RouterLink"),i=n("ExternalLinkIcon");return f(),G("div",null,[k,t("p",null,[r("双击"),N,r("选项卡中的一个"),v,r("将为您提供一个地图视图(有关地图和图层,请参见"),s(o,{to:"/docs/3.6_maps_and_layers.html"},{default:e(()=>[r("3.6")]),_:1}),r(")。切换"),w,r("按钮 "),y,r(",然后在"),L,r("中选择一系列单元格。然后可以在"),M,r("的"),S,r("选项卡中编辑这些单元格的值。")]),A,C,t("p",null,[r("用户可以使用"),E,r("面板来显示单元格的值,更改颜色并设置"),I,r("的透明度。使用"),V,r("按钮可以创建一个"),B,r("的3D表面,其中单元格的值被转换为高程(见"),s(o,{to:"/docs/3.6_maps_and_layers.html#controlling-map-views"},{default:e(()=>[r("3.6")]),_:1}),r(")。")]),t("blockquote",null,[t("p",null,[r("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",R,[X,s(i)]),r("页面提交反馈。")])])])}const z=u(b,[["render",Y],["__file","3.3_raster_grids.html.vue"]]);export{z as default}; diff --git a/assets/3.3_raster_grids.html-t2xEoSZE.js b/assets/3.3_raster_grids.html-t2xEoSZE.js new file mode 100644 index 00000000..4b702550 --- /dev/null +++ b/assets/3.3_raster_grids.html-t2xEoSZE.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0d5147c0","path":"/en/docs/3.3_raster_grids.html","title":"3.3 Raster Grids","lang":"en-US","frontmatter":{"prev":"./3.2_vector_shapes.md","next":"./3.4_3d_scenes.md","description":"MicroCity can open, create and edit SAGA Grid (\\\\*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (\\\\*.bmp, \\\\*.gif, \\\\*.jpg, \\\\*.png, ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.3_raster_grids.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.3_raster_grids.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.3 Raster Grids"}],["meta",{"property":"og:description","content":"MicroCity can open, create and edit SAGA Grid (\\\\*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (\\\\*.bmp, \\\\*.gif, \\\\*.jpg, \\\\*.png, ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.3 Raster Grids\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing Grids","slug":"opening-creating-saving-and-closing-grids","link":"#opening-creating-saving-and-closing-grids","children":[]},{"level":2,"title":"Showing and Editing Grids","slug":"showing-and-editing-grids","link":"#showing-and-editing-grids","children":[]},{"level":2,"title":"Display Settings and 3D View","slug":"display-settings-and-3d-view","link":"#display-settings-and-3d-view","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.3_raster_grids.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.3_raster_grids.html-xKWq9pqo.js b/assets/3.3_raster_grids.html-xKWq9pqo.js deleted file mode 100644 index 22f6e9a4..00000000 --- a/assets/3.3_raster_grids.html-xKWq9pqo.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-6a2d64ac","path":"/docs/3.3_raster_grids.html","title":"3.3 栅格图","lang":"zh-CN","frontmatter":{"prev":"./3.2_vector_shapes.md","next":"./3.4_3d_scenes.md","description":"MicroCity can open, create and edit SAGA Grid (\\\\*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (\\\\*.bmp, \\\\*.gif, \\\\*.jpg, \\\\*.png, ...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.3_raster_grids.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.3 栅格图"}],["meta",{"property":"og:description","content":"MicroCity can open, create and edit SAGA Grid (\\\\*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (\\\\*.bmp, \\\\*.gif, \\\\*.jpg, \\\\*.png, ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.3 栅格图"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.3 栅格图\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing Grids","slug":"opening-creating-saving-and-closing-grids","link":"#opening-creating-saving-and-closing-grids","children":[]},{"level":2,"title":"Showing and Editing Grids","slug":"showing-and-editing-grids","link":"#showing-and-editing-grids","children":[]},{"level":2,"title":"Display Settings and 3D View","slug":"display-settings-and-3d-view","link":"#display-settings-and-3d-view","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.3_raster_grids.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.4_3d_scenes.html-2qe1Dffq.js b/assets/3.4_3d_scenes.html-2qe1Dffq.js new file mode 100644 index 00000000..ca387727 --- /dev/null +++ b/assets/3.4_3d_scenes.html-2qe1Dffq.js @@ -0,0 +1 @@ +import{_ as e}from"./button_load-GOP3K2yO.js";import{_ as n,a as t,b as o,c as s}from"./scene_coordinate-_YCPy6or.js";import{_ as a,o as r,c as i,e as c}from"./app-LOf__QKq.js";const g={},d=c('

3.4 3D Scenes

MicroCity 3D Scene (*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (*.3ds), Wavefront OBJ (*.obj) and Stereolithography (*.stl) can be loaded as objects in a scene (see below) but not be stored in the .m3d file.

Opening, Creating, Saving and Closing 3D Scenes

Users can click Load button button or File->Scene->Load menu item to open a Scene. Creating new Scene can be done from menu File->Scene->New and fill the pop-up dialog as shown below. After pressing Okay button an item will appear in the Data Tab of the Workspace Panel. Then Scene can be saved or closed through right-click menu:

new scene    scene_menu

Showing and Editing 3D Scenes

Double click a Scene from the Data tab will give you a scene view. Left-mouse-dragging in a scene veiw will rotate the camera and right-mouse-dragging will translate the camera. Double-left-clicking a scene view can select objects and Double-right-clicking a scene view can popup a context menu (shown below). One can add objects, load objects and set objects, etc.. Note that the Rotation in the coordinate system should obey Left-hand rule. The illustration of the coordinate system and an example of the rotation around y-axis is shown below:

object_menu    scene_coordinate

The coordinate used in the position and rotation of an object is relative to its parent object. By default, the parent of a new object is null.

Display Settings

Users can change the background color, reference grid or other display options of a Scene by using Settings Panel.

',11),l=[d];function h(p,m){return r(),i("div",null,l)}const b=a(g,[["render",h],["__file","3.4_3d_scenes.html.vue"]]);export{b as default}; diff --git a/assets/3.4_3d_scenes.html-E-00tpZF.js b/assets/3.4_3d_scenes.html-E-00tpZF.js new file mode 100644 index 00000000..c3403cfa --- /dev/null +++ b/assets/3.4_3d_scenes.html-E-00tpZF.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-26445025","path":"/docs/3.4_3d_scenes.html","title":"3.4 3D场景","lang":"zh-CN","frontmatter":{"prev":"./3.3_raster_grids.md","next":"./3.5_tables.md","description":"MicroCity 3D场景(\\\\*.m3d)是一种存储3D场景信息的数据文件格式。流行的3D文件格式包括3D Studio Max(\\\\*.3ds),Wavefront OBJ(\\\\*.obj)和立体光刻(\\\\*.stl)可以作为场景中的对象进行加载(详见下文中的显示和编辑3D场景 (#显示和编辑3D场景)),但不能存储在.m3d文件中。 打开、创建、保存和...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.4_3d_scenes.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.4_3d_scenes.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.4 3D场景"}],["meta",{"property":"og:description","content":"MicroCity 3D场景(\\\\*.m3d)是一种存储3D场景信息的数据文件格式。流行的3D文件格式包括3D Studio Max(\\\\*.3ds),Wavefront OBJ(\\\\*.obj)和立体光刻(\\\\*.stl)可以作为场景中的对象进行加载(详见下文中的显示和编辑3D场景 (#显示和编辑3D场景)),但不能存储在.m3d文件中。 打开、创建、保存和..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.4 3D场景\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"打开、创建、保存和关闭3D场景","slug":"打开、创建、保存和关闭3d场景","link":"#打开、创建、保存和关闭3d场景","children":[]},{"level":2,"title":"显示和编辑3D场景","slug":"显示和编辑3d场景","link":"#显示和编辑3d场景","children":[]},{"level":2,"title":"显示设置","slug":"显示设置","link":"#显示设置","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.4_3d_scenes.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.4_3d_scenes.html-IfcyMMcw.js b/assets/3.4_3d_scenes.html-IfcyMMcw.js new file mode 100644 index 00000000..da7809a8 --- /dev/null +++ b/assets/3.4_3d_scenes.html-IfcyMMcw.js @@ -0,0 +1 @@ +import{_ as o}from"./button_load-GOP3K2yO.js";import{_ as n,a as e,b as a,c as g}from"./scene_coordinate-_YCPy6or.js";import{_ as c,r as i,o as d,c as _,a as t,b as r,d as h,e as l}from"./app-LOf__QKq.js";const p={},m=l('

3.4 3D场景

MicroCity 3D场景(*.m3d)是一种存储3D场景信息的数据文件格式。流行的3D文件格式包括3D Studio Max(*.3ds),Wavefront OBJ(*.obj)和立体光刻(*.stl)可以作为场景中的对象进行加载(详见下文中的显示和编辑3D场景),但不能存储在.m3d文件中。

打开、创建、保存和关闭3D场景

用户可以点击加载按钮 button,或选择文件->场景->加载菜单项来打开一个场景。从菜单项文件->场景->新建可以创建新的场景并填写弹出对话框中的信息,如下所示。点击确定按钮之后,工作区面板数据选项卡中会出现一个项目。然后可以通过右键单击菜单来保存关闭场景:

new scene    scene_menu

显示和编辑3D场景

数据选项卡双击一个场景会显示一个场景视图。在场景视图中,用鼠标左键拖拽可以旋转相机,用鼠标右键拖拽可以平移相机。在场景视图上用双击左键可以选择对象,在场景视图上用双击右键可以弹出上下文菜单(如下图所示)。可以添加对象、加载对象和设置对象等等。请注意,坐标系中的旋转应该遵循左手规则。下图展示了坐标系的示例和沿y轴旋转的示例:

object_menu    scene_coordinate

在对象的位置和旋转中使用的坐标是相对于其父对象的。默认情况下,新对象的父对象为空。

显示设置

用户可以通过使用设置面板更改场景的背景色、参考网格或其他显示选项。

',11),u={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},f=t("strong",null,"反馈",-1);function b(E,x){const s=i("ExternalLinkIcon");return d(),_("div",null,[m,t("blockquote",null,[t("p",null,[r("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",u,[f,h(s)]),r("页面提交反馈。")])])])}const k=c(p,[["render",b],["__file","3.4_3d_scenes.html.vue"]]);export{k as default}; diff --git a/assets/3.4_3d_scenes.html-Q6eGIaTn.js b/assets/3.4_3d_scenes.html-Q6eGIaTn.js new file mode 100644 index 00000000..084a1af0 --- /dev/null +++ b/assets/3.4_3d_scenes.html-Q6eGIaTn.js @@ -0,0 +1 @@ +const e=JSON.parse(`{"key":"v-5e3d6591","path":"/en/docs/3.4_3d_scenes.html","title":"3.4 3D Scenes","lang":"en-US","frontmatter":{"prev":"./3.3_raster_grids.md","next":"./3.5_tables.md","description":"MicroCity 3D Scene (\\\\*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (\\\\*.3ds), Wavefront OBJ (\\\\*.obj) and Stereolit...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.4_3d_scenes.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.4_3d_scenes.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.4 3D Scenes"}],["meta",{"property":"og:description","content":"MicroCity 3D Scene (\\\\*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (\\\\*.3ds), Wavefront OBJ (\\\\*.obj) and Stereolit..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.4 3D Scenes\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing 3D Scenes","slug":"opening-creating-saving-and-closing-3d-scenes","link":"#opening-creating-saving-and-closing-3d-scenes","children":[]},{"level":2,"title":"Showing and Editing 3D Scenes","slug":"showing-and-editing-3d-scenes","link":"#showing-and-editing-3d-scenes","children":[]},{"level":2,"title":"Display Settings","slug":"display-settings","link":"#display-settings","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.4_3d_scenes.md","autoDesc":true}`);export{e as data}; diff --git a/assets/3.4_3d_scenes.html-SpQlhrPf.js b/assets/3.4_3d_scenes.html-SpQlhrPf.js deleted file mode 100644 index ca8e7498..00000000 --- a/assets/3.4_3d_scenes.html-SpQlhrPf.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse(`{"key":"v-26445025","path":"/docs/3.4_3d_scenes.html","title":"3.4 3D场景","lang":"zh-CN","frontmatter":{"prev":"./3.3_raster_grids.md","next":"./3.5_tables.md","description":"MicroCity 3D Scene (\\\\*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (\\\\*.3ds), Wavefront OBJ (\\\\*.obj) and Stereolit...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.4_3d_scenes.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.4 3D场景"}],["meta",{"property":"og:description","content":"MicroCity 3D Scene (\\\\*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (\\\\*.3ds), Wavefront OBJ (\\\\*.obj) and Stereolit..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.4 3D场景"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.4 3D场景\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing 3D Scenes","slug":"opening-creating-saving-and-closing-3d-scenes","link":"#opening-creating-saving-and-closing-3d-scenes","children":[]},{"level":2,"title":"Showing and Editing 3D Scenes","slug":"showing-and-editing-3d-scenes","link":"#showing-and-editing-3d-scenes","children":[]},{"level":2,"title":"Display Settings","slug":"display-settings","link":"#display-settings","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.4_3d_scenes.md","autoDesc":true}`);export{t as data}; diff --git a/assets/3.4_3d_scenes.html-f5Qwa3ic.js b/assets/3.4_3d_scenes.html-f5Qwa3ic.js deleted file mode 100644 index 27d48288..00000000 --- a/assets/3.4_3d_scenes.html-f5Qwa3ic.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e}from"./button_load-GOP3K2yO.js";import{_ as n,o as t,c as o,e as s}from"./app-DaLjD81q.js";const a="/MicroCityNotes/assets/new_scene-8_vgmKnR.png",r="/MicroCityNotes/assets/scene_menu-RSZKJk7N.png",i="/MicroCityNotes/assets/object_menu-rLYhy67y.png",c="/MicroCityNotes/assets/scene_coordinate-muj-oFBk.png",g={},d=s('

3.4 3D场景

MicroCity 3D Scene (*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (*.3ds), Wavefront OBJ (*.obj) and Stereolithography (*.stl) can be loaded as objects in a scene (see below) but not be stored in the .m3d file.

Opening, Creating, Saving and Closing 3D Scenes

Users can click Load button button or File->Scene->Load menu item to open a Scene. Creating new Scene can be done from menu File->Scene->New and fill the pop-up dialog as shown below. After pressing Okay button an item will appear in the Data Tab of the Workspace Panel. Then Scene can be saved or closed through right-click menu:

new scene    scene_menu

Showing and Editing 3D Scenes

Double click a Scene from the Data tab will give you a scene view. Left-mouse-dragging in a scene veiw will rotate the camera and right-mouse-dragging will translate the camera. Double-left-clicking a scene view can select objects and Double-right-clicking a scene view can popup a context menu (shown below). One can add objects, load objects and set objects, etc.. Note that the Rotation in the coordinate system should obey Left-hand rule. The illustration of the coordinate system and an example of the rotation around y-axis is shown below:

object_menu    scene_coordinate

The coordinate used in the position and rotation of an object is relative to its parent object. By default, the parent of a new object is null.

Display Settings

Users can change the background color, reference grid or other display options of a Scene by using Settings Panel.

',11),l=[d];function h(p,m){return t(),o("div",null,l)}const b=n(g,[["render",h],["__file","3.4_3d_scenes.html.vue"]]);export{b as default}; diff --git a/assets/3.5_tables.html-KMEBPMHz.js b/assets/3.5_tables.html-KMEBPMHz.js new file mode 100644 index 00000000..fa059427 --- /dev/null +++ b/assets/3.5_tables.html-KMEBPMHz.js @@ -0,0 +1 @@ +import{_ as e}from"./button_load-GOP3K2yO.js";import{_ as a,a as t,b as n,c as o}from"./add_field-ZFhY51wb.js";import{_ as s,o as i,c as r,e as l}from"./app-LOf__QKq.js";const c={},d=l('

3.5 Tables

Tabular files including dBase files (*.dbf), Text file (*.txt) and Comma Separated Values (*.csv) can be opened as Table and saved with MicroCity.

Opening, Creating, Saving and Closing Tables

Users can click Load button button or File->Table->Load menu item to open a tabular file. Creating a new Table can be done from menu File->Table->New and the pop-up dialog as shown below. Saving a Table can be done from the right click context menu Save or Save As.

new table    table_menu

Showing and Editing Tables

Double click a Table from the Data Tab will give you a table view. Altering a table's stucture can be done by right click the table's head. If you click "Add Field" then, a dialog which guide you (as shown below). If you want insert a record to the table, you can right click the left numbers of the table and select a context menu item.

table_view_menu    add_field

',8),g=[d];function b(h,_){return i(),r("div",null,g)}const f=s(c,[["render",b],["__file","3.5_tables.html.vue"]]);export{f as default}; diff --git a/assets/3.5_tables.html-LpE0kpTR.js b/assets/3.5_tables.html-LpE0kpTR.js new file mode 100644 index 00000000..70fe3548 --- /dev/null +++ b/assets/3.5_tables.html-LpE0kpTR.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-b2a5ca98","path":"/docs/3.5_tables.html","title":"3.5 表格","lang":"zh-CN","frontmatter":{"prev":"./3.4_3d_scenes.md","next":"./3.6_maps_and_layers.md","description":"包括 dBase 文件 (\\\\*.dbf)、文本文件 (\\\\*.txt) 和逗号分隔值 (\\\\*.csv) 在内的表格文件可以在 MicroCity 中打开并保存为表格。 打开、创建、保存和关闭表格 用户可以单击加载按钮 !button (../images/doc/button_load.png),或选择文件->表格->加载菜单项来打开一个表格文件。可以从...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.5_tables.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.5_tables.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.5 表格"}],["meta",{"property":"og:description","content":"包括 dBase 文件 (\\\\*.dbf)、文本文件 (\\\\*.txt) 和逗号分隔值 (\\\\*.csv) 在内的表格文件可以在 MicroCity 中打开并保存为表格。 打开、创建、保存和关闭表格 用户可以单击加载按钮 !button (../images/doc/button_load.png),或选择文件->表格->加载菜单项来打开一个表格文件。可以从..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.5 表格\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"打开、创建、保存和关闭表格","slug":"打开、创建、保存和关闭表格","link":"#打开、创建、保存和关闭表格","children":[]},{"level":2,"title":"显示和编辑表格","slug":"显示和编辑表格","link":"#显示和编辑表格","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.5_tables.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.5_tables.html-p-Cvt07d.js b/assets/3.5_tables.html-p-Cvt07d.js deleted file mode 100644 index 76e6a234..00000000 --- a/assets/3.5_tables.html-p-Cvt07d.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e}from"./button_load-GOP3K2yO.js";import{_ as n,o as A,c as t,e as a}from"./app-DaLjD81q.js";const o="/MicroCityNotes/assets/new_table-Elg2D_3m.png",s="/MicroCityNotes/assets/table_menu-enNFenIu.png",r="/MicroCityNotes/assets/table_view_menu-1OnsnofR.png",g="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfgAAAEsCAMAAAAYWVF0AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAHjUExURfHx8a2trScnJwB412RkZGlpaXBwcP///8jIyOHh4QAAAP/bkGtra9v//zo6kLb//5Db/+HBfwA6kDoAZv//2/+2ZoCAgMHh4f//tn/B4Wa2/6Dh4ZA6ADMzfzoAAJA6OrZmAOHhoMzMzOHhwQAAOuGgWjqQ2wBmtl1dXQAAZjMAWmYAZsF/M1qg4dvbkGYAOjN/wQAzf9uQOoCZsX8zAABaoGYAAH8zM7GZgAUHCAAAWgAAM6BaADMAAICNpr3IyKa9yICAjcjIsZmAgFoAAMjIvSYmJqaNgI2mvVoAM72mjToAOsixmZmxyJBmAMi9po2AgDMAM1oAWoCAmbZmZtv/ttv/27HIyFFRUbbbkMHhwVozM2ZmZiUlJTpmZgAzWgA6ZmY6Oj09PVBQUCQkJG5ubm9vb6BaWtuQZjMzWpCQZjo6ZpCQ25CQOj4+PldXV0VHShkZGTs7O1ozf9u2ZrGxmTo6ADo6OmY6AJA6ZlozALb/2y4uLktLS0BAQGVlZU5OTmJiYlxcXFZWVm1tbWNjY0ZGRmFhYWxsbGhoaF9fX42ZsTNaWsGgWn9/wX/BoMF/WrGZjZmNgICNmY2NgKB/M1paMwA6On9aAFp/f8HhoLa2ZpDbtrZmOpC2kGY6kDqQtopAvkwAAA0RSURBVHja7d2JXxvHGcZxt3URWgFCHEIIbAsDkokRAQLYNXLigyS1nfqIE8dO7dROaqeu6yRN0+Zqm973fd/tn9p5Z2ZXWoS4JNjr93wcSWgVe9mvZme1emf2QNce5Pb373eRrfLgwYP793/09lvHPvnxT2/e7Lrd0/POPv7rB7pSJIEBHngCPAGeAE+AJ8AT4En04YcHen33OplL/fZR4Xi2eTEJaZyj5v6o0wJ+aLzSAn5o3HGcgTngI5mjnzvacLcBfOb9wWwr+KLvrwI+evI+dz/8YrlUBD6m8n53H/zQkX4NWViR/Xqvd+/BZ9QOQZ4sa/iGxST88n53H7xSLzzZr0AVckk9tvdeH19W8PIC9S5Q8I2LSaThS2X9n2716sa997X4YUdSVvCNi0mUd/V61+3MZDeHNz8DH6ODu+GZrOgXZR8+NG529XLvg9c7+JeydlfvLiZR/jhXqthbtTuf+qoSde99B3eZw45T1Ad3DYtJtE/gkOQEeOAJ8AR4Elf4n7ERkgn/CzZCMuF/zkagjyfAE+BJPOEPkAQGeOAJ8AR4Em/4gyS02Vv4bhLSAA888MADDzzwwO8O3nHj/Zsn8/n8Uw3rcDL/he7ui76nyH7Cf6YD2QDe/kvu/bPPK+cX8k8/44cncYfX5qJ/7vzZP+Xzn1dtXeX6N1WLP3c+nz97pvvK1T/+QRY07RrIXsGn28x24E9qS3Wr4M/o5q9b/Av5p65cffqZZ58/e+bK1bNnzp2//spFhX/llxhFFt708H74iwJ//ZVuwXXh5bE84b4BTjb2ByRGLV7BK28/vK/l5/Uen8QCvqGP36LF6/cHjT5g+Nyhkc7Ae0f1Ai/9fLfb0s+dd1u6uf+9HOdxcBcU/LTqoOfbgW/1OV6O4eUgXt4K647q3T4+T4MPDH721Fh6Ym1+9/Ato3f1JKTwk0tVafWnxhT8xNryrDR//dz0wgjwMYbPPTGmbicujOYOvbo0r5+5Njq9nE7Xqu22eBIB+LVq7uFH82YfcGJ04sUx9Qf4ZLT4086ydPmOszqars3PLqeBT0gf/4+1qjxQLT6de/jF0V3BR3qYSHecxrzs5Kh+enVUNXTVx6u3w8II8PGGb/wcP7v62zXnS9LYNzy0Az5W8Btl40M74GMPv/GhXRLhM3293m0C4Hd95k5vq8NlM51lJOFlDk5nYM6VBn4H8JceZSMM71/xmMDvRelVM/zgP8uy/RZlpnL14LHjFEvOlMxYL7eRgFfSZm3VA9kHDAC/HfiPP8za7XepX3b8w05Rpip3Z7WPBrxZ20zfjfFi1Fv8PtTV2003XDbbb+hIv2wz89/LcmGSJ/vDDi99fMVb20zfnEy+Dfz24Ic+vKU2l9rXTzXAz8kmneqPSIu3a5vpe2+gF/jtwqeGX1PNfibb1OKjcnDnra16B/QBv334ofGZ7GJF9/EevPSaqZeyEYG3a6veAap3WhwAfnvwcsWSwopz914jvFyUqhKlo3q1turBsOO8RovnlC3wwEcF/lMdCPBRhE+3HeCBp/QqMqVXtHhaPPDAAw/81gMpgY8H/KwptNxT+OiUMnSvX+nYwuvS6m+MdBh+s+IlvUyuOh5l+KEj/VssCMH7ZjP4iQuj9WafO/Q3GUOTnlxynIURdat+2CX85sVL4S3K6hx8yFu8GT5lB0rmTlf1CNmaLrCtzcsP7cC3LF4yX94VU6lhtVe4rL+gD0lNloGXL2fcNbPVY32XZx7rR3rh3Q9kj+b9dpfN7qvkOP8bN7u6yzO3+txfrbASUA3CZvD1kdCTJ0YFWYZK64p6udUjaNuC37h4yXx5V1Gbqpg5XNTfeIakJsvAlyq6SyraVdLVY8WUeWQWmoZtfzuzTB4WvqYXyDNSx6H/gqHxckBVR5vCnxpzD/FWXXizF8iddtzndtnHty5e0vCF41n1R55UryiEpCZLr33huH3b2lW2tSTmkVmofQvub9frwtsFttzI/AXyy4YP3vbxZqCkD96OpGmvxbcoXjKLS+VF/WW33nghqcny76/0f171mH006MFn3N+u1+sgis3w8n4IH7w9qv+zHihp4SeX3D4+/eZYe/Atipfs4kf3+s02GswWQlKT1Qxfrx6zjwZ9Ld5/FLg4cKO5xfeFEl4f0Fcn9EBJC6+P6pftbft9/AbFS3bjjdvdwGJFd5dhqMnqNk23UoevV4+ZR2ahOjpJuSvtwn+lX45bZIEPvrBS1McGiThlu0Xxkv04p7eRPdoPSU1W/ai+knHd3Oox88iuqVrvgfpvZ/p4fXJCFsw1wsvzfw3k82tYz9XrPWXIzo/t0SnbYH7LsMIvVlKJgC8FdZqSb+f4kgb4xMLvfbElCWPpFeXVCW3xwAMPPPDAAw888G3AD7c+Z1GvTTrc9KJMn/cdR5Dwsva35Ju3IvA7bfGti6vq8DJhxvrai6Arl7y1l7XTk7YBv1P4jK08KknBklekNPUtx9Zg6U2rN6/3ssyjD2yRpnnS/SsCgpcvYoHfObypPNIFSQ1FSr4WL3PljNdf5u3qb5gn69VPwcCHep6mELd4rwClsUjJB1/ySnD0yzz4OVuXs+9zz/jhdUEo8LuD1wVJDUVKvoM7pS3iagObl7nw75kng4anxbcBn5KCpJfrRUq+Fm/vzAZeVJ272+IHs2Fo8fTxbcDbgqR6kVKp6IO3fbx+mdRqFRv7+GDh3bpp4Hf0Of6W7eP1p/WGIiVdtNTwiU/9rF6gX2YGXtij+plsKiB4Psdz5g544IF34Q8Cn0z47wKfTPi3Kb1KZulVDy0+mS0eeOCBBx544HeR5vN0QZyyNSmshHpq/eDgv9Nu6ZVs1pL3uqGNq66Cgy+VQzWVUXjgv9dm6ZVclLCwElp4WR/gd7qr31bp1eOivmKRWTjkzhel/ydbj7XvF/rTa28muio5Jk2TWwHfbunVrb7ef/9H6nD0Qm++KD1TlHcXTIuXqS+8Fu+f3Ar4LVv8VqVXHx/513/nzPw3amHDtEHuvDGZfb/QX3d9P+/Br5vcCvjtwbcuvRrMLr5f1rsGvbAR3tZjDQ8EU4ix6K7PRpNbAb89+NQmpVcyq5A345WvxQdaemWmt/K1+FQUJzUOFn6L0quM6eNlxqv6fFFuH1/Y9wv9mYO7itvHbzS5FfA9nSi9MtPa6hmv6vNF9dp6rNS+X+iv2565uXuv393Nr5/cCnhO2QIPPPDAhxK+k5MfAR8l+A5Od9ZD6VUyLzho4VMkmS2eDQw8SQD8O8DHFb75GgWN8D3ARx6+fg0y4IEHPjHwudNyaUl7rVm5+tgC8EmAn1yq2usP5q6Nyg+0+GTAi7O5DJ1cgk49BXwy4KW1S0PXF52UH4BPSIt/Ql9M1nfRSeCT08fP6otOyj5/loO7uMPL9YNPjak7ud6ovuhketpxfrVpi/868HE9c7f5KVtaPPAEeAI8AZ4ED9+xYkvgIwXfuQCfUHg+x9PiCfAEeBJP+DeATyb868An83P8TeCTeebuIPDAE+AJ8CSW8BzcJRSeEzgxgG89Xgr4OMNPrFXT6TfHgE8avB00qYdLSnW9lNdPLskISuBj3uLn3bfAtdHp5XS6Ni9/phlQkYQ+vpo2wyUnXhybuCC3dgQl8PE+qp82Q+PVba2qmroeXLMKfPzhVd9uhkump5dnq2lp8RzcxR1+el737ma4pNrDPxzT3XyLA33gY3Rwp3frdrhkuras9wCOs0yL58wd8MADDzzwwJOEwDOJcbTgO1ZseRv4KMEzoAJ44IFnJA3wjKQBfvO8C3wy4Y8BDzxJ0Od4D56ENnty5s6FJ5EI8MADDzzwwO8Y/rMktNkm/MSav8pu80uTePC0prCmFbyuna/Wf67Nr7/g4KsnRoGPIbxcYuy0pz25Xhn4GMOnp0+Npc0AyZrjrP5FX2bSXoIq9/AjR4ZP1/SlJ4GPF7wMkDMDJG2Lz11zrz1mW7xaNPEb4OMGP7lUtQMkLXz9onN1eHb1sWzxdoCkhtfjJv3wMqamCnwM+3g7QFIPmDSXmTQXlq0f3PkuPQh8PI7qq+4ASYE34yZl6GRtQcGP1NTS38kAWlp8HD/HmwGSAm/HTaod/t+lxcsw+YVfy1UogY8RfIdO2bKBkwXfBTzwBHgCPAkTfMeKLYGPFHznAjzwBHgCPAGeAE+AJ8AT4AnwBHgCPAGeBABP6RUtngBPgCfAE+AJ8AR4AjwBngBPgCfAE+AJ8AR44IEHHnjggQd+x6H0ihZPgCfAE+AJ8AR4AjwBngBPgCfAE+AJ8AR4AjzwwAMPPPDAAw888MADDzzwzfA/AD6Z8G8Bn0z4Y8DTxxPgCfAEeAI8AZ5EEf6HwCcT/ifAJxP+y8ADT4AncYe/AzzwJEHwzwEPPAGexB3+08ADT4AnwBPgCfAEeAI8AZ4AT8ILT0KbPYUnCQvwwBPgCfAktvAksDxnc+fOt2923e7peeP1d7v2K/8HJyX+walUsMUAAAAASUVORK5CYII=",i={},l=a('

3.5 表格

Tabular files including dBase files (*.dbf), Text file (*.txt) and Comma Separated Values (*.csv) can be opened as Table and saved with MicroCity.

Opening, Creating, Saving and Closing Tables

Users can click Load button button or File->Table->Load menu item to open a tabular file. Creating a new Table can be done from menu File->Table->New and the pop-up dialog as shown below. Saving a Table can be done from the right click context menu Save or Save As.

new table    table_menu

Showing and Editing Tables

Double click a Table from the Data Tab will give you a table view. Altering a table's stucture can be done by right click the table's head. If you click "Add Field" then, a dialog which guide you (as shown below). If you want insert a record to the table, you can right click the left numbers of the table and select a context menu item.

table_view_menu    add_field

',8),f=[l];function b(c,d){return A(),t("div",null,f)}const P=n(i,[["render",b],["__file","3.5_tables.html.vue"]]);export{P as default}; diff --git a/assets/3.5_tables.html-p1nKqUcK.js b/assets/3.5_tables.html-p1nKqUcK.js new file mode 100644 index 00000000..c41820fc --- /dev/null +++ b/assets/3.5_tables.html-p1nKqUcK.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-42244670","path":"/en/docs/3.5_tables.html","title":"3.5 Tables","lang":"en-US","frontmatter":{"prev":"./3.4_3d_scenes.md","next":"./3.6_maps_and_layers.md","description":"Tabular files including dBase files (\\\\*.dbf), Text file (\\\\*.txt) and Comma Separated Values (\\\\*.csv) can be opened as Table and saved with MicroCity. Opening, Creating, Saving a...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.5_tables.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.5_tables.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.5 Tables"}],["meta",{"property":"og:description","content":"Tabular files including dBase files (\\\\*.dbf), Text file (\\\\*.txt) and Comma Separated Values (\\\\*.csv) can be opened as Table and saved with MicroCity. Opening, Creating, Saving a..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.5 Tables\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing Tables","slug":"opening-creating-saving-and-closing-tables","link":"#opening-creating-saving-and-closing-tables","children":[]},{"level":2,"title":"Showing and Editing Tables","slug":"showing-and-editing-tables","link":"#showing-and-editing-tables","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.5_tables.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.5_tables.html-rfKSY5-v.js b/assets/3.5_tables.html-rfKSY5-v.js new file mode 100644 index 00000000..5053828d --- /dev/null +++ b/assets/3.5_tables.html-rfKSY5-v.js @@ -0,0 +1 @@ +import{_ as o}from"./button_load-GOP3K2yO.js";import{_ as s,a,b as n,c as i}from"./add_field-ZFhY51wb.js";import{_,r as c,o as g,c as l,a as t,b as e,d,e as h}from"./app-LOf__QKq.js";const p={},m=h('

3.5 表格

包括 dBase 文件 (*.dbf)、文本文件 (*.txt) 和逗号分隔值 (*.csv) 在内的表格文件可以在 MicroCity 中打开并保存为表格

打开、创建、保存和关闭表格

用户可以单击加载按钮 button,或选择文件->表格->加载菜单项来打开一个表格文件。可以从文件->表格->新建菜单项中创建一个新的表格,如下图所示的弹出对话框。要保存一个表格,可以右键单击上下文菜单中的保存另存为选项。

new table    table_menu

显示和编辑表格

双击数据选项卡中的表格,将显示一个表格视图。通过右键单击表头可以修改表格的结构。如果单击"添加字段",将显示一个引导对话框(如下图所示)。如果要向表格中插入一条记录,可以右键单击表格左侧的数字,并选择一个上下文菜单项。

table_view_menu    add_field

',8),u={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},f=t("strong",null,"反馈",-1);function b(x,k){const r=c("ExternalLinkIcon");return g(),l("div",null,[m,t("blockquote",null,[t("p",null,[e("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",u,[f,d(r)]),e("页面提交反馈。")])])])}const C=_(p,[["render",b],["__file","3.5_tables.html.vue"]]);export{C as default}; diff --git a/assets/3.5_tables.html-zF8D9g8c.js b/assets/3.5_tables.html-zF8D9g8c.js deleted file mode 100644 index 1e4ac6eb..00000000 --- a/assets/3.5_tables.html-zF8D9g8c.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-b2a5ca98","path":"/docs/3.5_tables.html","title":"3.5 表格","lang":"zh-CN","frontmatter":{"prev":"./3.4_3d_scenes.md","next":"./3.6_maps_and_layers.md","description":"Tabular files including dBase files (\\\\*.dbf), Text file (\\\\*.txt) and Comma Separated Values (\\\\*.csv) can be opened as Table and saved with MicroCity. Opening, Creating, Saving a...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.5_tables.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.5 表格"}],["meta",{"property":"og:description","content":"Tabular files including dBase files (\\\\*.dbf), Text file (\\\\*.txt) and Comma Separated Values (\\\\*.csv) can be opened as Table and saved with MicroCity. Opening, Creating, Saving a..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.5 表格"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.5 表格\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving and Closing Tables","slug":"opening-creating-saving-and-closing-tables","link":"#opening-creating-saving-and-closing-tables","children":[]},{"level":2,"title":"Showing and Editing Tables","slug":"showing-and-editing-tables","link":"#showing-and-editing-tables","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.5_tables.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.6_maps_and_layers.html-0HlObXq2.js b/assets/3.6_maps_and_layers.html-0HlObXq2.js deleted file mode 100644 index d072adc3..00000000 --- a/assets/3.6_maps_and_layers.html-0HlObXq2.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as o}from"./button_action-tmG_4IgV.js";import{_ as n}from"./button_3d-coWyniAs.js";import{_ as e,r as s,o as r,c as g,a,b as A,d as i,w as m,e as c}from"./app-DaLjD81q.js";const l="/MicroCityNotes/assets/map_coordinates-8ybUOErD.png",d="/MicroCityNotes/assets/map_menu-zU_XTli2.png",p="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUwAAAFMCAMAAACXsHVtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKpUExURf///6CgoGJnbK2treLi5IKHkFNTU/Hx8QB41+Hh4RaE23BwcAAAANv/////trb///+2Zv//2wA6kFtbW2a2//DOhr+/v//bj5A6AMzMzM7w8GYAADU1hmYAZjk5j+HBf6vw8MHh4YbO8AAAZhkZGRkZcLZmAJDb/zMzf2Z41wUHCACR7DqQ22YAOjUAYPDwzqDi5P/bkABmtvDwqwA5j4/b/9v/8uLCgKDh4Y85AH/B4TkAZjUAAAA1hjMAW4Y1ANuQOuHhoGCr8AAANX8zADoAAPCrYABgq9u/3oY1NQCo8gB43joAZjWGzuHhwcF/M5CR1wAAW6tgAGbV/2AAADkAAGAANQBaoOGgWs6GNQAAOs7OhjOAw485OVoAAOLiogAAWgB45cKANFqh5OKhW7ZmZjUANQAzf8Li5HBXPJDq+WAAYP/V5QAzgDN/wTmP27b/8uLiw5Dq/zMAAAAAYGYAOZCQZgAAMzMAWloAMwAAOf//8tvq8jp416BaALao16tgYFxhZTMzM1tgZVc8GV1hZhk8V2Jma1pfZFoAWtvbj1ozf6BbAJA6Oma2tlqg4dvV5Wao8tvq7Dq/+YZgAM7wzv//+QA1YJDq8tuPOY9mAH8zMzMAMzpmZpBmkH/C5FoANNv/ts7wq2BlaV5jZ2BlamFma11iZ2BkaV1iZmZna2Fmal9kaWFlal9jaFtfZF9kaGJna1tgZFxhZlxgZWlqbF5iZxSD2gBbopCQ26B/M5C2kNv/+ZC2/4+P29vq+TqQkDo6OmY6Otu/5To6ZmA1AH9aAGZmZmbV8v/q7AAzWjU1YNvV8rb/+WZ43maR7FozM86rYDkAOaBaWmaPj6ChW6DiojVgYIaGNTU1NavwzqvOhmA1hqtgNYarhobOq7bbj9uPZmA1Nb5w/AIAAAmiSURBVHja7d2HfxvlHcdxNb0gmT62rGIrjh1ixU5lXBsntnEWDnFMEhsbB5PRNAkNhDTQppSR0NKWhFDaQkuhrLaM7gF0QAvde++99/5L+ow7DWv69ESRTp/vK7qlky56+/c8z52UyKFziLWEzgkRSwETTDDBJGCCCSYBs5qYrS9uzpy3nB/1f4xSD/aOVVcRy818uSiAGesYAbPMLH/p8oxZHszh714e9YcZ62grH3PhznWJaRizLLMxJwaTbWAuQjPbMgszdn+ffl0tXUIIueDNXY/h7UK0xToG9atX9w1Klnd1eY8w23pdtwm9aPZSDzZLevad1M6DoaxjXPj17aKtVW/Wx9JPr+Y1q5ltmYWpjC7sk69P/vWT6uWauYsZ+2BzqLU3qriTbWo/WWCxDhdPFVtLl3I2G4Z1f+HuJR/sLaldzM7ehoxjyJ9LqxhRj3WPpZ++tTdaj5jJQX3T1Skn3jzVUnW1SQW5IutHZjDVYNWC3tXd0tJ1oE8+2OyV3t88m945Y4N3DPWDdG/mWPrJivYgNdvMdYsTpvbyYA5vH9QFNzE4MeJtzoN5f5+35UBf+sHuUgZmxoZcTPdYNY1ZfADS7Um2O9X0Yh2mmat5hseE3GX4B99zu4Kj0SxM08zN/sPfTDXio1HVzN0lOWv5qtk5tSF1jDSmeyx9qjZRm828xKlRcsSdyiZ44PXy5Xhzt8/sEOIDqivUXZw3QnhVM7FgAEoK2fu5e6VGL71B7qF2djdkHiON6R4r1vHj9DPW20l7eVFda3VSs92ltWvz4cujYFrCTFbxvC/4lUnABBNMMAmYYIJJysIME0sBE0wwwSRgnpXcBaa9fApMe3k7mGDWZD4Lpr18Lo3pMPE7cfMWKtNewLSYL4BpL28G00YcMG3n874x21d0wpedt+Vgto9PyemuWxN5/MaF2NyZH3PNZT0ND5wH87qfJ8Kje/Jgju6ZDIfvTBTBbPB8Mhdz6C+T4R1/HkrsF0LMSbN3i0t73HsM5JotaovENAtqXTz6Q7n35oMrOmX16jtTj8ruowO3kHnS/nQezL+v6PznvzRc+3U97eOT4f2mbY/umdN77JoL79jcKTHNQnjXVLqZv2fLpL5zXM9yjxfofCkP5t8u+/c/DmpMKaRa8+jLelJ95mR49DUJtaV9xUfNglpPYR40u6tHNV4H+vE8mIn9f51TTVq280uzMGV2yC2SVN9x0F0YysD8rSzHNVsmGxPzM/kwVeseSuy4NeFWptdZ6v5y0lRi2FRmqiv1KnMo0biV+Vw+TLc+p3SfKUn2T5mqnNO9qOoz5aBu+ky5sGaLvnvXZGaf2ZCYzxTGHN0jHv1fT8a5pdyQGr2n3NFcLnjr495oLs+qCmAGbERfuOETpa6AuNApdUWezsfAtJcneaPDXp6tEmZDnLh/msq0l6fAtJd7qo0Z0LOjKmEGvrdMv8Dnaeb2siQT08Gjokb3oipWZuB/VovDdLArlrtzMZ1cCqfgDoWmjTCk5+StJSrToYGXn1czmoNZk8N6CpPTosqT22cuJWWn5Gi+lP+dW26WljzPBLNQFrZqMMGsb8yWLvOFduV+cXPsFWNmYdnKZjCzMWMb20KtI+q7ynoXiUll5mCqglx2cXRhZcY2CnFR87K94k1jugTlbdnKJ+SaukNcdO/KJ3r/s7JZrsj71Zc+3gSmaqwX58XU37Cpq1aSuph79ZquTLUsNyVvUlvkn5ZvBRIzXhBzdUHMlteNLcA0K0pR3peqTD0zmHr5I+frx0rMYDbzeDxuozL1FlV1qjoLYt67VzZ50/LbAogZj6c0K+ozDaZbtdq7UGWaPB6w4vTq0tNc5GjuYiaNSmxjZp/5uzG13cUMqV894C7LPjN0NPrfMfMMgcP0Jos+z5QjshqSXUw9mo/IcUbf97gQf0hVptooR3NTpXqv1pr96uXKMDPGIK6AuJysY8wIyRcwwQwW5kDztJys60fQBuY3TvaDaQtz3UPTGnP2eOi985GZGyKR3eo2DaYfzF891q8wJd/MT08NPHxq9tjJ/tlj82D6weyfmZaTwzf3Rw7/cl4qDjz4yGm1BqYfzNnHfr2uf0BdRsp2vvv0I6dnbhh4kD7TH2Zk5hemMlVmvn9s/vDND02D6RNz9vjtus+M/EQO7N9++FRk98l5MH1iRmZu16N5SA7js8enzTqYXAGBGQxMwvuZYIIJJphgggkmmGCCCSaYYIIJJphgggkmmARMMMEEE0wwwQSTgAkmmGCCCSaYYILpH/MlYIIJJn0mARPMOsdcDaY9zPPAZDQHk2ZOwAQTTDDBBJMrICqTUJlgggkm1+Zg0sw5NQITTDDBBBNMMMEEE0wwwQSTgMkbHVQmmGCCCSaYBExOjcAEk2YOJs0cTAImmGCCyb+CA7N+MPnP+2CCCSYBE0wwwQQTTDDBJGCCybtGYIIJJpgMQGCCCSaYYIIJJphgggkmmGASMHmjA0wwwaTPBBNMAiYDEJhg0szBBBNMAiaYYIIJJphgggkmmGCCCSaYYIIJJphgggkmARNMMMEEE0wwwSRgggkmmGCCCWYAMePh9BTMSjHj3oTfbWEBM65v/KYqG31mPO5Zgln5AJSyBNPCaB7nF9JV49QITDDBBJOAWZWUgUnKTklM4jtgggkmmARMMOs9q8G0l6zPgBw8fMUp+IEasVOZLyCLT6gAJm9dVPZmEs38TDVzAiaYYBIwwQQTTGIdk3c5Kn2fg8o8k83cqbGpTsRWvCd8oa3UYZ8Z+fK5VpLGbLKTusQ817ERMMEEE0wwq4XZfcGqBsB8pRDiKsdZf8la55Ztr32Vb8wr5PPc2OCY11651rn60FUa876v+K/MK67Z0LT1nasaGvOWbUdUdV65VmJeW6wuS2BufeOmdHl2X/AjcZtc37lNiOtXyalcaQRMVZCOc/WHP7T+kj8WtyyO2f2GDd7S+zd1n3ig6eXXr2q6Y5/acMeNamXxmLX0boezGMxDR9afEJVgKjuTne/bpODkbes7FLCayrr1W5lO4Zlzpi/h8/08y6zMP8me0z/mNRu8Yeg2D9NUa/cJ4W1rpD5z/YkjlfaZ0jRdmQbT1Gc5febqQI3marmy0fxr+3SfaTB3bvP6zKbfb2i480znvmKaZZxnPrD1kPjZbzxMPZrvc6eNgcnlJJhggnk2MJ0axuRjC3uY9f2BmlNgfoZLuMCnk/X6UW+JF+EUfeWWPtmt2/CPEMAEE0wSGEynfjGdoqdHxFplQlpaZonfZl6dM/f6yhIGIKuYZz93fXFJMPJ/r7GE4HhtUrsAAAAASUVORK5CYII=",h="/MicroCityNotes/assets/layer_menu-lHo367yT.png",M="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAg0lEQVR42r3TSw6AMAgE0M65rS60PTfKAoMoBONnNo0GX8amRTFpcyP9XKeKkggsMIzDYaAvPQVCEA0AKER0AiPsPUgjDNgwePXeloFt4zVyWtE/kJcQerjZH0GC8cqghuRASsJf02FwG+Z1/zC4Nj5kB2xjg6WgbELIjW6m9+s25GUFzwp8EfbjQrsAAAAASUVORK5CYII=",b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAbUlEQVR42q2TWQ7AIAhEO/c/NG3SmqAMW5UfgzKPRcUVm3wrkjgToIXy2OsAkcZsGqH2lzOcBInWm9Y8MUuiq/sFYm0OEB0yHWoAcmeTmQtaM1YhU2vVKjJQG3YExB6le/27oBRW+SIlWBfUthvY82MRgXNcRQAAAABJRU5ErkJggg==",u="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAeUlEQVR42s2T0RbAEAhA67u3x/nu2AwtZfKkB+R0rq4DghkXtfWJ8BM4BNGRKsLeIHKA2N1U0JveuQQg5knsU4q0GzrQCCI7eiCtaKqTTu0D4TALUuq5mgoxL1WBlGGekk/1q3m62kat+i2rgXjMS2qg/Ai3Ghj/MwKEPFUOVRcF+QAAAABJRU5ErkJggg==",B="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAkklEQVR42p3S3Q6AIAgFYM5z27po9txmPzZFOLS8k8E3ASH8FCMG+RpsSD0CQPKWZVkXaXerDgx5k2qxvutaxMheA2luRWGIkDs4QxpDhPgDTAMGijgvEdXuiV1Q3UppW/nzonOrb2sMYzN6vgaGYXuYt7WGWFszsQgxoQizEBfy27QRCmmMISHUYwz5BHUYzT0A22OImeMm74kAAAAASUVORK5CYII=",C="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAlElEQVR42p3SSQ6AIAwF0P5zS1wYPDfiUMROENkB7UtpAcWrGGeg2UNG6iIAlLdMaU3EeysPEdKCarLcy1yMkDd5rxeLi2EGYegOsDFYCCf5zdMYJNKgLliXp595QXUqhafyp6Jzqu1pEpvt0fM18Gl2hFlTY8Sa2rAyCzGhcWUacSEP85AQkliEDKEei5ApqMPC2AOBS4iZAFEifAAAAABJRU5ErkJggg==",G="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAjUlEQVR42s2TSw6AIAxE7XG8oYkuJfGGHqcWkV9pEXDjLICS5qXTAkyqdoznDaYXQRWEK2WYf4OwA5T0JoCe0MYcAOA2do8kujUFqAbhFd2QmNRUSWEtg6QwFbKcLjjmYE2EqE0VIH5pp1jlkNJaSGgRQbyLdGqfIUPWJEhmrbvh7DGPTU34Ef1TU/7nBemGUA6duqlQAAAAAElFTkSuQmCC",Y="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAArklEQVR42o3SQRLDIAgFUDh3nC4yem6LMSrih9ZN1OALBJniUcEer2mW94nN5onIIGamfGdKn0Rj3c9l9ZHEHCEzBQnb1+WNumRRbJoYOeoCCMoIIu1wlYMeYjNyy5mAQTreHY6Q9SwQ0fEPJF2poysuFCCtq7M0DztKmyVc+mrsP9tiA3xrNw1YCGy/xvas9rlGvHt0YDojhLhQVCZCQghl5iE/IY1FyF+QwsLYL0f7sRzChG+ZAAAAAElFTkSuQmCC",w="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAATUlEQVR42mNkIBEwgskWotXXwDVUE6G6FVWDE17F+7BqcMKtGqcGJxyq8WmwRFJ9nDgN/+EhSCsNJDqJNE+TFqykRRyJSYNIANVAAgAA3hg4Ed06kO0AAAAASUVORK5CYII=",E="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAWElEQVR42q1QQQ4AIAiC/z+6WodmWyPMuJSGhBBFULw1h0cxTFFbDvBLoMFc4US89hiaSAgsLrGnrdwdOV8cWGHdMniGysCanwID40Zkz00g/3UQqK5QQgcKSi4RSBgHpAAAAABJRU5ErkJggg==",N={},f=c('

3.6 地图和图层

In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid.

Opening, Creating, Saving, Printing and Closing Maps

Because Maps are based on Shapes and Grids, they can not be saved or opened independently, but can be saved or opened along with a MicroCity Project (*.mprj). Creating a Map is by double clicking a Shapes or Grid from the Data Tab of the Workspace Panel. A Map window contains four coordinate bars which can be used to locate objects (see below). A Map can also be printed or closed from the context menu of the Maps Tab of the Workspace Panel.

map_coordinates   map_menu

Adding, Moving, Hiding and Closing Layers in a Map

A Map can have multiple Layers, each of them represents a data item. One can add a Layer to a Map by double clicking a Shapes or a Grid from the Data Tab. A lower layer can be obscured by upper layers. One can move a layer by dragging, hide a layer by double clicking and close a layer through the menu (as shown below).

add_layer    layer_menu

Controlling Map Views

When a data item or a layer is selected, this layer is called the active layer. One can toggle the Action button b_action to select and edit an object in the active layer. By toggling the Zoom b_zoom or Pan b_pan botton, the map can zoomed in, zoomed out or panned. If one lose in a map, he can use the Zoom to Full Extent b_zfull button to get a full view of the map. Other zoom controlling buttons b_zlastb_znextb_zactiveb_zsel can be used to facilitate the map browsing.

The Synchronise b_sync button can be used if you want compare difference between two or more maps. The Ruler b_ruler button can be used to meassure distances. Note that, by default, the unit of the distances measured is kilometer under the coordinate system of Earth. One can change the coordinate system to Non-Earth from the Settings Panel of the Map, and get Cartesian distance without unit.

',11),z=a("img",{src:n,alt:"b_3d"},null,-1),U=a("strong",null,"Grid",-1);function Z(D,k){const t=s("RouterLink");return r(),g("div",null,[f,a("p",null,[A("One can create a 3D surface map by clicking 3D "),z,A(" button, which need a appropriately sized "),U,A(" (see "),i(t,{to:"/docs/3.3_raster_grids.html#display-settings-and-3d-view"},{default:m(()=>[A("3.3")]),_:1}),A(").")])])}const R=e(N,[["render",Z],["__file","3.6_maps_and_layers.html.vue"]]);export{R as default}; diff --git a/assets/3.6_maps_and_layers.html-IZMNuK0Y.js b/assets/3.6_maps_and_layers.html-IZMNuK0Y.js new file mode 100644 index 00000000..f9f7e90b --- /dev/null +++ b/assets/3.6_maps_and_layers.html-IZMNuK0Y.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-eac61a9c","path":"/en/docs/3.6_maps_and_layers.html","title":"3.6 Maps and Layers","lang":"en-US","frontmatter":{"prev":"./3.5_tables.md","next":"./3.7_modules.md","description":"In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid. Opening, Creating, Saving, Pri...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.6_maps_and_layers.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.6_maps_and_layers.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.6 Maps and Layers"}],["meta",{"property":"og:description","content":"In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid. Opening, Creating, Saving, Pri..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.6 Maps and Layers\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving, Printing and Closing Maps","slug":"opening-creating-saving-printing-and-closing-maps","link":"#opening-creating-saving-printing-and-closing-maps","children":[]},{"level":2,"title":"Adding, Moving, Hiding and Closing Layers in a Map","slug":"adding-moving-hiding-and-closing-layers-in-a-map","link":"#adding-moving-hiding-and-closing-layers-in-a-map","children":[]},{"level":2,"title":"Controlling Map Views","slug":"controlling-map-views","link":"#controlling-map-views","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.6_maps_and_layers.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.6_maps_and_layers.html-KNvuRdkG.js b/assets/3.6_maps_and_layers.html-KNvuRdkG.js new file mode 100644 index 00000000..dca03724 --- /dev/null +++ b/assets/3.6_maps_and_layers.html-KNvuRdkG.js @@ -0,0 +1 @@ +import{_ as g,a as e,b as _,c as i,d as c,e as l,f as m,g as p,h as d,i as h,j as u,k as b,l as f}from"./button_ruler-TjPjykp6.js";import{_ as x}from"./button_action-tmG_4IgV.js";import{_ as y}from"./button_3d-coWyniAs.js";import{_ as k,r,o as z,c as C,a as s,b as t,d as o,w as v,e as N}from"./app-LOf__QKq.js";const w={},L=N('

3.6 地图和图层

在MicroCity中,形状网格可以显示在地图中。每个地图可以包含多个图层,每个图层对应一个形状或一个网格

打开、创建、保存、打印和关闭地图

由于地图是基于形状网格的,它们不能独立保存或打开,但可以与一个MicroCity项目(*.mprj)一同保存或打开。创建一个地图是通过在工作区面板的数据选项卡中双击一个形状网格来实现的。地图窗口包含四个坐标栏,可用于定位对象(见下文)。地图也可以通过工作区面板的地图选项卡的上下文菜单进行打印或关闭。

map_coordinates   map_menu

在地图中添加、移动、隐藏和关闭图层

一个地图可以有多个图层,每个图层表示一个数据项。可以通过在数据选项卡中双击一个形状网格来将一个图层添加到一个地图中。较低的图层可以被上面的图层遮挡。可以通过拖动来移动一个图层,通过双击来隐藏一个图层,通过菜单来关闭一个图层(如下所示)。

add_layer    layer_menu

控制地图视图

当选择一个数据项或图层时,该图层被称为活动图层。可以切换操作按钮b_action来选择和编辑活动图层中的对象。通过切换缩放按钮b_zoom平移按钮b_pan,可以对地图进行缩放和平移操作。如果在地图中迷失了方向,可以使用缩放至全图范围按钮b_zfull来查看整个地图。其他的缩放控制按钮b_zlastb_znextb_zactiveb_zsel可用于方便地浏览地图。

如果要比较两个或多个地图之间的差异,可以使用同步按钮b_sync。可以使用尺子按钮b_ruler测量距离。需要注意的是,默认情况下,在地球坐标系下测得的距离单位是公里。可以在地图的设置面板中将坐标系更改为非地球,从而获取没有单位的笛卡尔距离。

',11),V=s("img",{src:y,alt:"b_3d"},null,-1),B=s("strong",null,"网格",-1),E={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},M=s("strong",null,"反馈",-1);function j(D,I){const n=r("RouterLink"),a=r("ExternalLinkIcon");return z(),C("div",null,[L,s("p",null,[t("点击3D按钮"),V,t("可以创建一个3D表面地图,需要一个适当大小的"),B,t("(参见"),o(n,{to:"/docs/3.3_raster_grids.html#display-settings-and-3d-view"},{default:v(()=>[t("3.3")]),_:1}),t(")来实现。")]),s("blockquote",null,[s("p",null,[t("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),s("a",E,[M,o(a)]),t("页面提交反馈。")])])])}const P=k(w,[["render",j],["__file","3.6_maps_and_layers.html.vue"]]);export{P as default}; diff --git a/assets/3.6_maps_and_layers.html-T_p6rWde.js b/assets/3.6_maps_and_layers.html-T_p6rWde.js new file mode 100644 index 00000000..2f340b2b --- /dev/null +++ b/assets/3.6_maps_and_layers.html-T_p6rWde.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-8532c374","path":"/docs/3.6_maps_and_layers.html","title":"3.6 地图和图层","lang":"zh-CN","frontmatter":{"prev":"./3.5_tables.md","next":"./3.7_modules.md","description":"在MicroCity中,形状和网格可以显示在地图中。每个地图可以包含多个图层,每个图层对应一个形状或一个网格。 打开、创建、保存、打印和关闭地图 由于地图是基于形状和网格的,它们不能独立保存或打开,但可以与一个MicroCity项目(\\\\*.mprj)一同保存或打开。创建一个地图是通过在工作区面板的数据选项卡中双击一个形状或网格来实现的。地图窗口包含四个...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.6_maps_and_layers.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.6_maps_and_layers.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.6 地图和图层"}],["meta",{"property":"og:description","content":"在MicroCity中,形状和网格可以显示在地图中。每个地图可以包含多个图层,每个图层对应一个形状或一个网格。 打开、创建、保存、打印和关闭地图 由于地图是基于形状和网格的,它们不能独立保存或打开,但可以与一个MicroCity项目(\\\\*.mprj)一同保存或打开。创建一个地图是通过在工作区面板的数据选项卡中双击一个形状或网格来实现的。地图窗口包含四个..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.6 地图和图层\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"打开、创建、保存、打印和关闭地图","slug":"打开、创建、保存、打印和关闭地图","link":"#打开、创建、保存、打印和关闭地图","children":[]},{"level":2,"title":"在地图中添加、移动、隐藏和关闭图层","slug":"在地图中添加、移动、隐藏和关闭图层","link":"#在地图中添加、移动、隐藏和关闭图层","children":[]},{"level":2,"title":"控制地图视图","slug":"控制地图视图","link":"#控制地图视图","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.6_maps_and_layers.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.6_maps_and_layers.html-XuAmYobJ.js b/assets/3.6_maps_and_layers.html-XuAmYobJ.js deleted file mode 100644 index 1f19326b..00000000 --- a/assets/3.6_maps_and_layers.html-XuAmYobJ.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-8532c374","path":"/docs/3.6_maps_and_layers.html","title":"3.6 地图和图层","lang":"zh-CN","frontmatter":{"prev":"./3.5_tables.md","next":"./3.7_modules.md","description":"In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid. Opening, Creating, Saving, Pri...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.6_maps_and_layers.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.6 地图和图层"}],["meta",{"property":"og:description","content":"In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid. Opening, Creating, Saving, Pri..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.6 地图和图层"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.6 地图和图层\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Opening, Creating, Saving, Printing and Closing Maps","slug":"opening-creating-saving-printing-and-closing-maps","link":"#opening-creating-saving-printing-and-closing-maps","children":[]},{"level":2,"title":"Adding, Moving, Hiding and Closing Layers in a Map","slug":"adding-moving-hiding-and-closing-layers-in-a-map","link":"#adding-moving-hiding-and-closing-layers-in-a-map","children":[]},{"level":2,"title":"Controlling Map Views","slug":"controlling-map-views","link":"#controlling-map-views","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.6_maps_and_layers.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.6_maps_and_layers.html-Zp7Na5N3.js b/assets/3.6_maps_and_layers.html-Zp7Na5N3.js new file mode 100644 index 00000000..cbc7cdb5 --- /dev/null +++ b/assets/3.6_maps_and_layers.html-Zp7Na5N3.js @@ -0,0 +1 @@ +import{_ as e,a as o,b as s,c as r,d as i,e as g,f as c,g as d,h as l,i as p,j as m,k as h,l as _}from"./button_ruler-TjPjykp6.js";import{_ as b}from"./button_action-tmG_4IgV.js";import{_ as u}from"./button_3d-coWyniAs.js";import{_ as y,r as f,o as w,c as v,a,b as t,d as M,w as k,e as x}from"./app-LOf__QKq.js";const z={},C=x('

3.6 Maps and Layers

In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid.

Opening, Creating, Saving, Printing and Closing Maps

Because Maps are based on Shapes and Grids, they can not be saved or opened independently, but can be saved or opened along with a MicroCity Project (*.mprj). Creating a Map is by double clicking a Shapes or Grid from the Data Tab of the Workspace Panel. A Map window contains four coordinate bars which can be used to locate objects (see below). A Map can also be printed or closed from the context menu of the Maps Tab of the Workspace Panel.

map_coordinates   map_menu

Adding, Moving, Hiding and Closing Layers in a Map

A Map can have multiple Layers, each of them represents a data item. One can add a Layer to a Map by double clicking a Shapes or a Grid from the Data Tab. A lower layer can be obscured by upper layers. One can move a layer by dragging, hide a layer by double clicking and close a layer through the menu (as shown below).

add_layer    layer_menu

Controlling Map Views

When a data item or a layer is selected, this layer is called the active layer. One can toggle the Action button b_action to select and edit an object in the active layer. By toggling the Zoom b_zoom or Pan b_pan botton, the map can zoomed in, zoomed out or panned. If one lose in a map, he can use the Zoom to Full Extent b_zfull button to get a full view of the map. Other zoom controlling buttons b_zlastb_znextb_zactiveb_zsel can be used to facilitate the map browsing.

The Synchronise b_sync button can be used if you want compare difference between two or more maps. The Ruler b_ruler button can be used to meassure distances. Note that, by default, the unit of the distances measured is kilometer under the coordinate system of Earth. One can change the coordinate system to Non-Earth from the Settings Panel of the Map, and get Cartesian distance without unit.

',11),S=a("img",{src:u,alt:"b_3d"},null,-1),O=a("strong",null,"Grid",-1);function A(G,L){const n=f("RouterLink");return w(),v("div",null,[C,a("p",null,[t("One can create a 3D surface map by clicking 3D "),S,t(" button, which need a appropriately sized "),O,t(" (see "),M(n,{to:"/en/docs/3.3_raster_grids.html#display-settings-and-3d-view"},{default:k(()=>[t("3.3")]),_:1}),t(").")])])}const B=y(z,[["render",A],["__file","3.6_maps_and_layers.html.vue"]]);export{B as default}; diff --git a/assets/3.7_modules.html-acS-BfiZ.js b/assets/3.7_modules.html-acS-BfiZ.js new file mode 100644 index 00000000..58a307f6 --- /dev/null +++ b/assets/3.7_modules.html-acS-BfiZ.js @@ -0,0 +1 @@ +import{_}from"./icon_script_editor-ibm_2NsU.js";import{_ as l}from"./button_load-GOP3K2yO.js";import{_ as a,a as c}from"./icon_module-AxwvBQMt.js";import{_ as g,a as d,b as h,c as u,d as m}from"./module_settings-yrsWXh8u.js";import{_ as p,r as n,o as f,c as b,a as t,b as o,d as r,w as y,e}from"./app-LOf__QKq.js";const C={},k=t("h1",{id:"_3-7-拓展模块",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-7-拓展模块","aria-hidden":"true"},"#"),o(" 3.7 拓展模块")],-1),x={href:"https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga_modules2.0.8.zip",target:"_blank",rel:"noopener noreferrer"},M=t("strong",null,"SAGA模块",-1),w=t("strong",null,"SAGA模块",-1),S=t("strong",null,[o("形状(Shapes)"),t("strong",null,"和"),o("网格(Grids)"),t("strong",null,"库。另一种类型的模块是"),o("MicroCity脚本")],-1),L=t("img",{src:_,alt:"ScriptEditor图标"},null,-1),v=e('

加载、关闭和执行模块

可以通过点击加载按钮加载按钮模块->加载模块库菜单项将模块加载到MicroCity中。工作区面板的模块选项卡将显示已加载的库文件模块库图标(每个对应一个文件)及其包含的模块模块图标。可以通过上下文菜单关闭或重新加载模块库。执行模块有多种方式:双击模块,点击设置面板的执行按钮,或点击执行上下文菜单项。还可以通过点击调试上下文菜单项来调试MicroCity脚本模块,这需要后台运行ScriptEditor。MicroCity还可以捕获运行时错误并暂停模块的执行。

module_file_menu    module_menu

加速、停止模块的执行

',4),E=t("strong",null,"MicroCity Script",-1),G={href:"https://www.lua.org/",target:"_blank",rel:"noopener noreferrer"},N=t("strong",null,"工作区",-1),A=t("strong",null,"模块",-1),V=t("img",{src:g,alt:"icon_module_lib"},null,-1),B=t("strong",null,"模块库",-1),I=t("strong",null,"设置",-1),R=t("strong",null,"脚本运行模式",-1),T=t("strong",null,"安全模式",-1),j=t("strong",null,"快速模式",-1),q={href:"https://luajit.org/",target:"_blank",rel:"noopener noreferrer"},z=e('

如果一个模块正在被执行,可以通过点击相应的 设置 中的 执行 按钮来停止它。在 安全模式 下,执行可以立即停止,但在 快速模式 下,停止操作取决于脚本中调用的 GetReady() 函数(参见 4.2)。

module_libraries_settings    module_settings

',2),J={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},P=t("strong",null,"反馈",-1);function D(F,H){const s=n("ExternalLinkIcon"),i=n("RouterLink");return f(),b("div",null,[k,t("p",null,[o("MicroCity的功能可以通过模块进行拓展,其中之一是"),t("a",x,[M,r(s)]),o("(*.dll)。"),w,o("包含许多有用的"),S,o("(*.mcs),可以使用"),L,o("进行编辑和调试(请参阅"),r(i,{to:"/docs/4.1_si_overview.html"},{default:y(()=>[o("4.1")]),_:1}),o(")。")]),v,t("p",null,[E,o(" 模块是使用非常快速的 "),t("strong",null,[t("a",G,[o("Lua"),r(s)])]),o(" 语言创建的。在某些情况下,如果您想要更快的执行速度,可以在 "),N,o(" 面板的 "),A,o(" 标签中点击 "),V,o(),B,o(",然后在 "),I,o(" 面板中将 "),R,o(" 从 "),T,o(" 切换到 "),j,o("。然后 MicroCity 将使用 "),t("strong",null,[t("a",q,[o("LuaJIT"),r(s)])]),o(" 来执行模块。")]),z,t("blockquote",null,[t("p",null,[o("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),t("a",J,[P,r(s)]),o("页面提交反馈。")])])])}const X=p(C,[["render",D],["__file","3.7_modules.html.vue"]]);export{X as default}; diff --git a/assets/3.7_modules.html-d3BG3VZc.js b/assets/3.7_modules.html-d3BG3VZc.js new file mode 100644 index 00000000..985c2efa --- /dev/null +++ b/assets/3.7_modules.html-d3BG3VZc.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-35430c3c","path":"/en/docs/3.7_modules.html","title":"3.7 Modules","lang":"en-US","frontmatter":{"prev":"./3.6_maps_and_layers.md","next":"./4.1_si_overview.md","description":"The functionality of MicroCity can be extended by modules, one type of which is SAGA Module (https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.7_modules.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.7_modules.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3.7 Modules"}],["meta",{"property":"og:description","content":"The functionality of MicroCity can be extended by modules, one type of which is SAGA Module (https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.7 Modules\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Loading, Closing and Executing Modules","slug":"loading-closing-and-executing-modules","link":"#loading-closing-and-executing-modules","children":[]},{"level":2,"title":"Accelerating, Stopping the Execution of a Module","slug":"accelerating-stopping-the-execution-of-a-module","link":"#accelerating-stopping-the-execution-of-a-module","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/3.7_modules.md","autoDesc":true}');export{e as data}; diff --git a/assets/3.7_modules.html-heS1MNUm.js b/assets/3.7_modules.html-heS1MNUm.js deleted file mode 100644 index 266b2dc8..00000000 --- a/assets/3.7_modules.html-heS1MNUm.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-656b8bd0","path":"/docs/3.7_modules.html","title":"3.7 拓展模块","lang":"zh-CN","frontmatter":{"prev":"./3.6_maps_and_layers.md","next":"./4.1_si_overview.md","description":"The functionality of MicroCity can be extended by modules, one type of which is SAGA Module (https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.7_modules.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.7 拓展模块"}],["meta",{"property":"og:description","content":"The functionality of MicroCity can be extended by modules, one type of which is SAGA Module (https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3.7 拓展模块"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.7 拓展模块\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Loading, Closing and Executing Modules","slug":"loading-closing-and-executing-modules","link":"#loading-closing-and-executing-modules","children":[]},{"level":2,"title":"Accelerating, Stopping the Execution of a Module","slug":"accelerating-stopping-the-execution-of-a-module","link":"#accelerating-stopping-the-execution-of-a-module","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/3.7_modules.md","autoDesc":true}');export{t as data}; diff --git a/assets/3.7_modules.html-mmRRzoSK.js b/assets/3.7_modules.html-mmRRzoSK.js new file mode 100644 index 00000000..ca3d91d9 --- /dev/null +++ b/assets/3.7_modules.html-mmRRzoSK.js @@ -0,0 +1 @@ +import{_ as a}from"./icon_script_editor-ibm_2NsU.js";import{_ as l}from"./button_load-GOP3K2yO.js";import{_ as c,a as d}from"./icon_module-AxwvBQMt.js";import{_ as u,a as g,b as _,c as h,d as m}from"./module_settings-yrsWXh8u.js";import{_ as p,r as s,o as f,c as b,a as e,b as t,d as o,w as x,e as r}from"./app-LOf__QKq.js";const y={},M=e("h1",{id:"_3-7-modules",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-7-modules","aria-hidden":"true"},"#"),t(" 3.7 Modules")],-1),k={href:"https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga_modules2.0.8.zip",target:"_blank",rel:"noopener noreferrer"},w=e("strong",null,"SAGA Module",-1),S=e("strong",null,"SAGA Modules",-1),L=e("strong",null,"Shapes",-1),C=e("strong",null,"Grids",-1),E=e("strong",null,"Module",-1),T=e("strong",null,"MicroCity Script",-1),v=e("img",{src:a,alt:"icon_script_editor"},null,-1),A=e("strong",null,"ScriptEditor",-1),I=r('

Loading, Closing and Executing Modules

Modules can be loaded to MicroCity by clicking Load button button or Modules->Load Module Library menu item. The Modules Tab of the Workspace Panel will display the loaded Librariesicon_module_lib (each of which corresponding to a file) and their inside Modules icon_module. One can close or reload a Module Library from the context menu. Executing a moule has many ways: double clicking it, clicking the Execute button from the Settings Panel, or click the Execute context menu item. One can also Debug a MicroCity Script module by clicking the Debug context menu item, that needs the ScriptEditor running in the background. MicroCity can also capture runtime errors and pause the execution of modules.

module_file_menu    module_menu

Accelerating, Stopping the Execution of a Module

',4),G=e("strong",null,"MicroCity Script",-1),N={href:"https://www.lua.org/",target:"_blank",rel:"noopener noreferrer"},P=e("img",{src:u,alt:"icon_module_lib"},null,-1),R=e("strong",null,"Module Libraries",-1),V=e("strong",null,"Modules",-1),B=e("strong",null,"Workspace",-1),D=e("strong",null,"Script Running Mode",-1),F=e("strong",null,"Settings",-1),O=e("strong",null,"Safe Mode",-1),W=e("strong",null,"Fast Mode",-1),j={href:"https://luajit.org/",target:"_blank",rel:"noopener noreferrer"},z=r('

If a module is being executed, one can stop it by click the Execute button in the corresponding Settings. In Safe Mode the execution can be immediately stopped, but in Fast Mode the stopping is depend on the GetReady() function called in the script (see 4.2.

module_libraries_settings    module_settings

',2);function J(q,H){const n=s("ExternalLinkIcon"),i=s("RouterLink");return f(),b("div",null,[M,e("p",null,[t("The functionality of MicroCity can be extended by modules, one type of which is "),e("a",k,[w,o(n)]),t(" (*.dll). "),S,t(" contains many useful libraries for "),L,t(" and "),C,t(". Another type of "),E,t(" is "),T,t(" (*.mcs), which can be edited and debugged with "),v,A,t(" (see "),o(i,{to:"/en/docs/4.1_si_overview.html"},{default:x(()=>[t("4.1")]),_:1}),t(").")]),I,e("p",null,[G,t(" module is created with "),e("strong",null,[e("a",N,[t("Lua"),o(n)])]),t(" language which is very fast. In some cases, if you want much more faster execution speed, you can click the "),P,t(),R,t(" in the "),V,t(" Tab of the "),B,t(" Panel and switch the "),D,t(" in the "),F,t(" Panel from the "),O,t(" to the "),W,t(". Then MicroCity will use "),e("strong",null,[e("a",j,[t("LuaJIT"),o(n)])]),t(" to execute modules.")]),z])}const Z=p(y,[["render",J],["__file","3.7_modules.html.vue"]]);export{Z as default}; diff --git a/assets/3.7_modules.html-q0PqEjdM.js b/assets/3.7_modules.html-q0PqEjdM.js deleted file mode 100644 index a7b1152c..00000000 --- a/assets/3.7_modules.html-q0PqEjdM.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as i}from"./icon_script_editor-ibm_2NsU.js";import{_ as c}from"./button_load-GOP3K2yO.js";import{_ as f,a}from"./icon_module-AxwvBQMt.js";import{_ as l,r,o as h,c as g,a as t,b as o,d as e,w as u,e as s}from"./app-DaLjD81q.js";const P="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAP8AAAFjCAMAAADFBS10AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKyUExURf///6CgoOPj4wB416WlpYKHkGlpafDw8PLy8tzc3MzMzAAAAPHx8fz8/I6Ojqurq9TU1AAAhAAA/9fX1//bkAD///DOhzo6kNv//87w8Kvw8PLyrKzy8gCQ7PKsYQA2iDYAADp418/y8rb//4fO8JGRkWEAADYAYPDOhtvq7PLPiDY2h2Gs8gAAYfLyzzoAZvr7+zU1hog2AAAANmCr8DaIz/Dwq/CrYABhrIjP8vDwzpCQ15Db/21tbWEAYQAAYAA2h9vbkP+2ZgCo8mZ4186HNv39/axhAAB43s+INgA6kDoAAGa2/wBgqwCt/4c2Nv//tmAAAO3t7DYANjUAAAB45f7+/v//26tgAP/q7GbU/zqQ27ao1zaHzpDq/4c2AJA6ANu+3gAAOobO8AAAZoSEhPr6+rS0tNnZ2bZmAM6GNWAANv/U5Tq++P//+Etjp9uQOgBmtpDq+AA1hmYAALb/8joAOrq7vGAAYP//8jWGzs7OhqvOhmYAOvb29mYAZpubm8fHx/X19bb/+DUAYM7wq2EANtv/ttv/+LZmZpBmAAAANTYAYWA2NrbbkAA2YJCQOjZgYJCQkKysrIhhANXV1TUANTY2NjU1NZA6OqtgYKvwzs7Oh5DU/4iIYYeHztv/8oY1ANvq8tvU5Yg2NqtgNaxhYWbU8mAANTY2YM6HYIarhjpmZjY2AIeHNqvOh6tgNoerh4fOq2A2hwA2NqurYDVgq2A1hoY1YKuHNtvq+La+7JCQ29u+5bbq+M7wzmao8v/q8mA1ADVgYGCHhzZhYTU1YGaQkIis8odgAIZgADq+8quGNYhhiAA6Zjo6ZjWGhqzyrGY6Os/PiNuQZoY1NWGsz5C+3mCGzjp45azyz8/yrDo6Orb/25C2kGY6kLZmOpDbts6GYIbOq4Zghs+sYVBAmB8AAAwGSURBVHja7d2JQxTXHQfw0bUO5pljpyzCAguKHCUclfuyICqIgoGoiKLGVKti1aoxiSE2p7ZpYluTmMaYNG2TpleS3jl63/d933f7f/T3e+/Nziy7KuwuMrvzfS47b2ZnYD/v93tvrgWNBT4uixYtMhaYvi3wX9pftaLAN362Vn1gj9lyMpzlfiHcE9vP7oMXmmLMWRp/Kdd8J/9f2GNefGXSbJ00qzaL7nDVih93n1pR0PrInoNC3Hb3978tRJNJ1UcoRUaoTitRNWMbwOY7/oOTHf8981rBWFPLCEGHqjZzLtx9Olx1OmxePEU9o7Wbe0brUMdHmlS6ZG56iCjf8Ve9WvVqx+tPvx6WI8HpU/y8mcgtI92K2vKJPRR0ygVmc010h7PI33LylSbz3/95rcDlX/HTIX5lhHsC+V+kLKCckP5MHhoS5r/5wgXK8QuTps5/6S8Ym6z6o9nxuxdprlVG/uBt35D5Tytl1/hHMs74JtMe/6S/ZeSXNNpNcrpTto8J8Z0VBTzTJLtCQcby4/Z/ly/ZeyQEP47/jQWGX8tC7Z/vzzIv6vdn9sPv+N/guzLF77ex74p+Ok3wm1+IKJoqlv/8lmWpJhChkC/9BqOv7M9dkh9XS/hyBsZ/qj93wzF6nthbdmV/bn2ZXLQqAxrlsvFnftR/xy/KjOET0/dnQfxj/PXnBo3el4iWu0G8tYsTQoj1+WykL3ps3S0Xx8T/YV6Uu+ThvedoOBmXtfdF15zgRRnkp3f+z7/Xl23dTe2wPp8nCq4nE+O8OMa/YdA4Sk1EE5lAXVyLrkmP4a96Ov+Zbzj+vz31r3+sqi9j8fA7uxjp9r/73jJePLX/56oNqGx9qkutrNfUjZU5/rKjfx2nZ37fFHyeuP2rqDvoDuD2D9+r/Ef5RbWyXpN6gRjMKD9nMD3Xy/DZcDsNOKoJxn8d/969ZTHxV+Xo3KfA5fo/891+9az7P+c6d+47uoyJ9br/G+8pm+qfOCZ3A0ePyf6v2kyt+dsuo/eYp+Of2M8DP+8Fe4V4iWVC/MAe/8UxfahACU4D/Sq5h5D+4RPi57+2/WpN2j5mZ+rx+Pvt/Mc+CfLh+R/O/1VZmeBigFMPpFgyL/5CBIPCR/6VcfqgqwH8FX+tdzXAZXHFb1qa2f47y1W5U/NDweCUBshuf/mbVSnX/mBcA/jMH9cAgcDqQ4HAdv669TDN30roD961Zt0u40gnV3kSKM5Xc0vl13ZeS62QeX5XA8jdoAzyuuPPrVl3nDnFD3UW5+/gxgis3raUqzRZt0tOtJ9qW/6gV/C8/+Z3cLm5nPYC9E+OfiFb/zYVf4IXP394x5bb1wTUDDF5ZsuDnVosl0TnJFuv4H2/KuWGkwCyAViv/YHtOw7vWH2o+PlAgDrAEcXkM9ojbjHlgJ6jzDd26BU879c3h8uNmAYgfcgI6fwPrP7a8c4tt3+TEvquNa746/GP4/9hlQ00USPi4W1/UitknF82AMXe5rO/+Ms8qD3XGTh8SPZ/JlL3Dnx8TTTiqv8/1BnYvm3pTzp5yFQrZNj+XzeAIL5w9v/rdpGFYh/YUmZ86+vKz0l+KDriU7bTy9w9vkK9weAZtUJGHv9T/MXMjn+v8XCZ+fmvmPH53zU5ni1J+GOKL/0rZ9i9yH+5j55kcvypBH3nXxmj50OCzPXn3LOvbzSF+AeDlhXM4PgfmL9432gq8beC/KCa5Sx07gp73r///vkP9CUf/6DyE95y/MMnBu27QGnxV5eWLJst/337D+T0pTL+c/6T3wqFLLsJ9Ecfcpesqj8nxOCEl/2PPf7E4mtT6v+kJz/pQ1Y0/uPav2Hc6BWDXvZfd/0NM/avdP2TuwBldxqA+/+gfe93Sf40/BUk7Bc1Of21f24QorGdzG39tUWFFUI0s/9/PM3h2doifi2nroEqEToWrclRK11Ff3yx/c4Y0Ms3+qfv729sJ0ZzXUPJX0hDyOrSL5bW/orroobrvKxQzvJryl9dyq+qpTVz6o/Nf/lBj92DM/EPkHLTy22FFc26NapLKQkioo2C3cz1worG9oiQWdJs+yMy7HqluY2/Gv/s2I+rD/rMwE+ASMn5kt9saq+j/Bfsb+NW4dIm+z+1yQB7Bxw/R75kmV5pbuPPTWA4459QH/mavp8S/3xzpPHZ2qIBint/1N8cHf/6Of60rJ/7Q8mywgrq/zwAtA0k3fnT60/t+G+g8WVyPdmmYq79hfZYoPx2/7enERl4vdJc+1M8/q0urS2i1Jejecl57c+pLnX77fGfw/77BuWnV9RKGe6fq+Nf+OGHH3744Ycffvivuv+Nc1YQf/jhhx9++OGHf+79hW8p8qmfr222+dcf4TtYkWa/+gsranyd/xF9h5v99lX+ATlJ5e5uRvrlPdBIbVH1WU6Fwne159Q11PjIL6tE5ju+8laPmMUE8Ez/pzDH+D/azo3Q2B6ZtY9+eGv8H5DBbo7mf8my6h+qLKDc/1hR9u//I8Le/9vjX7+8q893N2t8c/yH43/44Ycffvjhhx9++OH3nf8Sl8HSfzLsFb/81Lej86GfznH72/ztj/jbX9egf8WnOeYyiL4AIj/mntX9n6+A6cu9rsvAdT9bxhN5Haw/q+PP3V9f7nVdBtb3AeRsduc/h1gLXZeB+Vebqs/6wZ8zwL/WIy/3ui4Ds3lA5X9dQ3b76xra9GjnGv94ZPjeWfm7jo3PZq0fx7/ww+9P/9wV+OG/On6vFvivht/D5Wr4Zck5sP++x67zXEnm798kVe6Zf//+x6/3XEnx7x9Nv+xbPP/AEzd4riTz96+SKn37HshZ7L2S6t8/m3YZHe3ru9Z7pa9vdBT//wP88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDD7zm/70qsP71lXmaUWfLPW5gpZbb8SW+YwltJ5qd61C9cxZd+Z5jOXH8SMXT8oVBo40bLCF5tfzCN8RczDqLjT6IHpMEfNINU0pb/iRogr5RETfZcx03LL+FP0APySofoeaw7PHv+oGVNi593Y0FcLVH+J0BUhgmy88r++B6Qt+mTYbNlZDb9VpAfVLNc1gTNPh2/KUKh+AZgv9naHV5LrbOz4xZ67vkSV+P88T0gr/LTTWbro5VqW/rJPxKN1HxjeuvU/UHlJ7zl9ido9mn5ZQPEI+j7tLx9ufzGy+34UzXOH9cD8io/c2PBZz/H34A3yCttMtf2FLT2FLR8KF3jH+c/+a1QyIo2QbTZue9yg3MX7ilgOH3Rg6LojoM7/0N2icl/s+OWJpX8tl9PY/1Te0Be5dM3ff4Lz0g/bcBvgBqS/Gns/6QnP+lDlvOOdbPzu6afxhMF15Oxnbw4Ggcn/y0rvgGi8ackbtR+WZ1y/KP9lmVYjj+89smd/A3kBtrPfagpfft/GX2yOw0QbXb9A+UI5vKfORmOiYMr/6kBEuY/9X962PFX1djjX/ZvpGIFY/yc9pV6W/kGZDKslT86bcc/tt+a0uwspODzxO1/hvdojU4cXO+EGkCXKeM/9dwh2enHaBNdvZR/o+FuOvl25Ab8Bqj2qeVm61B6j/+m5r9udv75HH8Nt9OA46/KWp0CzjuJbwB7/98yIt7/3uU823NGVWP91APUhgn8als1DJmtQqihOX3xV+NfzIjFz7r/y85L4x9Hr0f3f/NiOBqHmHcys8M49/mfMPhohOIfusTh49Q9TzqP/0kf7+dgcVNTiz/KuSfEd+3xXww5cUjT+e8Vz4Fm1T/35/8zPgPw0vlfstejTNNI/mKW6R1/koU3XpjKxsn5U2j0tEVibor2m+m9qmhmmN/Hhf2L/F387v8/d7iN0ESosl4AAAAASUVORK5CYII=",d="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAP8AAAFjCAMAAADFBS10AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAL9UExURf///6CgoOPj48zMzKWlpYKHkGlpafDw8PLy8tzc3AB41wAAANfX1/Hx8Y6Ojvz8/NTU1KurqwAAhAAA///bkKOjo2NjY4aGhoWFhaGhodv//zo6kAD///DOh87w8Kzy8tvq7ACQ7Kvw8PLyz2Gs8og2ALb///LyrDp41wAAYfLPiGEAADYAAJDb/4fO8JGRkTYAYPDOhgAANgA2iDY2h4jP8s/y8joAZvr7+zU1hmCr8PKsYf+2ZvDwq/CrYPDwzv//26xhAAA6kJCQ121tbQAAYDYAYf//tjaIzwA2h2a2/zqQ7JA6ADoAALZmAM6HNjqQ2wAAZgBmttuQOs+INgBhrABgqwCt/wAAOoc2NmAAADYANu3t7KSkpLao1zUAAAB43qtgANvbkP/q7DaHzmYAZoc2AIbO8GYAOoSEhJA6OgCo8pDq+M6GNWAANjoAOktjp///+GZ41wB45QA1hrq7vKmpqWAAYJDq/zWGzpBmAM7OhqvOhtu+3tv/8v39/YiIiNv/+Nv/trZmZjUAYM7wq2bU/6xhYQAANWYAAGA2NrbbkAA2YP7+/jo6Zvr6+mRkZGVlZWEANtnZ2bS0tGdnZ2hoaJKSkpeXl7u7uzZgYJ2dndbW1uTk5Ojo6O7u7jUANTU1NQA2NqtgYKvwzs7Oh4iIYYeHzoY1ADp43rb/+DZhYatgNZCQOpCQ22aQkGAANTq++DY2YDo6Os6HYDpmtoarhv//8jqo8jpmZs+sYQA6ZmY6OoeHNtuQZqvOhzY2NofOq2A2h6tgNoerh6urYDVgq2A1hoY1YGa++KKiovb29vX19ZCQkKysrJubm8fHx9XV1UhLUHuAiICFjp+fn1dbYWxweIiIz2bU8quHNpDU/5C++GFhYYg2Yc7wzmA1ADVgYIg2NmGsrGCHh7a+7DU1YIdgAIZgAKzyrKuGNTqQtra2ZohhADWGhv/q8rbq+GGsz4Y1NWCGzrb/25C2kGY6kJDbtrZmOoZghs6GYIbOqzp45f/U5c+IYYQezC0AAAxXSURBVHja7d0HfNTWHQdwMYoOvyZtT27TkvM5nO0jGBsPYijnhSHGI2DAi8ZJDSYQWihNSwY4gZC0QJMmIW2TrnSkhKQz6UqzuldW9957773Xp///e08n3fDgONvS6fewTzpZsvV9//970tOLHWNugMv8+fONuWZgC/xj++tWRgPjZ2vdm3aazftiBe4Xwr2w/ezeczyRYi7Q+Eu55jv5f/dO88TDo2bLqFm3RbTH6lb+ov3AymjLdTv3CHHZVT/7gRAJk1avoxQZonXaiVZ9WwE23/HvGW3955FHoyOJ5iGCDtZt4Vy46nCs7nDMPHGAWkZLO7eMlsHWtyZUuvg3PUSS7/jrHql7pPWxOx+LyZ7g8AF+3ULk5qF2RW1+904KOuUCs3lNtMcKyN+87+GE+a9/Pxp1+Vf+apC/MsQtgfz3UxZQTki/n7uGrPlv3n2ccvz4qKnzX/qjI6N1fzZb/3Q/vWuRkd9z2fdl/tNOhdX/kYwzPmHa/Z/0Nw/9jnq7UU53yvYRIX64MspvErIpRH3Lz7j+jV8K904Iftz/G3ONoJZ52j87mGVW0h/M7Iff8T8hcCXNH7S+b0I/DROC5hciiaYVK3h+y7JUFYhIJJB+g9ET+4vPXJCxlvXLPox/ur94fS+99myKT+wvXhGXm7b5oFLGjT/zk/5LjsWNjusn7y+A+Kf4V9zTbTQ9RLTi9eJZ1ZwQQqxewEb6pI9V6+TmlPhfyZuKz7xy0z3UnWyUazck9+zhTT7y05n/468r4qvWUT2sXsALBdeLno28OcW/vtvooyqihUygal5L7kkfHe/0dP4z33D8f9n1979tWxFnccdzqhnp9r9oR5w3p7f/YnUAlVW7qtXOek9dWf7xx/vu3UivfN4UfF64/duoOegG4PZ37FD+Pv6i2lnvSa1AdPvKzxlMrytk+Gy4nQYc1Sz9v45/06Z4SvxV6Zv5FBiv/TPf7Vevuv1zrnPjvqTa6Fmt27/x4ni6v6dXXgb6emX7V3Wm9vxwtdHU6+n4Z/dzx89XwSYhHmKZEO+y+3/Rq28VKMGpo98mrxDS33G9+MAHbb/ak45PuZh6PP5BG//Yg6AAjv8w/lfl3CwPA4IcfyHCYRHY+LM+XHAVMNn4a/1kK8APQ79x/ZfXqHK55kfC4ZOpAN/7a56pSo32h0+uAgrPn6UC+Pa1hz839iWH93E1uC9WQ3/9rEDf96kRv/OcwF9+VwXoyyDfyu46xgMbZ3hvqME9r+qHBE3JhyRqxO88J/C0/8IXcLmwhq4C9E/2fhFb/1y1D4/o7uvr7pDjOT2869iRMjrUzwqSfsPewft+VWoMJwFkBbBe+42e7r7upt7i+9zDezW4d4kpB1zjnu5i5zmBp/16crjGSKkA0keMiH0b2PTrXdUdO36z0TW8V8lguJ4OOM+K5Ijf9ZzAV35ZARR7F98ovpc7tWPVruG9oQb3yYir9q8eEqgRv/OcwEfXf10BgviuMcCqdWSh2LuG94Ya3Ns9vn5WoB4SqBG/85zAd/f/FH8R0PtffRMc6PEfnn9keSTgLkW5F1/GPxw4/7kper4lCG78w2HLCk86/gvPOrvQ4m+F+YPWLMe/kG4BLjo7C9betPV5a7JVhv/iH1Z+wluO/9L4cFHRN/eOE3/pL4j4G5z/5LciEUtVASmv3quw5139HcMYPmq8cA3D6XPhWY/THge37qfXi86j9wvoa/SFb/PCp+2f9OQnfcRKxv+g9i84WLTbGC7azVblp/gvvHaNzv+37eevUS3IhY/i7/yTlwBl1xWg2/8w+5XaWZN+wms/b7307XZy+PT6z8X2W8n+fzfnfDb/ewzKde1/kIK+df+w//2p+S97OGa5/NQlSP+DD+x1xZ+2Fkb8Vf+n/bsPykae4r92TdFRviQ+/l/+UtHRYXf793/8uQoMp/8zVLfu+Dntf8rx/0/c+P0f1nAPofv/B/YWFYY/qOOfSY7/5ni5TIc/5N0yZxqef8AfGu/3b+CHf+b8b3jj61717AD757z+Na8Msv+K157+cs/4Fy1ZXJrtLCurUrePtV8O/ldfcc3LPOCvrBKivmEy/v76hnz6r/nUGU976oz7mU/+sc7S7W8be7dc/Gc84+ke8DeKgVDofzL+lVXL3k9V0ShEJ7kHQmUVvG1xaVmFrKE2qqgBGf9FS4SQC9qf9vW5X0ZV+e+gZLhDtge3n7nkTfrle8FL3jfX9uARPwdXlGs/f4py2lTu9tu536bbf6NYtpyyoXPRkvqGsopcG4VH/CGZ1+U6/5fL/G5L9csqcvn7Oef72c/14HN/Yzm3gc5Mv1pnf7+2O/Ef4ForLwy//HWDjPjbbVz6hbA7wLT2XwB+ef2z27/j53r5o9P/LfstMWnX9P7f//6Zu/+FH3744Ycffvjhh3+6/U+cuYL4ww8//PDDDz/88M/k/Ee+5jR96S8f/zwn3AH+AvD382P/AflkvzOkFpVrS0OVa39JqzwtkPtErw/aP89ndTYS8xUNXCGLlrBV+Uu5gvT2Qs5/nszVk2FcE6l+vb3w/RIeyvSr7YXsb+vs52ZOb15SyotF36i8oIG7BZn/anvBtv/6hrZly8sqBuRsaLmcFKX+sF+Id6zlxbLlejvu/+CHH3744Ycffvjhx/wn5j+R//DDDz/88MPva/9UTff4Zf4zeH75C1DlgfbLuY4g+9UkB09xlVX8eAk/69ezP7y1/s1TMP3jOb+e4+Rfegw1Li7Vfp75KasofP+PGvQcp3xPL9ovZ/4aC95PQo0MpL9R/marnOPkWUCe9tSznwHIf8H/gUcopOc+yyq+q+4H9OwnbS3o/m8ypTG4/rLv8SWwMxTY+HOr6AyFAp3/hXr/N4MFfvinxe/ZAv80+L1cpsEvS+iWWz//2dM9V740DX//TZZPz/7CrZ97iufK16bh7//JcvNps2/54pM9V74+DX//UZZDN38mdJr3ypen4e9/ynLTTYcOPcl75Su33/5V/P+f4Icffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH34/+wNXUv35LbP8UabIP2ueX8pU+XM+8BROJZef6lG/cJVA+p1u2r/+HGLo+CORyObNlhGebn84j/EXJx1Ex59DC8iDP2yGqeQt/7NVQEkViRL2u9bzl47hz9ICSqoG6XWkPTZ1/rBlTYpfck40Yy1b/mdB1MYIsn1if2YLKLngvTGzeWgq/VaYP2jNclmzVPtk/KaIRDIrgP1mS3tsA9XO9taL6bXrW7ya4c9sASW1H0qYLbfVqmPpJ/9c1FP1jeijT90fVn7CW25/lmqflF9WQCaCvk/z85fKb7zUjj+tZvgzWkBJ7UfOiX7ik/wN+ICSqoS5oSva0hVtfku++j/Of/JbkYiVrIJktXPb5QrnJtwVZTh90gdF0R0Hd/5H7JKS/2brxQmV/LZfL1P96S2gpPbO8z/28buknw7gE6CKJH8e2z/pyU/6iOWcsa52Pmv6abxQcL0Y2c6bk3Fw8t+yMisgGX9K4nrtl6tp9z/ab1mG5fhjGz66nb+BPED7uQ0l8nf9l9Enu1MByWrXP1D2YC7/kX2xlDi48p8qIGv+U/unDzv+ajX1/pf9m6lY4RQ/p32tPlaegEyGDfJH5+3+x/ZbadXOQgo+L9z+u/iKVu/EwXUmVAG6pPX/1HIHZaMfoUP06lj+zYa76uTpyAP4BGjtfUvNlsH83v+l57+udv75HH8Nt9OA46/KBp0CzplkVoB9/W8eEje+dCm/7TqiVlP91ALUgVn86ljVDZktQqiuOX/xV/1fSo/Fr7r9y8ZL/R9Hr0u3f/NELBmHlDM5uds49/hPGHw3QvGPjHH7mH7lyef9P+kz/Rwsrmqq8ds494T4id3/i0EnDnka/044BppS/8yP/096BOCl8V+uz6NM08j9YZbpHX+OhQ+edyoH5+Y/hUrPWyRmpmi/md+niqbP/AEu7J8f7BJ0//8BBRwxo36FEUsAAAAASUVORK5CYII=",v="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAZElEQVR42s1TWw7AIAwq9z80e9mF6NTaJcv4qlgoNRGWA72AHgSYCa8SbsCRFreCpQ9oDY67k98plkY4ETHQgSmDSYJKbMsJPjAYrGCVWIb+yqD7Bq3Y1hJEDV4mCEE/CZ/IFDZVF3sClc46gQAAAABJRU5ErkJggg==",z="/MicroCityNotes/assets/module_libraries_settings-lee40Qvj.png",m="/MicroCityNotes/assets/module_settings-3JBvpV80.png",p={},b=t("h1",{id:"_3-7-拓展模块",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-7-拓展模块","aria-hidden":"true"},"#"),o(" 3.7 拓展模块")],-1),D={href:"https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/saga_modules2.0.8.zip",target:"_blank",rel:"noopener noreferrer"},w=t("strong",null,"SAGA Module",-1),Y=t("strong",null,"SAGA Modules",-1),H=t("strong",null,"Shapes",-1),O=t("strong",null,"Grids",-1),y=t("strong",null,"Module",-1),G=t("strong",null,"MicroCity Script",-1),M=t("img",{src:i,alt:"icon_script_editor"},null,-1),Z=t("strong",null,"ScriptEditor",-1),j=s('

Loading, Closing and Executing Modules

Modules can be loaded to MicroCity by clicking Load button button or Modules->Load Module Library menu item. The Modules Tab of the Workspace Panel will display the loaded Librariesicon_module_lib (each of which corresponding to a file) and their inside Modules icon_module. One can close or reload a Module Library from the context menu. Executing a moule has many ways: double clicking it, clicking the Execute button from the Settings Panel, or click the Execute context menu item. One can also Debug a MicroCity Script module by clicking the Debug context menu item, that needs the ScriptEditor running in the background. MicroCity can also capture runtime errors and pause the execution of modules.

module_file_menu    module_menu

Accelerating, Stopping the Execution of a Module

',4),q=t("strong",null,"MicroCity Script",-1),x={href:"https://www.lua.org/",target:"_blank",rel:"noopener noreferrer"},N=t("img",{src:v,alt:"icon_module_lib"},null,-1),k=t("strong",null,"Module Libraries",-1),L=t("strong",null,"Modules",-1),C=t("strong",null,"Workspace",-1),T=t("strong",null,"Script Running Mode",-1),U=t("strong",null,"Settings",-1),V=t("strong",null,"Safe Mode",-1),X=t("strong",null,"Fast Mode",-1),W={href:"https://luajit.org/",target:"_blank",rel:"noopener noreferrer"},B=s('

If a module is being executed, one can stop it by click the Execute button in the corresponding Settings. In Safe Mode the execution can be immediately stopped, but in Fast Mode the stopping is depend on the GetReady() function called in the script (see 4.2.

module_libraries_settings    module_settings

',2);function S(_,Q){const n=r("ExternalLinkIcon"),A=r("RouterLink");return h(),g("div",null,[b,t("p",null,[o("The functionality of MicroCity can be extended by modules, one type of which is "),t("a",D,[w,e(n)]),o(" (*.dll). "),Y,o(" contains many useful libraries for "),H,o(" and "),O,o(". Another type of "),y,o(" is "),G,o(" (*.mcs), which can be edited and debugged with "),M,Z,o(" (see "),e(A,{to:"/docs/4.1_si_overview.html"},{default:u(()=>[o("4.1")]),_:1}),o(").")]),j,t("p",null,[q,o(" module is created with "),t("strong",null,[t("a",x,[o("Lua"),e(n)])]),o(" language which is very fast. In some cases, if you want much more faster execution speed, you can click the "),N,o(),k,o(" in the "),L,o(" Tab of the "),C,o(" Panel and switch the "),T,o(" in the "),U,o(" Panel from the "),V,o(" to the "),X,o(". Then MicroCity will use "),t("strong",null,[t("a",W,[o("LuaJIT"),e(n)])]),o(" to execute modules.")]),B])}const R=l(p,[["render",S],["__file","3.7_modules.html.vue"]]);export{R as default}; diff --git a/assets/3.7_modules.html-yzio17Ud.js b/assets/3.7_modules.html-yzio17Ud.js new file mode 100644 index 00000000..066c1917 --- /dev/null +++ b/assets/3.7_modules.html-yzio17Ud.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-656b8bd0","path":"/docs/3.7_modules.html","title":"3.7 拓展模块","lang":"zh-CN","frontmatter":{"prev":"./3.6_maps_and_layers.md","next":"./4.1_si_overview.md","description":"MicroCity的功能可以通过模块进行拓展,其中之一是SAGA模块 (https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/sagamodules2.0.8.zip)(\\\\*.dll)。**SAGA模块**包含许多有用的**形状(Shapes)**...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.7_modules.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/3.7_modules.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3.7 拓展模块"}],["meta",{"property":"og:description","content":"MicroCity的功能可以通过模块进行拓展,其中之一是SAGA模块 (https://github.com/microcity/microcity.github.io/releases/download/MicroCity1.8/sagamodules2.0.8.zip)(\\\\*.dll)。**SAGA模块**包含许多有用的**形状(Shapes)**..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.7 拓展模块\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"加载、关闭和执行模块","slug":"加载、关闭和执行模块","link":"#加载、关闭和执行模块","children":[]},{"level":2,"title":"加速、停止模块的执行","slug":"加速、停止模块的执行","link":"#加速、停止模块的执行","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/3.7_modules.md","autoDesc":true}');export{t as data}; diff --git a/assets/3d-objects-en.html-rNfsYRE-.js b/assets/3d-objects-en.html-rNfsYRE-.js deleted file mode 100644 index 638f57e0..00000000 --- a/assets/3d-objects-en.html-rNfsYRE-.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-12c828e2","path":"/notes/3d-objects-en.html","title":"3D Objects","lang":"zh-CN","frontmatter":{"description":"This section will introduce the objects and their control functions in a 3D scene. Adding Objects To add objects to the scene, use the following function: Optional Object Proper...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects-en.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3D Objects"}],["meta",{"property":"og:description","content":"This section will introduce the objects and their control functions in a 3D scene. Adding Objects To add objects to the scene, use the following function: Optional Object Proper..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T09:36:02.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3D Objects"}],["meta",{"property":"article:modified_time","content":"2023-11-14T09:36:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D Objects\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-11-14T09:36:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Adding Objects","slug":"adding-objects","link":"#adding-objects","children":[]},{"level":2,"title":"Optional Object Properties","slug":"optional-object-properties","link":"#optional-object-properties","children":[]},{"level":2,"title":"Object Types","slug":"object-types","link":"#object-types","children":[{"level":3,"title":"List of Object Types","slug":"list-of-object-types","link":"#list-of-object-types","children":[]},{"level":3,"title":"label","slug":"label","link":"#label","children":[]},{"level":3,"title":"points","slug":"points","link":"#points","children":[]},{"level":3,"title":"polyline","slug":"polyline","link":"#polyline","children":[]},{"level":3,"title":"box","slug":"box","link":"#box","children":[]},{"level":3,"title":"sphere","slug":"sphere","link":"#sphere","children":[]},{"level":3,"title":"polygon","slug":"polygon","link":"#polygon","children":[]},{"level":3,"title":"External model","slug":"external-model","link":"#external-model","children":[]},{"level":3,"title":"Light","slug":"light","link":"#light","children":[]},{"level":3,"title":"Mesh","slug":"mesh","link":"#mesh","children":[]}]},{"level":2,"title":"Object Control Functions","slug":"object-control-functions","link":"#object-control-functions","children":[{"level":3,"title":"getpos()","slug":"getpos","link":"#getpos","children":[]},{"level":3,"title":"setpos()","slug":"setpos","link":"#setpos","children":[]},{"level":3,"title":"getrot()","slug":"getrot","link":"#getrot","children":[]},{"level":3,"title":"setrot()","slug":"setrot","link":"#setrot","children":[]},{"level":3,"title":"getscale()","slug":"getscale","link":"#getscale","children":[]},{"level":3,"title":"setscale()","slug":"setscale","link":"#setscale","children":[]},{"level":3,"title":"getchildren()","slug":"getchildren","link":"#getchildren","children":[]},{"level":3,"title":"setchildren()","slug":"setchildren","link":"#setchildren","children":[]},{"level":3,"title":"getparent()","slug":"getparent","link":"#getparent","children":[]},{"level":3,"title":"setparent()","slug":"setparent","link":"#setparent","children":[]},{"level":3,"title":"delete()","slug":"delete","link":"#delete","children":[]}]}],"git":{"updatedTime":1699954562000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"notes/3d-objects-en.md","autoDesc":true}');export{e as data}; diff --git a/assets/3d-objects.html-0syC6c1Y.js b/assets/3d-objects.html-0syC6c1Y.js deleted file mode 100644 index aa8302d5..00000000 --- a/assets/3d-objects.html-0syC6c1Y.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-0be8554c","path":"/notes/3d-objects.html","title":"3D 对象","lang":"zh-CN","frontmatter":{"description":"本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。 添加对象 向场景中添加对象,函数形式如下 对象可选属性列表 添加到场景中的对象通常支持设置以下属性中的某些属性 对象属性含义 :---:---- color对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 (./3d-scene.md#bgcolor-场景背景...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3D 对象"}],["meta",{"property":"og:description","content":"本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。 添加对象 向场景中添加对象,函数形式如下 对象可选属性列表 添加到场景中的对象通常支持设置以下属性中的某些属性 对象属性含义 :---:---- color对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 (./3d-scene.md#bgcolor-场景背景..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3D 对象"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D 对象\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"添加对象","slug":"添加对象","link":"#添加对象","children":[]},{"level":2,"title":"对象可选属性列表","slug":"对象可选属性列表","link":"#对象可选属性列表","children":[]},{"level":2,"title":"对象类型","slug":"对象类型","link":"#对象类型","children":[{"level":3,"title":"对象类型列表","slug":"对象类型列表","link":"#对象类型列表","children":[]},{"level":3,"title":"label","slug":"label","link":"#label","children":[]},{"level":3,"title":"points","slug":"points","link":"#points","children":[]},{"level":3,"title":"polyline","slug":"polyline","link":"#polyline","children":[]},{"level":3,"title":"box","slug":"box","link":"#box","children":[]},{"level":3,"title":"sphere","slug":"sphere","link":"#sphere","children":[]},{"level":3,"title":"polygon","slug":"polygon","link":"#polygon","children":[]},{"level":3,"title":"外部模型","slug":"外部模型","link":"#外部模型","children":[]},{"level":3,"title":"light","slug":"light","link":"#light","children":[]},{"level":3,"title":"mesh","slug":"mesh","link":"#mesh","children":[]}]},{"level":2,"title":"对象控制函数","slug":"对象控制函数","link":"#对象控制函数","children":[{"level":3,"title":"getpos()","slug":"getpos","link":"#getpos","children":[]},{"level":3,"title":"setpos()","slug":"setpos","link":"#setpos","children":[]},{"level":3,"title":"getrot()","slug":"getrot","link":"#getrot","children":[]},{"level":3,"title":"setrot()","slug":"setrot","link":"#setrot","children":[]},{"level":3,"title":"getscale()","slug":"getscale","link":"#getscale","children":[]},{"level":3,"title":"setscale()","slug":"setscale","link":"#setscale","children":[]},{"level":3,"title":"getchildren()","slug":"getchildren","link":"#getchildren","children":[]},{"level":3,"title":"getchildren()","slug":"getchildren-1","link":"#getchildren-1","children":[]},{"level":3,"title":"getparent()","slug":"getparent","link":"#getparent","children":[]},{"level":3,"title":"setparent()","slug":"setparent","link":"#setparent","children":[]},{"level":3,"title":"delete()","slug":"delete","link":"#delete","children":[]}]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"notes/3d-objects.md","autoDesc":true}');export{e as data}; diff --git a/assets/3d-objects.html-AEqGn78x.js b/assets/3d-objects.html-AEqGn78x.js new file mode 100644 index 00000000..e1273d82 --- /dev/null +++ b/assets/3d-objects.html-AEqGn78x.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6c395474","path":"/en/notes/3d-objects.html","title":"3D Objects","lang":"en-US","frontmatter":{"description":"This section will introduce the objects and their control functions in a 3D scene. Adding Objects To add objects to the scene, use the following function: Optional Object Proper...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/3d-objects.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3D Objects"}],["meta",{"property":"og:description","content":"This section will introduce the objects and their control functions in a 3D scene. Adding Objects To add objects to the scene, use the following function: Optional Object Proper..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D Objects\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Adding Objects","slug":"adding-objects","link":"#adding-objects","children":[]},{"level":2,"title":"Optional Object Properties","slug":"optional-object-properties","link":"#optional-object-properties","children":[]},{"level":2,"title":"Object Types","slug":"object-types","link":"#object-types","children":[{"level":3,"title":"List of Object Types","slug":"list-of-object-types","link":"#list-of-object-types","children":[]},{"level":3,"title":"label","slug":"label","link":"#label","children":[]},{"level":3,"title":"points","slug":"points","link":"#points","children":[]},{"level":3,"title":"polyline","slug":"polyline","link":"#polyline","children":[]},{"level":3,"title":"box","slug":"box","link":"#box","children":[]},{"level":3,"title":"sphere","slug":"sphere","link":"#sphere","children":[]},{"level":3,"title":"polygon","slug":"polygon","link":"#polygon","children":[]},{"level":3,"title":"External model","slug":"external-model","link":"#external-model","children":[]},{"level":3,"title":"Light","slug":"light","link":"#light","children":[]},{"level":3,"title":"Mesh","slug":"mesh","link":"#mesh","children":[]}]},{"level":2,"title":"Object Control Functions","slug":"object-control-functions","link":"#object-control-functions","children":[{"level":3,"title":"getpos()","slug":"getpos","link":"#getpos","children":[]},{"level":3,"title":"setpos()","slug":"setpos","link":"#setpos","children":[]},{"level":3,"title":"getrot()","slug":"getrot","link":"#getrot","children":[]},{"level":3,"title":"setrot()","slug":"setrot","link":"#setrot","children":[]},{"level":3,"title":"getscale()","slug":"getscale","link":"#getscale","children":[]},{"level":3,"title":"setscale()","slug":"setscale","link":"#setscale","children":[]},{"level":3,"title":"getchildren()","slug":"getchildren","link":"#getchildren","children":[]},{"level":3,"title":"setchildren()","slug":"setchildren","link":"#setchildren","children":[]},{"level":3,"title":"getparent()","slug":"getparent","link":"#getparent","children":[]},{"level":3,"title":"setparent()","slug":"setparent","link":"#setparent","children":[]},{"level":3,"title":"delete()","slug":"delete","link":"#delete","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"en/notes/3d-objects.md","autoDesc":true}');export{e as data}; diff --git a/assets/3d-objects.html-lKAwFYq5.js b/assets/3d-objects.html-frmlnhRb.js similarity index 99% rename from assets/3d-objects.html-lKAwFYq5.js rename to assets/3d-objects.html-frmlnhRb.js index 445bce7d..b5530684 100644 --- a/assets/3d-objects.html-lKAwFYq5.js +++ b/assets/3d-objects.html-frmlnhRb.js @@ -1,4 +1,4 @@ -import{_ as c,a as l,b as u,c as i}from"./polygon_sizes-bVJYQmiT.js";import{_ as r,r as o,o as d,c as k,a as n,b as a,d as s,w as h,e as t}from"./app-DaLjD81q.js";const b={},g=t(`

3D 对象

本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。

添加对象

向场景中添加对象,函数形式如下

local obj = scene.addobj([类型], {key1 = value1, key2 = value2, ...})
+import{_ as c,a as l,b as u,c as i}from"./polygon_sizes-bVJYQmiT.js";import{_ as r,r as o,o as d,c as k,a as n,b as a,d as s,w as h,e as t}from"./app-LOf__QKq.js";const b={},g=t(`

3D 对象

本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。

添加对象

向场景中添加对象,函数形式如下

local obj = scene.addobj([类型], {key1 = value1, key2 = value2, ...})
 

对象可选属性列表

添加到场景中的对象通常支持设置以下属性中的某些属性

`,7),x=n("thead",null,[n("tr",null,[n("th",{style:{"text-align":"center"}},"对象属性"),n("th",null,"含义")])],-1),m=n("td",{style:{"text-align":"center"}},[n("code",null,"color")],-1),y=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"opacity")]),n("td",null,"透明度")],-1),v=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"hcolor")]),n("td",null,"选中时的颜色")],-1),f=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"size")]),n("td",null,"对象的大小,默认值为1")],-1),_=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"length")]),n("td",null,[a("对象的长度,常用于 "),n("a",{href:"#box"},"box(立方体)")])],-1),j=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"width")]),n("td",null,[a("对象的宽度,常用于 "),n("a",{href:"#box"},"box(立方体)")])],-1),w=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"height")]),n("td",null,[a("对象的高度,常用于 "),n("a",{href:"#box"},"box(立方体)")])],-1),z=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"radius")]),n("td",null,"对象圆角大小")],-1),q=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"segments")]),n("td",null,[a("份数,通常用于设置 "),n("a",{href:"#sphere"},"sphere(球体)"),a(" 绘制的精度")])],-1),E=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"selectable")]),n("td",null,"是否可被选中")],-1),A=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"name")]),n("td",null,"对象名称")],-1),R=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"text")]),n("td",null,"对象文本值")],-1),B=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"font")]),n("td",null,"文本字体")],-1),C=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"vertices")]),n("td",null,"构成对应对象的点集合")],-1),M=t(`

支持添加到场景中的类型如下

对象类型

对象类型列表

注释

为了简洁起见,下方示例的对象可选属性中只展示对应对象的关键属性。其他通用的属性可以参考 对象可选属性列表 自行添加。

label

label 是文本标签。可以在 text 属性中设置label的文本。

local obj = scene.addobj('label', {text = "Hello World!"})
 

points

points 是点集合。可以只创建单个点,也可以创建多个点。每个点都有三个维度的坐标以确定其在三维空间中的位置。点的个数通过 vertices 属性确定。

下面是一个创建 points 点集对象的示例

-- 在坐标为(5,5,5)的位置创建一个点
 scene.addobj("points", {vertices = {5,5,5}, size = 5})
diff --git a/assets/3d-objects.html-jGytICR_.js b/assets/3d-objects.html-jGytICR_.js
new file mode 100644
index 00000000..39539b16
--- /dev/null
+++ b/assets/3d-objects.html-jGytICR_.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-0be8554c","path":"/notes/3d-objects.html","title":"3D 对象","lang":"zh-CN","frontmatter":{"description":"本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。 添加对象 向场景中添加对象,函数形式如下 对象可选属性列表 添加到场景中的对象通常支持设置以下属性中的某些属性 对象属性含义 :---:---- color对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 (./3d-scene.md#bgcolor-场景背景...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/3d-objects.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3D 对象"}],["meta",{"property":"og:description","content":"本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。 添加对象 向场景中添加对象,函数形式如下 对象可选属性列表 添加到场景中的对象通常支持设置以下属性中的某些属性 对象属性含义 :---:---- color对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 (./3d-scene.md#bgcolor-场景背景..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D 对象\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"添加对象","slug":"添加对象","link":"#添加对象","children":[]},{"level":2,"title":"对象可选属性列表","slug":"对象可选属性列表","link":"#对象可选属性列表","children":[]},{"level":2,"title":"对象类型","slug":"对象类型","link":"#对象类型","children":[{"level":3,"title":"对象类型列表","slug":"对象类型列表","link":"#对象类型列表","children":[]},{"level":3,"title":"label","slug":"label","link":"#label","children":[]},{"level":3,"title":"points","slug":"points","link":"#points","children":[]},{"level":3,"title":"polyline","slug":"polyline","link":"#polyline","children":[]},{"level":3,"title":"box","slug":"box","link":"#box","children":[]},{"level":3,"title":"sphere","slug":"sphere","link":"#sphere","children":[]},{"level":3,"title":"polygon","slug":"polygon","link":"#polygon","children":[]},{"level":3,"title":"外部模型","slug":"外部模型","link":"#外部模型","children":[]},{"level":3,"title":"light","slug":"light","link":"#light","children":[]},{"level":3,"title":"mesh","slug":"mesh","link":"#mesh","children":[]}]},{"level":2,"title":"对象控制函数","slug":"对象控制函数","link":"#对象控制函数","children":[{"level":3,"title":"getpos()","slug":"getpos","link":"#getpos","children":[]},{"level":3,"title":"setpos()","slug":"setpos","link":"#setpos","children":[]},{"level":3,"title":"getrot()","slug":"getrot","link":"#getrot","children":[]},{"level":3,"title":"setrot()","slug":"setrot","link":"#setrot","children":[]},{"level":3,"title":"getscale()","slug":"getscale","link":"#getscale","children":[]},{"level":3,"title":"setscale()","slug":"setscale","link":"#setscale","children":[]},{"level":3,"title":"getchildren()","slug":"getchildren","link":"#getchildren","children":[]},{"level":3,"title":"getchildren()","slug":"getchildren-1","link":"#getchildren-1","children":[]},{"level":3,"title":"getparent()","slug":"getparent","link":"#getparent","children":[]},{"level":3,"title":"setparent()","slug":"setparent","link":"#setparent","children":[]},{"level":3,"title":"delete()","slug":"delete","link":"#delete","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"notes/3d-objects.md","autoDesc":true}');export{e as data};
diff --git a/assets/3d-objects-en.html-7DC5k-lZ.js b/assets/3d-objects.html-l7ht6tpD.js
similarity index 97%
rename from assets/3d-objects-en.html-7DC5k-lZ.js
rename to assets/3d-objects.html-l7ht6tpD.js
index 99b2b493..44376495 100644
--- a/assets/3d-objects-en.html-7DC5k-lZ.js
+++ b/assets/3d-objects.html-l7ht6tpD.js
@@ -1,5 +1,5 @@
-import{_ as c,a as l,b as i,c as r}from"./polygon_sizes-bVJYQmiT.js";import{_ as u,r as s,o as d,c as h,a as n,b as a,d as t,w as k,e}from"./app-DaLjD81q.js";const b={},g=e(`

3D Objects

This section will introduce the objects and their control functions in a 3D scene.

Adding Objects

To add objects to the scene, use the following function:

local obj = scene.addobj([type], {key1 = value1, key2 = value2, ...})
-

Optional Object Properties

Objects added to the scene typically support setting some of the following properties:

`,7),m=n("thead",null,[n("tr",null,[n("th",{style:{"text-align":"center"}},"Object Property"),n("th",null,"Meaning")])],-1),f=n("td",{style:{"text-align":"center"}},[n("code",null,"color")],-1),y=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"opacity")]),n("td",null,"Opacity")],-1),x=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"hcolor")]),n("td",null,"The color when the object is selected")],-1),v=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"size")]),n("td",null,"The size of the object. The default value is 1")],-1),j=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"length")]),n("td",null,[a("The length of the object, commonly used for "),n("a",{href:"#box"},"box")])],-1),_=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"width")]),n("td",null,[a("The width of the object, commonly used for "),n("a",{href:"#box"},"box")])],-1),w=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"height")]),n("td",null,[a("The height of the object, commonly used for "),n("a",{href:"#box"},"box")])],-1),T=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"radius")]),n("td",null,"The size of the object's rounded corners")],-1),z=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"segments")]),n("td",null,[a("The number of segments, usually used to set the precision of the "),n("a",{href:"#sphere"},"sphere"),a(" drawn")])],-1),q=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"selectable")]),n("td",null,"Whether the object can be selected")],-1),O=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"name")]),n("td",null,"The name of the object")],-1),S=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"text")]),n("td",null,"The text value of the object")],-1),E=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"font")]),n("td",null,"The font of the text")],-1),L=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"vertices")]),n("td",null,"The set of points that make up the corresponding object")],-1),B=e(`

The following are the types of objects that can be added to the scene:

Object Types

List of Object Types

For the sake of brevity, the key properties of the optional objects shown in the example below only display the relevant attributes of the object. Other common properties can be added by referring to the Optional Object Properties.

label

label is a text label. The text of the label can be set in the text attribute.

local obj = scene.addobj('label', {text = "Hello World!"})
+import{_ as c,a as l,b as i,c as r}from"./polygon_sizes-bVJYQmiT.js";import{_ as u,r as s,o as d,c as h,a as n,b as a,d as t,w as k,e}from"./app-LOf__QKq.js";const b={},g=e(`

3D Objects

This section will introduce the objects and their control functions in a 3D scene.

Adding Objects

To add objects to the scene, use the following function:

local obj = scene.addobj([type], {key1 = value1, key2 = value2, ...})
+

Optional Object Properties

Objects added to the scene typically support setting some of the following properties:

`,7),m=n("thead",null,[n("tr",null,[n("th",{style:{"text-align":"center"}},"Object Property"),n("th",null,"Meaning")])],-1),f=n("td",{style:{"text-align":"center"}},[n("code",null,"color")],-1),y=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"opacity")]),n("td",null,"Opacity")],-1),x=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"hcolor")]),n("td",null,"The color when the object is selected")],-1),v=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"size")]),n("td",null,"The size of the object. The default value is 1")],-1),j=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"length")]),n("td",null,[a("The length of the object, commonly used for "),n("a",{href:"#box"},"box")])],-1),_=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"width")]),n("td",null,[a("The width of the object, commonly used for "),n("a",{href:"#box"},"box")])],-1),w=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"height")]),n("td",null,[a("The height of the object, commonly used for "),n("a",{href:"#box"},"box")])],-1),T=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"radius")]),n("td",null,"The size of the object's rounded corners")],-1),z=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"segments")]),n("td",null,[a("The number of segments, usually used to set the precision of the "),n("a",{href:"#sphere"},"sphere"),a(" drawn")])],-1),q=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"selectable")]),n("td",null,"Whether the object can be selected")],-1),O=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"name")]),n("td",null,"The name of the object")],-1),S=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"text")]),n("td",null,"The text value of the object")],-1),L=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"font")]),n("td",null,"The font of the text")],-1),B=n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"vertices")]),n("td",null,"The set of points that make up the corresponding object")],-1),D=e(`

The following are the types of objects that can be added to the scene:

Object Types

List of Object Types

For the sake of brevity, the key properties of the optional objects shown in the example below only display the relevant attributes of the object. Other common properties can be added by referring to the Optional Object Properties.

label

label is a text label. The text of the label can be set in the text attribute.

local obj = scene.addobj('label', {text = "Hello World!"})
 

points

points is a collection of points. You can create a single point or multiple points. Each point has three-dimensional coordinates to determine its position in three-dimensional space. The number of points is determined by the vertices attribute.

Here is an example of creating a points object:

-- create a point at position (5,5,5)
 scene.addobj("points", {vertices = {5,5,5}, size = 5})
 
@@ -23,7 +23,7 @@ scene.addobj
 

Optional attributes for sphere objects:

AttributeMeaning
radiusThe radius of the sphere. It can be used to control the size of the sphere.
segmentsThe number of rendered surfaces of the sphere. The higher the value, the more detailed the sphere model will be.

The impact of different segments on the same sphere

The impact of different segments on the same sphere

polygon

polygon is used to create a polygon object, mainly set through the vertices attribute.

local obj = scene.addobj("polygon", {vertices = {-1,-1,0, -1,1,-0, 1,1,0, 1,-1,0}})
 

Because the polygon in this example is a square, it looks no different from the box introduced above. However, when the shape is set to other types of polygons (such as triangles, pentagons, etc.), the meaning of the polygon can be reflected.

AttributeMeaningExplanation
verticesThe vertices of the polygonYou can set the three-dimensional coordinates of each point in turn in the vertices attribute. The third dimension coordinates do not have an impact but play a placeholder role.
sizeVolumeSince the third dimension coordinates do not have an impact, and the area is already determined by the vertices of the polygon, the size attribute controls the volume by controlling the third dimension coordinate values of each point.

The impact of different size on the same polygon volume

The impact of different size on the same polygon volume

External model

Reference external files. However, for MicroCityWeb, only the built-in files on the website can be referenced at present.

For example, in the built-in example, a box-type truck is generated in the view by referencing the internal file:

local obj = scene.addobj('/res/2axle.glb')
 

You can also reference an external model by referencing the URL of the file:

local obj = scene.addobj('https://microcityweb.gitee.io/res/agv.glb')
-
`,48),D={href:"http://3dviewer.net/",target:"_blank",rel:"noopener noreferrer"},I=n("code",null,".glb",-1),M=e(`

Light

Set the direction of the light, and the optional parameter vertices is a three-dimensional vector that represents the direction of the light. Since a strong light source has already been set in the MicroCityWeb scene, this will not be discussed in detail here.

Mesh

A face composed of multiple points, commonly found in referenced external models. Due to its limited application, it will not be introduced here.

Object Control Functions

Assuming the 3D object to be manipulated is obj.

getpos()

Gets the position coordinates (x, y, z) of obj.

local x, y, z = obj:getpos()
+
`,48),E={href:"http://3dviewer.net/",target:"_blank",rel:"noopener noreferrer"},I=n("code",null,".glb",-1),M=e(`

Light

Set the direction of the light, and the optional parameter vertices is a three-dimensional vector that represents the direction of the light. Since a strong light source has already been set in the MicroCityWeb scene, this will not be discussed in detail here.

Mesh

A face composed of multiple points, commonly found in referenced external models. Due to its limited application, it will not be introduced here.

Object Control Functions

Assuming the 3D object to be manipulated is obj.

getpos()

Gets the position coordinates (x, y, z) of obj.

local x, y, z = obj:getpos()
 

setpos()

Sets the position coordinates of obj to (x, y, z).

obj:setpos(x, y, z)
 

getrot()

Gets the rotation angles (rx, ry, rz) of obj in the x, y, and z directions.

local rx, ry, rz = obj:getrot()
 

setrot()

Sets the rotation angles of obj in the x, y, and z directions to (rx, ry, rz).

obj:setrot(rx, ry, rz)
@@ -34,4 +34,4 @@ scene.addobj
 

getparent()

Gets the parent object of obj.

local num = obj:getparent()
 

setparent()

Sets the parent object of obj to obj0.

obj:setparent(obj0)
 

delete()

Delete obj.

obj:delete()
-
`,39);function A(C,G){const o=s("RouterLink"),p=s("ExternalLinkIcon");return d(),h("div",null,[g,n("table",null,[m,n("tbody",null,[n("tr",null,[f,n("td",null,[a("The color of the object. The format of the color can support built-in colors, hexadecimal, and RGB. Same as the "),t(o,{to:"/notes/3d-scene-en.html#bgcolor-background-color-of-the-scene"},{default:k(()=>[a("background color of the scene")]),_:1})])]),y,x,v,j,_,w,T,z,q,O,S,E,L])]),B,n("blockquote",null,[n("p",null,[a("If you have 3D model resources at hand, you can view them in "),n("a",D,[a("3D Viewer"),t(p)]),a(" and export them as "),I,a(" models through this website.")])]),M])}const P=u(b,[["render",A],["__file","3d-objects-en.html.vue"]]);export{P as default}; +
`,39);function A(C,G){const o=s("RouterLink"),p=s("ExternalLinkIcon");return d(),h("div",null,[g,n("table",null,[m,n("tbody",null,[n("tr",null,[f,n("td",null,[a("The color of the object. The format of the color can support built-in colors, hexadecimal, and RGB. Same as the "),t(o,{to:"/en/notes/3d-scene.html#bgcolor-background-color-of-the-scene"},{default:k(()=>[a("background color of the scene")]),_:1})])]),y,x,v,j,_,w,T,z,q,O,S,L,B])]),D,n("blockquote",null,[n("p",null,[a("If you have 3D model resources at hand, you can view them in "),n("a",E,[a("3D Viewer"),t(p)]),a(" and export them as "),I,a(" models through this website.")])]),M])}const P=u(b,[["render",A],["__file","3d-objects.html.vue"]]);export{P as default}; diff --git a/assets/3d-scene-en.html-iUVl-UL0.js b/assets/3d-scene-en.html-iUVl-UL0.js deleted file mode 100644 index 37612e31..00000000 --- a/assets/3d-scene-en.html-iUVl-UL0.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-d47089cc","path":"/notes/3d-scene-en.html","title":"3D Scene","lang":"zh-CN","frontmatter":{"description":"This section introduces 3D scenes and their settings. MicroCityWeb 3D Scene Coordinate System The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate sy...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene-en.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3D Scene"}],["meta",{"property":"og:description","content":"This section introduces 3D scenes and their settings. MicroCityWeb 3D Scene Coordinate System The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate sy..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-05-21T06:17:26.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3D Scene"}],["meta",{"property":"article:modified_time","content":"2023-05-21T06:17:26.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D Scene\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-05-21T06:17:26.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCityWeb 3D Scene Coordinate System","slug":"microcityweb-3d-scene-coordinate-system","link":"#microcityweb-3d-scene-coordinate-system","children":[]},{"level":2,"title":"Setting up a Scene","slug":"setting-up-a-scene","link":"#setting-up-a-scene","children":[]},{"level":2,"title":"Optional Parameters of a Scene","slug":"optional-parameters-of-a-scene","link":"#optional-parameters-of-a-scene","children":[{"level":3,"title":"Parameter List","slug":"parameter-list","link":"#parameter-list","children":[]},{"level":3,"title":"grid: Background grid of the scene","slug":"grid-background-grid-of-the-scene","link":"#grid-background-grid-of-the-scene","children":[]},{"level":3,"title":"bgcolor: Background color of the scene","slug":"bgcolor-background-color-of-the-scene","link":"#bgcolor-background-color-of-the-scene","children":[]},{"level":3,"title":"camtype: Camera angle of view","slug":"camtype-camera-angle-of-view","link":"#camtype-camera-angle-of-view","children":[]},{"level":3,"title":"clear: Whether to clear the scene","slug":"clear-whether-to-clear-the-scene","link":"#clear-whether-to-clear-the-scene","children":[]},{"level":3,"title":"rotspeed & transpeed","slug":"rotspeed-transpeed","link":"#rotspeed-transpeed","children":[]}]},{"level":2,"title":"Others","slug":"others","link":"#others","children":[{"level":3,"title":"Regarding high-frequency setting scenarios","slug":"regarding-high-frequency-setting-scenarios","link":"#regarding-high-frequency-setting-scenarios","children":[]}]}],"git":{"updatedTime":1684649846000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"notes/3d-scene-en.md","autoDesc":true}');export{e as data}; diff --git a/assets/3d-scene.html-QeNNxNdQ.js b/assets/3d-scene.html-QeNNxNdQ.js new file mode 100644 index 00000000..834acd8e --- /dev/null +++ b/assets/3d-scene.html-QeNNxNdQ.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-41e82e22","path":"/notes/3d-scene.html","title":"3D 场景","lang":"zh-CN","frontmatter":{"description":"本节将介绍 MicroCity Web 中的三维场景及其设置。 MicroCityWeb三维场景坐标系 MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。 MicroCityWeb中的坐标系 MicroCity Web中的坐标系 手动绘制上图坐标轴的代码 设置场景 设置场景需要用到 setenv 函数,具体用法如...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/3d-scene.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3D 场景"}],["meta",{"property":"og:description","content":"本节将介绍 MicroCity Web 中的三维场景及其设置。 MicroCityWeb三维场景坐标系 MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。 MicroCityWeb中的坐标系 MicroCity Web中的坐标系 手动绘制上图坐标轴的代码 设置场景 设置场景需要用到 setenv 函数,具体用法如..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D 场景\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCityWeb三维场景坐标系","slug":"microcityweb三维场景坐标系","link":"#microcityweb三维场景坐标系","children":[]},{"level":2,"title":"设置场景","slug":"设置场景","link":"#设置场景","children":[]},{"level":2,"title":"场景可选参数","slug":"场景可选参数","link":"#场景可选参数","children":[{"level":3,"title":"参数列表","slug":"参数列表","link":"#参数列表","children":[]},{"level":3,"title":"grid:场景的背景网格","slug":"grid-场景的背景网格","link":"#grid-场景的背景网格","children":[]},{"level":3,"title":"bgcolor:场景背景颜色","slug":"bgcolor-场景背景颜色","link":"#bgcolor-场景背景颜色","children":[]},{"level":3,"title":"camtype:摄像机视角","slug":"camtype-摄像机视角","link":"#camtype-摄像机视角","children":[]},{"level":3,"title":"clear:是否清除场景","slug":"clear-是否清除场景","link":"#clear-是否清除场景","children":[]},{"level":3,"title":"rotspeed & transpeed","slug":"rotspeed-transpeed","link":"#rotspeed-transpeed","children":[]}]},{"level":2,"title":"其他","slug":"其他","link":"#其他","children":[{"level":3,"title":"有关高频率设置场景","slug":"有关高频率设置场景","link":"#有关高频率设置场景","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"notes/3d-scene.md","autoDesc":true}');export{e as data}; diff --git a/assets/3d-scene.html-_tzv6BUx.js b/assets/3d-scene.html-_tzv6BUx.js deleted file mode 100644 index fb8daee8..00000000 --- a/assets/3d-scene.html-_tzv6BUx.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-41e82e22","path":"/notes/3d-scene.html","title":"3D 场景","lang":"zh-CN","frontmatter":{"description":"本节将介绍 MicroCity Web 中的三维场景及其设置。 MicroCityWeb三维场景坐标系 MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。 MicroCityWeb中的坐标系 MicroCity Web中的坐标系 手动绘制上图坐标轴的代码 设置场景 设置场景需要用到 setenv 函数,具体用法如...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"3D 场景"}],["meta",{"property":"og:description","content":"本节将介绍 MicroCity Web 中的三维场景及其设置。 MicroCityWeb三维场景坐标系 MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。 MicroCityWeb中的坐标系 MicroCity Web中的坐标系 手动绘制上图坐标轴的代码 设置场景 设置场景需要用到 setenv 函数,具体用法如..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"3D 场景"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D 场景\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCityWeb三维场景坐标系","slug":"microcityweb三维场景坐标系","link":"#microcityweb三维场景坐标系","children":[]},{"level":2,"title":"设置场景","slug":"设置场景","link":"#设置场景","children":[]},{"level":2,"title":"场景可选参数","slug":"场景可选参数","link":"#场景可选参数","children":[{"level":3,"title":"参数列表","slug":"参数列表","link":"#参数列表","children":[]},{"level":3,"title":"grid:场景的背景网格","slug":"grid-场景的背景网格","link":"#grid-场景的背景网格","children":[]},{"level":3,"title":"bgcolor:场景背景颜色","slug":"bgcolor-场景背景颜色","link":"#bgcolor-场景背景颜色","children":[]},{"level":3,"title":"camtype:摄像机视角","slug":"camtype-摄像机视角","link":"#camtype-摄像机视角","children":[]},{"level":3,"title":"clear:是否清除场景","slug":"clear-是否清除场景","link":"#clear-是否清除场景","children":[]},{"level":3,"title":"rotspeed & transpeed","slug":"rotspeed-transpeed","link":"#rotspeed-transpeed","children":[]}]},{"level":2,"title":"其他","slug":"其他","link":"#其他","children":[{"level":3,"title":"有关高频率设置场景","slug":"有关高频率设置场景","link":"#有关高频率设置场景","children":[]}]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/3d-scene.md","autoDesc":true}');export{e as data}; diff --git a/assets/3d-scene.html-A33RmZzw.js b/assets/3d-scene.html-iJwBMXhE.js similarity index 99% rename from assets/3d-scene.html-A33RmZzw.js rename to assets/3d-scene.html-iJwBMXhE.js index 38a7e9d2..6b98c523 100644 --- a/assets/3d-scene.html-A33RmZzw.js +++ b/assets/3d-scene.html-iJwBMXhE.js @@ -1,4 +1,4 @@ -import{_ as n}from"./coordinate-R7ZKfirG.js";import{_ as s,o as a,c as t,e}from"./app-DaLjD81q.js";const p={},o=e('

3D 场景

本节将介绍 MicroCity Web 中的三维场景及其设置。

MicroCityWeb三维场景坐标系

MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。

MicroCityWeb中的坐标系 MicroCity Web中的坐标系

手动绘制上图坐标轴的代码

scene.setenv({grid="plane"})
+import{_ as n}from"./coordinate-R7ZKfirG.js";import{_ as s,o as a,c as t,e}from"./app-LOf__QKq.js";const p={},o=e('

3D 场景

本节将介绍 MicroCity Web 中的三维场景及其设置。

MicroCityWeb三维场景坐标系

MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。

MicroCityWeb中的坐标系 MicroCity Web中的坐标系

手动绘制上图坐标轴的代码

scene.setenv({grid="plane"})
 
 -- x
 scene.addobj("polyline", {vertices = {0,0,0, 10,0,0}, color = "blue"})
diff --git a/assets/3d-scene-en.html-M1ONxEpk.js b/assets/3d-scene.html-pmrdLLCG.js
similarity index 98%
rename from assets/3d-scene-en.html-M1ONxEpk.js
rename to assets/3d-scene.html-pmrdLLCG.js
index da389272..03cf65a0 100644
--- a/assets/3d-scene-en.html-M1ONxEpk.js
+++ b/assets/3d-scene.html-pmrdLLCG.js
@@ -1,6 +1,6 @@
-import{_ as e}from"./coordinate-R7ZKfirG.js";import{_ as a,o as t,c as n,e as s}from"./app-DaLjD81q.js";const o={},c=s('

3D Scene

This section introduces 3D scenes and their settings.

MicroCityWeb 3D Scene Coordinate System

The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate system, and the specific direction of each coordinate axis is shown in the following figure.

Coordinate system in MicroCityWeb

Coordinate system in MicroCityWeb

Note that the three-dimensional coordinate axes x, y, and z here are manually drawn to show the coordinate system in MicroCityWeb and do not directly exist in the three-dimensional scene.

Setting up a Scene

Setting up a scene requires the use of the setenv function, with the specific usage as follows:

local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true})
+import{_ as e}from"./coordinate-R7ZKfirG.js";import{_ as a,o as t,c as n,e as s}from"./app-LOf__QKq.js";const o={},c=s('

3D Scene

This section introduces 3D scenes and their settings.

MicroCityWeb 3D Scene Coordinate System

The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate system, and the specific direction of each coordinate axis is shown in the following figure.

Coordinate system in MicroCityWeb

Coordinate system in MicroCityWeb

Note that the three-dimensional coordinate axes x, y, and z here are manually drawn to show the coordinate system in MicroCityWeb and do not directly exist in the three-dimensional scene.

Setting up a Scene

Setting up a scene requires the use of the setenv function, with the specific usage as follows:

local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true})
 

It can be simplified as follows:

local s = scene.setenv({key1 = value1, key2 = value2, ...})
 

The variable s holds the returned environment object. The optional parameters of the function will be described in detail below.

Optional Parameters of a Scene

Parameter List

grid: Background grid of the scene

Optional values

ValueMeaning
"none"default, no grid
"plane"flat grid
"sphere"spherical grid

bgcolor: Background color of the scene

Optional value types:

Value TypeExample
Built-in colors"black", "white", "gray", etc.
Hexadecimal colors"#ffffff", "#fff", "#000000", "#000", etc.
Colors represented by RGB"rgb(255, 255, 255)", "rgb(0, 0, 0)", etc.

Example:

scene.setenv({bgcolor='gray'}) -- Sets the background color to the built-in color "gray"
 scene.setenv({bgcolor='#eee'}) -- Sets the background color to the hexadecimal color "#eee"
 scene.setenv({bgcolor='rgb(255, 255, 255)'}) -- Sets the background color to white
-

camtype: Camera angle of view

Optional values:

ValueMeaning
"ortho"Orthographic. Equivalent to a projection onto the x and y plane. User's view is in two-dimensional space.
"persp"Perspective (default). User's view is in three-dimensional space.

clear: Whether to clear the scene

When the value is set to true, the scene is cleared.

The setenv function does not clear the original scene by default, unless the value of the clear parameter is manually set to true.

rotspeed & transpeed

ValueMeaning
rotspeedSets the speed of rotating a 3D object with the mouse.
transpeedSets the speed of translating a 3D object with the mouse.

These two parameters usually do not need to be set specially, and the default values can be used.

Others

Regarding high-frequency setting scenarios

2023/03/21: It has been found that setting the scene too frequently can cause excessive memory usage and browser crashes. Therefore, it is recommended to avoid calling the scene.setenv() function in a loop as much as possible.

If it is necessary to do so, make sure that the frequency of calls is relatively low. This allows the browser to have enough time for garbage collection, otherwise it may cause the browser to crash.

`,37),r=[c];function d(i,p){return t(),n("div",null,r)}const h=a(o,[["render",d],["__file","3d-scene-en.html.vue"]]);export{h as default}; +

camtype: Camera angle of view

Optional values:

ValueMeaning
"ortho"Orthographic. Equivalent to a projection onto the x and y plane. User's view is in two-dimensional space.
"persp"Perspective (default). User's view is in three-dimensional space.

clear: Whether to clear the scene

When the value is set to true, the scene is cleared.

The setenv function does not clear the original scene by default, unless the value of the clear parameter is manually set to true.

rotspeed & transpeed

ValueMeaning
rotspeedSets the speed of rotating a 3D object with the mouse.
transpeedSets the speed of translating a 3D object with the mouse.

These two parameters usually do not need to be set specially, and the default values can be used.

Others

Regarding high-frequency setting scenarios

2023/03/21: It has been found that setting the scene too frequently can cause excessive memory usage and browser crashes. Therefore, it is recommended to avoid calling the scene.setenv() function in a loop as much as possible.

If it is necessary to do so, make sure that the frequency of calls is relatively low. This allows the browser to have enough time for garbage collection, otherwise it may cause the browser to crash.

`,37),r=[c];function d(i,p){return t(),n("div",null,r)}const h=a(o,[["render",d],["__file","3d-scene.html.vue"]]);export{h as default}; diff --git a/assets/3d-scene.html-smFwVKZl.js b/assets/3d-scene.html-smFwVKZl.js new file mode 100644 index 00000000..2e1bac49 --- /dev/null +++ b/assets/3d-scene.html-smFwVKZl.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-543cd98e","path":"/en/notes/3d-scene.html","title":"3D Scene","lang":"en-US","frontmatter":{"description":"This section introduces 3D scenes and their settings. MicroCityWeb 3D Scene Coordinate System The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate sy...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/3d-scene.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"3D Scene"}],["meta",{"property":"og:description","content":"This section introduces 3D scenes and their settings. MicroCityWeb 3D Scene Coordinate System The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate sy..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3D Scene\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCityWeb 3D Scene Coordinate System","slug":"microcityweb-3d-scene-coordinate-system","link":"#microcityweb-3d-scene-coordinate-system","children":[]},{"level":2,"title":"Setting up a Scene","slug":"setting-up-a-scene","link":"#setting-up-a-scene","children":[]},{"level":2,"title":"Optional Parameters of a Scene","slug":"optional-parameters-of-a-scene","link":"#optional-parameters-of-a-scene","children":[{"level":3,"title":"Parameter List","slug":"parameter-list","link":"#parameter-list","children":[]},{"level":3,"title":"grid: Background grid of the scene","slug":"grid-background-grid-of-the-scene","link":"#grid-background-grid-of-the-scene","children":[]},{"level":3,"title":"bgcolor: Background color of the scene","slug":"bgcolor-background-color-of-the-scene","link":"#bgcolor-background-color-of-the-scene","children":[]},{"level":3,"title":"camtype: Camera angle of view","slug":"camtype-camera-angle-of-view","link":"#camtype-camera-angle-of-view","children":[]},{"level":3,"title":"clear: Whether to clear the scene","slug":"clear-whether-to-clear-the-scene","link":"#clear-whether-to-clear-the-scene","children":[]},{"level":3,"title":"rotspeed & transpeed","slug":"rotspeed-transpeed","link":"#rotspeed-transpeed","children":[]}]},{"level":2,"title":"Others","slug":"others","link":"#others","children":[{"level":3,"title":"Regarding high-frequency setting scenarios","slug":"regarding-high-frequency-setting-scenarios","link":"#regarding-high-frequency-setting-scenarios","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/3d-scene.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.1_si_overview.html-3JNy66LR.js b/assets/4.1_si_overview.html-3JNy66LR.js new file mode 100644 index 00000000..24b42a84 --- /dev/null +++ b/assets/4.1_si_overview.html-3JNy66LR.js @@ -0,0 +1,2 @@ +import{_ as r}from"./icon_script_editor-ibm_2NsU.js";import{_ as c}from"./script_editor-a48-sxc_.js";import{_ as l}from"./icon_microcity-Je85-7MO.js";import{_ as u,r as s,o as m,c as h,a as t,b as e,d as n,w as i,e as d}from"./app-LOf__QKq.js";const p={},_=t("h1",{id:"_4-1-si-overview",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_4-1-si-overview","aria-hidden":"true"},"#"),e(" 4.1 SI Overview")],-1),g=t("strong",null,"Modules",-1),b=t("strong",null,"MicroCity Script",-1),f=t("img",{src:r,alt:"icon"},null,-1),w=t("strong",null,"ScriptEditor",-1),k=d('

The Script Editor

scritp_editor

Coding and Debugging MicroCity Scripts

',3),v=t("strong",null,"ScriptEditor",-1),y={href:"https://studio.zerobrane.com/",target:"_blank",rel:"noopener noreferrer"},x=t("img",{src:r,alt:"icon"},null,-1),S=t("strong",null,"Script Editor",-1),T=t("strong",null,"module",-1),C=t("img",{src:l,alt:"icon"},null,-1),M=t("strong",null,"MicroCity",-1),q=t("strong",null,"Debug",-1),E=t("strong",null,"Code View",-1),N=t("strong",null,"ScriptEditor",-1),L=t("strong",null,"Debug Buttons",-1),j=t("h2",{id:"the-lua-language-and-embedded-functions",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#the-lua-language-and-embedded-functions","aria-hidden":"true"},"#"),e(" The Lua Language and Embedded Functions")],-1),V={href:"https://www.lua.org/manual/5.1/",target:"_blank",rel:"noopener noreferrer"},B=d(`

Conventions in this reference:
There are four major data types in Lua can be passed though embedded functions as parameters, namely Number, Boolean, String and Object. The type Object includes builtin Lua objects, such as Table, Function adn Thread..., as well as MicroCity objects, such as Shapes, Grid, Table and Scene.... To clarify the parameter type in embedded functions, we use capitalization, quotation mark and semantic information to avoid ambiguities in function descriptions. A lowercase word of a paramter means a Number. Sometimes, to present an integer parameter, a letter 'i' followed by a word is used, like iField. Starting with the letter 'b' and followed by a word means a Boolean, like bShow. A quoted word means a String. A capitalized word means an Object or a keyword. Following is an example of a embedded function description.

AddParameter (Module, ParentNode, "Value",  "id" [, default = 0])
+

In this case, the Module parameter should be a Module object. The ParentNode parameter should be a Node object, but it act as a parent Node. The "Value" parameter is a string, but it represent the builtin type Value in MicroCity, so this string can not be changed. The "id" parameter should be a user specified string. The default parameter is a number. The contents in a pair of '[' and ']' are optional. The character '|' among parameters means "or".

Encoding formats:
MicroCity uses ANSI encoding format to read and write data, such as shp, txt, csv and dbf. ScriptEditor and the embedded funtions use UTF-8 encoding format to read and write data, such as txt or csv.

`,4);function O(F,A){const a=s("RouterLink"),o=s("ExternalLinkIcon");return m(),h("div",null,[_,t("p",null,[e("MicroCity uses "),g,e(" (see "),n(a,{to:"/en/docs/3.7_modules.html"},{default:i(()=>[e("3.7")]),_:1}),e(") to extend its functionalities. One type of the modules is "),b,e(" (*.mcs) which can be edited and debugged in the "),f,w,e(".")]),k,t("p",null,[v,e(" is based on "),t("a",y,[e("ZeroBrane"),n(o)]),e(". One can find detailed information there. For debugging, you should keep "),x,S,e(" being opened. Then right click the "),T,e(" from "),C,M,e(" and choose "),q,e(" item in the context menu (see "),n(a,{to:"/en/docs/3.7_modules.html#loading-closing-and-executing-modules"},{default:i(()=>[e("3.7")]),_:1}),e("). The execution can be indicated in the "),E,e(" of "),N,e(". You can control the execution and watch variables with "),L,e(".")]),j,t("p",null,[e("MicroCity uses "),t("a",V,[e("Lua 5.1"),n(o)]),e(" as its script language. One can find the reference manual there. MicroCity embeds many useful funtions in Lua, which can not only control user interfaces, manipulate data, but also can solve mathematical models and sun simulations. You should read following chapters for more information.")]),B])}const R=u(p,[["render",O],["__file","4.1_si_overview.html.vue"]]);export{R as default}; diff --git a/assets/4.1_si_overview.html-aQjVZ38p.js b/assets/4.1_si_overview.html-aQjVZ38p.js new file mode 100644 index 00000000..8ba0549e --- /dev/null +++ b/assets/4.1_si_overview.html-aQjVZ38p.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6a627406","path":"/en/docs/4.1_si_overview.html","title":"4.1 SI Overview","lang":"en-US","frontmatter":{"prev":"./3.7_modules.md","next":"./4.2_ui_control.md","description":"MicroCity uses Modules (see 3.7 (3.7modules.md)) to extend its functionalities. One type of the modules is **MicroCity Script** (\\\\*.mcs) which can be edited and debugged in the ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.1_si_overview.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.1_si_overview.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.1 SI Overview"}],["meta",{"property":"og:description","content":"MicroCity uses Modules (see 3.7 (3.7modules.md)) to extend its functionalities. One type of the modules is **MicroCity Script** (\\\\*.mcs) which can be edited and debugged in the ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.1 SI Overview\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"The Script Editor","slug":"the-script-editor","link":"#the-script-editor","children":[]},{"level":2,"title":"Coding and Debugging MicroCity Scripts","slug":"coding-and-debugging-microcity-scripts","link":"#coding-and-debugging-microcity-scripts","children":[]},{"level":2,"title":"The Lua Language and Embedded Functions","slug":"the-lua-language-and-embedded-functions","link":"#the-lua-language-and-embedded-functions","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.1_si_overview.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.1_si_overview.html-iNqEh7u3.js b/assets/4.1_si_overview.html-iNqEh7u3.js deleted file mode 100644 index ce57ce90..00000000 --- a/assets/4.1_si_overview.html-iNqEh7u3.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as r}from"./icon_script_editor-ibm_2NsU.js";import{_ as c}from"./icon_microcity-Je85-7MO.js";import{_ as l,r as s,o as u,c as m,a as t,b as e,d as n,w as i,e as d}from"./app-DaLjD81q.js";const h="/MicroCityNotes/assets/script_editor-51w4xjN9.png",p={},_=t("h1",{id:"_4-1-脚本概览",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_4-1-脚本概览","aria-hidden":"true"},"#"),e(" 4.1 脚本概览")],-1),g=t("strong",null,"Modules",-1),b=t("strong",null,"MicroCity Script",-1),f=t("img",{src:r,alt:"icon"},null,-1),w=t("strong",null,"ScriptEditor",-1),k=d('

The Script Editor

scritp_editor

Coding and Debugging MicroCity Scripts

',3),y=t("strong",null,"ScriptEditor",-1),x={href:"https://studio.zerobrane.com/",target:"_blank",rel:"noopener noreferrer"},v=t("img",{src:r,alt:"icon"},null,-1),T=t("strong",null,"Script Editor",-1),S=t("strong",null,"module",-1),C=t("img",{src:c,alt:"icon"},null,-1),M=t("strong",null,"MicroCity",-1),N=t("strong",null,"Debug",-1),q=t("strong",null,"Code View",-1),E=t("strong",null,"ScriptEditor",-1),L=t("strong",null,"Debug Buttons",-1),j=t("h2",{id:"the-lua-language-and-embedded-functions",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#the-lua-language-and-embedded-functions","aria-hidden":"true"},"#"),e(" The Lua Language and Embedded Functions")],-1),V={href:"https://www.lua.org/manual/5.1/",target:"_blank",rel:"noopener noreferrer"},B=d(`

Conventions in this reference:
There are four major data types in Lua can be passed though embedded functions as parameters, namely Number, Boolean, String and Object. The type Object includes builtin Lua objects, such as Table, Function adn Thread..., as well as MicroCity objects, such as Shapes, Grid, Table and Scene.... To clarify the parameter type in embedded functions, we use capitalization, quotation mark and semantic information to avoid ambiguities in function descriptions. A lowercase word of a paramter means a Number. Sometimes, to present an integer parameter, a letter 'i' followed by a word is used, like iField. Starting with the letter 'b' and followed by a word means a Boolean, like bShow. A quoted word means a String. A capitalized word means an Object or a keyword. Following is an example of a embedded function description.

AddParameter (Module, ParentNode, "Value",  "id" [, default = 0])
-

In this case, the Module parameter should be a Module object. The ParentNode parameter should be a Node object, but it act as a parent Node. The "Value" parameter is a string, but it represent the builtin type Value in MicroCity, so this string can not be changed. The "id" parameter should be a user specified string. The default parameter is a number. The contents in a pair of '[' and ']' are optional. The character '|' among parameters means "or".

Encoding formats:
MicroCity uses ANSI encoding format to read and write data, such as shp, txt, csv and dbf. ScriptEditor and the embedded funtions use UTF-8 encoding format to read and write data, such as txt or csv.

`,4);function F(O,A){const a=s("RouterLink"),o=s("ExternalLinkIcon");return u(),m("div",null,[_,t("p",null,[e("MicroCity uses "),g,e(" (see "),n(a,{to:"/docs/3.7_modules.html"},{default:i(()=>[e("3.7")]),_:1}),e(") to extend its functionalities. One type of the modules is "),b,e(" (*.mcs) which can be edited and debugged in the "),f,w,e(".")]),k,t("p",null,[y,e(" is based on "),t("a",x,[e("ZeroBrane"),n(o)]),e(". One can find detailed information there. For debugging, you should keep "),v,T,e(" being opened. Then right click the "),S,e(" from "),C,M,e(" and choose "),N,e(" item in the context menu (see "),n(a,{to:"/docs/3.7_modules.html#loading-closing-and-executing-modules"},{default:i(()=>[e("3.7")]),_:1}),e("). The execution can be indicated in the "),q,e(" of "),E,e(". You can control the execution and watch variables with "),L,e(".")]),j,t("p",null,[e("MicroCity uses "),t("a",V,[e("Lua 5.1"),n(o)]),e(" as its script language. One can find the reference manual there. MicroCity embeds many useful funtions in Lua, which can not only control user interfaces, manipulate data, but also can solve mathematical models and sun simulations. You should read following chapters for more information.")]),B])}const P=l(p,[["render",F],["__file","4.1_si_overview.html.vue"]]);export{P as default}; diff --git a/assets/4.1_si_overview.html-mGhzJSIB.js b/assets/4.1_si_overview.html-mGhzJSIB.js new file mode 100644 index 00000000..0c77f5e5 --- /dev/null +++ b/assets/4.1_si_overview.html-mGhzJSIB.js @@ -0,0 +1,2 @@ +import{_ as i}from"./icon_script_editor-ibm_2NsU.js";import{_ as l}from"./script_editor-a48-sxc_.js";import{_ as u}from"./icon_microcity-Je85-7MO.js";import{_ as d,r as a,o as m,c as _,a as e,b as t,d as o,w as r,e as c}from"./app-LOf__QKq.js";const p={},h=e("h1",{id:"_4-1-脚本概览",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_4-1-脚本概览","aria-hidden":"true"},"#"),t(" 4.1 脚本概览")],-1),g=e("strong",null,"模块",-1),f=e("strong",null,"MicroCity脚本",-1),b=e("img",{src:i,alt:"icon"},null,-1),k=e("strong",null,"ScriptEditor",-1),v=c('

脚本编辑器

scritp_editor

编码和调试MicroCity脚本

',3),x=e("strong",null,"ScriptEditor",-1),C={href:"https://studio.zerobrane.com/",target:"_blank",rel:"noopener noreferrer"},y=e("img",{src:i,alt:"icon"},null,-1),M=e("strong",null,"Script Editor",-1),q=e("img",{src:u,alt:"icon"},null,-1),S=e("strong",null,"MicroCity",-1),w=e("strong",null,"模块",-1),N=e("strong",null,"调试",-1),L=e("strong",null,"ScriptEditor",-1),E=e("strong",null,"Code View",-1),V=e("strong",null,"调试按钮",-1),T=e("h2",{id:"lua语言和嵌入函数",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#lua语言和嵌入函数","aria-hidden":"true"},"#"),t(" Lua语言和嵌入函数")],-1),B={href:"https://www.lua.org/manual/5.1/",target:"_blank",rel:"noopener noreferrer"},P=c(`

本参考资料中的约定:
Lua中有四种主要的数据类型可以作为参数通过嵌入函数传递,分别是数字(Number)布尔值(Boolean)字符串(String)对象(Object)对象类型包括内置的Lua对象,如表(Table)函数(Function)线程(Thread),以及MicroCity对象,如形状(Shapes)网格(Grid)表(Table)场景(Scene)。为了明确嵌入函数中的参数类型,在函数描述中我们使用大写、引号和语义信息来避免歧义。参数的小写单词表示数字。有时候为了表示整数参数,会在单词后面加上字母'i',如iField。以字母'b'开头并跟随一个单词表示布尔值,如bShow。用引号括起来的单词表示字符串。大写的单词表示对象或关键字。以下是一个嵌入函数描述的示例。

AddParameter(Module, ParentNode, "Value", "id" [, default = 0])
+

在这个例子中,Module参数应该是一个Module对象。ParentNode参数应该是一个Node对象,但它作为一个父节点。"Value"参数是一个字符串,但它代表MicroCity中的内置类型Value,因此这个字符串是不能改变的。*"id"*参数应该是一个用户指定的字符串。default参数是一个数字。方括号中的内容是可选的。参数之间的竖线表示"或"的关系。

编码格式:
MicroCity使用ANSI编码格式读写数据,比如shp、txt、csv和dbf等。ScriptEditor和嵌入函数使用UTF-8编码格式读写数据,比如txt或csv等。

`,4),F={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},I=e("strong",null,"反馈",-1);function A(G,R){const s=a("RouterLink"),n=a("ExternalLinkIcon");return m(),_("div",null,[h,e("p",null,[t("MicroCity使用"),g,t("(详见"),o(s,{to:"/docs/3.7_modules.html"},{default:r(()=>[t("3.7")]),_:1}),t(")来扩展其功能。模块的一种类型是"),f,t("(*.mcs),可以在"),b,k,t("中进行编辑和调试。")]),v,e("p",null,[x,t("基于"),e("a",C,[t("ZeroBrane"),o(n)]),t("。可以在那里找到详细的信息。要进行调试,您应该保持"),y,M,t("打开。然后从"),q,S,t("中右键点击"),w,t(",选择上下文菜单中的"),N,t("项(详见"),o(s,{to:"/docs/3.7_modules.html#loading-closing-and-executing-modules"},{default:r(()=>[t("3.7")]),_:1}),t(")。执行过程可以在"),L,t("的"),E,t("中显示。您可以使用"),V,t("控制执行并查看变量。")]),T,e("p",null,[t("MicroCity使用"),e("a",B,[t("Lua 5.1"),o(n)]),t("作为其脚本语言。可以在那里找到参考手册。MicroCity在Lua中嵌入了许多有用的函数,不仅可以控制用户界面、操作数据,还可以解决数学模型和太阳模拟等问题。请阅读以下章节以获取更多信息。")]),P,e("blockquote",null,[e("p",null,[t("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),e("a",F,[I,o(n)]),t("页面提交反馈。")])])])}const Z=d(p,[["render",A],["__file","4.1_si_overview.html.vue"]]);export{Z as default}; diff --git a/assets/4.1_si_overview.html-niv4qRLq.js b/assets/4.1_si_overview.html-niv4qRLq.js new file mode 100644 index 00000000..e8b24e73 --- /dev/null +++ b/assets/4.1_si_overview.html-niv4qRLq.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-4c59099a","path":"/docs/4.1_si_overview.html","title":"4.1 脚本概览","lang":"zh-CN","frontmatter":{"prev":"./3.7_modules.md","next":"./4.2_ui_control.md","description":"MicroCity使用模块(详见3.7 (3.7modules.md))来扩展其功能。模块的一种类型是**MicroCity脚本**(\\\\*.mcs),可以在!icon (../images/doc/iconscript_editor.png)ScriptEditor中进行编辑和调试。 脚本编辑器 scritp_editor 编码和调试MicroCity...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.1_si_overview.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.1_si_overview.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.1 脚本概览"}],["meta",{"property":"og:description","content":"MicroCity使用模块(详见3.7 (3.7modules.md))来扩展其功能。模块的一种类型是**MicroCity脚本**(\\\\*.mcs),可以在!icon (../images/doc/iconscript_editor.png)ScriptEditor中进行编辑和调试。 脚本编辑器 scritp_editor 编码和调试MicroCity..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.1 脚本概览\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"脚本编辑器","slug":"脚本编辑器","link":"#脚本编辑器","children":[]},{"level":2,"title":"编码和调试MicroCity脚本","slug":"编码和调试microcity脚本","link":"#编码和调试microcity脚本","children":[]},{"level":2,"title":"Lua语言和嵌入函数","slug":"lua语言和嵌入函数","link":"#lua语言和嵌入函数","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.1_si_overview.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.1_si_overview.html-umQYu3pM.js b/assets/4.1_si_overview.html-umQYu3pM.js deleted file mode 100644 index fc5e2373..00000000 --- a/assets/4.1_si_overview.html-umQYu3pM.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-4c59099a","path":"/docs/4.1_si_overview.html","title":"4.1 脚本概览","lang":"zh-CN","frontmatter":{"prev":"./3.7_modules.md","next":"./4.2_ui_control.md","description":"MicroCity uses Modules (see 3.7 (3.7modules.md)) to extend its functionalities. One type of the modules is **MicroCity Script** (\\\\*.mcs) which can be edited and debugged in the ...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.1_si_overview.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.1 脚本概览"}],["meta",{"property":"og:description","content":"MicroCity uses Modules (see 3.7 (3.7modules.md)) to extend its functionalities. One type of the modules is **MicroCity Script** (\\\\*.mcs) which can be edited and debugged in the ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.1 脚本概览"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.1 脚本概览\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"The Script Editor","slug":"the-script-editor","link":"#the-script-editor","children":[]},{"level":2,"title":"Coding and Debugging MicroCity Scripts","slug":"coding-and-debugging-microcity-scripts","link":"#coding-and-debugging-microcity-scripts","children":[]},{"level":2,"title":"The Lua Language and Embedded Functions","slug":"the-lua-language-and-embedded-functions","link":"#the-lua-language-and-embedded-functions","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.1_si_overview.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.2_ui_control.html-P4QU671J.js b/assets/4.2_ui_control.html-P4QU671J.js deleted file mode 100644 index 845b4f2f..00000000 --- a/assets/4.2_ui_control.html-P4QU671J.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-68871b76","path":"/docs/4.2_ui_control.html","title":"4.2 控制用户界面","lang":"zh-CN","frontmatter":{"prev":"./4.1_si_overview.md","next":"./4.3_shapes_and_tables.md","description":"Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be f...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.2_ui_control.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.2 控制用户界面"}],["meta",{"property":"og:description","content":"Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be f..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-11T04:14:01.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.2 控制用户界面"}],["meta",{"property":"article:modified_time","content":"2022-12-11T04:14:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.2 控制用户界面\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-11T04:14:01.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Basic User Interfaces","slug":"basic-user-interfaces","link":"#basic-user-interfaces","children":[]},{"level":2,"title":"Data Objects","slug":"data-objects","link":"#data-objects","children":[]},{"level":2,"title":"Modules and Parameters","slug":"modules-and-parameters","link":"#modules-and-parameters","children":[]}],"git":{"updatedTime":1670732041000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.2_ui_control.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.2_ui_control.html-Zsu36Eou.js b/assets/4.2_ui_control.html-Zsu36Eou.js new file mode 100644 index 00000000..24b060c0 --- /dev/null +++ b/assets/4.2_ui_control.html-Zsu36Eou.js @@ -0,0 +1,30 @@ +import{_ as t}from"./icon_script_editor-ibm_2NsU.js";import{_ as e}from"./shot_parameter_id-roH75mzn.js";import{_ as p,r as o,o as u,c,a as n,b as a,d as l,e as i}from"./app-LOf__QKq.js";const r={},d=i('

4.2 控制用户界面

Microcity Script 可用于控制用户界面上的一些功能,包括模块、数据对象、消息等等。在 iconScriptEditor项目标签的"user_interface"文件夹中可以找到一些示例代码。

基本用户界面

Print ("hello" [,...])
+

消息面板中打印数值。

Note ("hello" [,...])
+

通知用户并暂停执行。

SetProcessText ("processing")
+

MicroCity的左下角设置一个文本。

SetProgress (position, range)
+

设置位于MicroCity右下角的进度条的 position/range 值。

Sleep (milliseconds)
+

暂停执行 milliseconds 毫秒。

GetReady ()
+

MicroCity与Lua引擎共享同一线程。Lua中的计算量较大会阻塞MicroCity界面。在内部使用该函数可以使MicroCity界面响应用户操作。如果用户取消当前执行,则返回false。

GetClickXY ()
+

返回用户在地图视图中点击的 x,y 坐标。

GetDragExtent ()
+

返回用户使用鼠标在地图视图中拖动矩形时的底部左侧和顶部右侧坐标:Lx,By,Rx,Ty。

数据对象

PATH
+

内部全局变量,保存当前工作目录的字符串,例如"c:\\microcity"。

Open (".\\\\shapes.shp" [, ".\\\\grid.sgrd" [, ".\\\\table.dbf" [, ".\\\\scene.m3d" , ...]]])
+

从当前工作目录或打开的数据中打开并返回ShapesTableGridScene对象。

Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel)
+

关闭已打开或创建的ShapesTableGridSceneNetworkRndEngineLPModel对象。

Update (Shapes|Grid|Table [, bShow = true])
+

MicroCity中更新ShapesGridTable对象的当前更改。bShow表示是否创建对象的视图。如果用户取消当前执行,返回false。

CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...])
+

创建一个地图视图,以显示按参数中的顺序分层排列的对象。

模块和参数

AddModule ("Function" [, "name"]) 
+

此函数可以将Lua函数作为模块添加到当前模块库。模块的默认名称是函数的名称。返回一个Module对象。

function AddParameter(Module, ParentNode, "Node", "id")
+function AddParameter(Module, ParentNode, "Value", "id" [, default = 0])
+function AddParameter(Module, ParentNode, "Range", "id" [, low = 0 [, high = 1]])
+function AddParameter(Module, ParentNode, "Check", "id" [, default = 0])
+function AddParameter(Module, ParentNode, "String", "id" [, "string" = "")
+function AddParameter(Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]])
+function AddParameter(Module, ParentNode, "File", "id" [, "c:\\\\default.txt" = ""])
+function AddParameter(Module, ParentNode, "Color", "id" [, "color" = "255 255 255")
+function AddParameter(Module, ParentNode, "Shapes", "id")
+function AddParameter(Module, ParentNode, "Grid", "id")
+function AddParameter(Module, ParentNode, "Scene", "id")
+function AddParameter(Module, ParentNode, "Table", "id")
+function AddParameter(Module, ParentNode, "Field", "id")
+

这些函数可以在模块的设置面板中添加参数。返回相应的值或对象。ParentNode 可以设置为 AddParameter 函数的第一个返回值。如果 "Field" 在第三个位置,则 parent_node 可以设置为 TableShapes 对象,以获取其属性表的头部。

GetParameter(Shapes|Table|Grid|Scene|Module, "id")
+

从对象的设置面板中返回指定的参数。

SetParameter(Shapes|Table|Grid|Scene|Module, "id", Number | "String" | Object)
+

在对象的设置面板中设置指定的参数。如果成功,则返回 true。请注意,选择参数应从1开始。可以在下图中的参数帮助文本中找到参数的 "id"

shot

',40),k={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},m=n("strong",null,"反馈",-1);function g(v,q){const s=o("ExternalLinkIcon");return u(),c("div",null,[d,n("blockquote",null,[n("p",null,[a("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",k,[m,l(s)]),a("页面提交反馈。")])])])}const P=p(r,[["render",g],["__file","4.2_ui_control.html.vue"]]);export{P as default}; diff --git a/assets/4.2_ui_control.html-PXdKdANV.js b/assets/4.2_ui_control.html-it8dN_Kd.js similarity index 92% rename from assets/4.2_ui_control.html-PXdKdANV.js rename to assets/4.2_ui_control.html-it8dN_Kd.js index 4ef65870..bf731fa0 100644 --- a/assets/4.2_ui_control.html-PXdKdANV.js +++ b/assets/4.2_ui_control.html-it8dN_Kd.js @@ -1,4 +1,4 @@ -import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as e,e as t}from"./app-DaLjD81q.js";const o="/MicroCityNotes/assets/shot_parameter_id-ljNzzofT.png",p={},c=t('

4.2 控制用户界面

Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be found in the "user_interface" folder of the Project Tab in iconScriptEditor.

Basic User Interfaces

Print ("hello" [,...])
+import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a}from"./shot_parameter_id-roH75mzn.js";import{_ as s,o as e,c as t,e as o}from"./app-LOf__QKq.js";const p={},c=o('

4.2 UI Control

Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be found in the "user_interface" folder of the Project Tab in iconScriptEditor.

Basic User Interfaces

Print ("hello" [,...])
 

Prints values in the Messages Panel.

Note ("hello" [,...])
 

Notifies users and pauses the execution.

SetProcessText ("processing")
 

Sets a text at the bottom left corner of MicroCity.

SetProgress (position, range)
@@ -27,4 +27,4 @@ import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as e
 AddParameter (Module, ParentNode, "Field",  "id")
 

These functions can add a parameter to a module's settings panel. Returns corresponding values or an object. The ParentNode can be set to the first return of a AddParameter function. If "Field" is set at the third place, the parent_node can be set to a Table or Shapes object to get its attributes table's head.

GetParameter (Shapes|Table|Grid|Scene|Module, "id")
 

Returns the parameter specified by "id" from the object's settings panel.

SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
-

Sets the parameter specified by "id" in the object's settings panel. Returns true if succeed. Note that the choice parameter should start from 1. A parameter's "id" can be found in the parameter's helper text shown as below.

shot

',40),u=[c];function i(l,r){return s(),e("div",null,u)}const m=a(p,[["render",i],["__file","4.2_ui_control.html.vue"]]);export{m as default}; +

Sets the parameter specified by "id" in the object's settings panel. Returns true if succeed. Note that the choice parameter should start from 1. A parameter's "id" can be found in the parameter's helper text shown as below.

shot

',40),u=[c];function i(l,r){return e(),t("div",null,u)}const g=s(p,[["render",i],["__file","4.2_ui_control.html.vue"]]);export{g as default}; diff --git a/assets/4.2_ui_control.html-n4jA58yX.js b/assets/4.2_ui_control.html-n4jA58yX.js new file mode 100644 index 00000000..78a8acb7 --- /dev/null +++ b/assets/4.2_ui_control.html-n4jA58yX.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-da33eb4e","path":"/en/docs/4.2_ui_control.html","title":"4.2 UI Control","lang":"en-US","frontmatter":{"prev":"./4.1_si_overview.md","next":"./4.3_shapes_and_tables.md","description":"Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be f...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.2_ui_control.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.2_ui_control.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.2 UI Control"}],["meta",{"property":"og:description","content":"Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be f..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.2 UI Control\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Basic User Interfaces","slug":"basic-user-interfaces","link":"#basic-user-interfaces","children":[]},{"level":2,"title":"Data Objects","slug":"data-objects","link":"#data-objects","children":[]},{"level":2,"title":"Modules and Parameters","slug":"modules-and-parameters","link":"#modules-and-parameters","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.2_ui_control.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.2_ui_control.html-qgHwWAaN.js b/assets/4.2_ui_control.html-qgHwWAaN.js new file mode 100644 index 00000000..06d3a94e --- /dev/null +++ b/assets/4.2_ui_control.html-qgHwWAaN.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-68871b76","path":"/docs/4.2_ui_control.html","title":"4.2 控制用户界面","lang":"zh-CN","frontmatter":{"prev":"./4.1_si_overview.md","next":"./4.3_shapes_and_tables.md","description":"Microcity Script 可用于控制用户界面上的一些功能,包括模块、数据对象、消息等等。在 !icon (../images/doc/iconscripteditor.png)ScriptEditor 的项目标签的\\"user_interface\\"文件夹中可以找到一些示例代码。 基本用户界面在消息面板中打印数值。通知用户并暂停执行。在MicroC...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.2_ui_control.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.2_ui_control.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.2 控制用户界面"}],["meta",{"property":"og:description","content":"Microcity Script 可用于控制用户界面上的一些功能,包括模块、数据对象、消息等等。在 !icon (../images/doc/iconscripteditor.png)ScriptEditor 的项目标签的\\"user_interface\\"文件夹中可以找到一些示例代码。 基本用户界面在消息面板中打印数值。通知用户并暂停执行。在MicroC..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.2 控制用户界面\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"基本用户界面","slug":"基本用户界面","link":"#基本用户界面","children":[]},{"level":2,"title":"数据对象","slug":"数据对象","link":"#数据对象","children":[]},{"level":2,"title":"模块和参数","slug":"模块和参数","link":"#模块和参数","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"docs/4.2_ui_control.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.3_shapes_and_tables.html-kM2JYXcO.js b/assets/4.3_shapes_and_tables.html-9CbssTxf.js similarity index 93% rename from assets/4.3_shapes_and_tables.html-kM2JYXcO.js rename to assets/4.3_shapes_and_tables.html-9CbssTxf.js index 8334ef8d..1f8b1c44 100644 --- a/assets/4.3_shapes_and_tables.html-kM2JYXcO.js +++ b/assets/4.3_shapes_and_tables.html-9CbssTxf.js @@ -1,4 +1,4 @@ -import{_ as p}from"./icon_script_editor-ibm_2NsU.js";import{_ as o,r as u,o as i,c as l,a as n,b as a,d as e,w as t,e as c}from"./app-DaLjD81q.js";const d={},r=n("h1",{id:"_4-3-矢量图形和表格",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-3-矢量图形和表格","aria-hidden":"true"},"#"),a(" 4.3 矢量图形和表格")],-1),m=n("strong",null,"Shapes",-1),k=n("strong",null,"Tables",-1),v=n("strong",null,"Shapes",-1),h=n("strong",null,"Shapes",-1),g=n("strong",null,"Tables",-1),b=n("strong",null,"Shapes",-1),f=n("strong",null,"Tables",-1),S=n("strong",null,"Project",-1),x=n("img",{src:p,alt:"icon"},null,-1),_=n("strong",null,"ScriptEditor",-1),y=c(`

Tabular Data Manipulation

CreateShapes ("name", "Point|Line|Polygon")
+import{_ as p}from"./icon_script_editor-ibm_2NsU.js";import{_ as o,r as u,o as i,c as l,a as n,b as a,d as e,w as t,e as c}from"./app-LOf__QKq.js";const d={},r=n("h1",{id:"_4-3-shapes-and-tables",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-3-shapes-and-tables","aria-hidden":"true"},"#"),a(" 4.3 Shapes and Tables")],-1),m=n("strong",null,"Shapes",-1),k=n("strong",null,"Tables",-1),v=n("strong",null,"Shapes",-1),h=n("strong",null,"Shapes",-1),g=n("strong",null,"Tables",-1),b=n("strong",null,"Shapes",-1),f=n("strong",null,"Tables",-1),S=n("strong",null,"Project",-1),x=n("img",{src:p,alt:"icon"},null,-1),_=n("strong",null,"ScriptEditor",-1),y=c(`

Tabular Data Manipulation

CreateShapes ("name", "Point|Line|Polygon")
 

Returns a Shapes object.

CreateTable ("Name")
 

Returns a Table object.

GetFieldCount (Shapes|Table)
 

Returns the number of fields in a Shapes or Table

GetField (Shapes|Table, iField)
@@ -37,4 +37,4 @@ import{_ as p}from"./icon_script_editor-ibm_2NsU.js";import{_ as o,r as u,o as i
 

Returns a Shape (Point, Line or Polygon) object of the intersection of two Shapes.

GetValue (Shape, "field_name")
 

Returns the value of specified field of a Shape.

SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...])
 

Sets values in different fiedds for a Shape.

SetCoorSys ("Earth"|"Non-Earth")
-

Sets coordinate system. If using "Earth", distances, lenths and areas are calculated according to the earth ellipsoid coordinate system. By default the "Non-Earth" is used, which is cartesian coordinate system.

`,80);function q(R,T){const s=u("RouterLink");return i(),l("div",null,[r,n("p",null,[a("Users can manipulate "),m,a(" and "),k,a(" with MicroCity Script. For detailed data structure of "),v,a(", you can refer to previous chapter "),e(s,{to:"/docs/2.2_searching_for_countries.html#gis-data-structure"},{default:t(()=>[a("2.2")]),_:1}),a(" and "),e(s,{to:"/docs/3.2_vector_shapes.html"},{default:t(()=>[a("3.2")]),_:1}),a(". Because "),h,a(" can be treated as "),g,a(" with extra field with geographic data, some of embeded functions for tabular data manipulation can be used both in "),b,a(" and "),f,a('. Sample codes for this chapter can be found in the "shapes_samples" folder of the '),S,a(" Tab in "),x,_,a(".")]),y])}const j=o(d,[["render",q],["__file","4.3_shapes_and_tables.html.vue"]]);export{j as default}; +

Sets coordinate system. If using "Earth", distances, lenths and areas are calculated according to the earth ellipsoid coordinate system. By default the "Non-Earth" is used, which is cartesian coordinate system.

`,80);function q(R,T){const s=u("RouterLink");return i(),l("div",null,[r,n("p",null,[a("Users can manipulate "),m,a(" and "),k,a(" with MicroCity Script. For detailed data structure of "),v,a(", you can refer to previous chapter "),e(s,{to:"/en/docs/2.2_searching_for_countries.html#gis-data-structure"},{default:t(()=>[a("2.2")]),_:1}),a(" and "),e(s,{to:"/en/docs/3.2_vector_shapes.html"},{default:t(()=>[a("3.2")]),_:1}),a(". Because "),h,a(" can be treated as "),g,a(" with extra field with geographic data, some of embeded functions for tabular data manipulation can be used both in "),b,a(" and "),f,a('. Sample codes for this chapter can be found in the "shapes_samples" folder of the '),S,a(" Tab in "),x,_,a(".")]),y])}const j=o(d,[["render",q],["__file","4.3_shapes_and_tables.html.vue"]]);export{j as default}; diff --git a/assets/4.3_shapes_and_tables.html-Ix5omLFZ.js b/assets/4.3_shapes_and_tables.html-Ix5omLFZ.js new file mode 100644 index 00000000..3007b16e --- /dev/null +++ b/assets/4.3_shapes_and_tables.html-Ix5omLFZ.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-3c0f83c0","path":"/docs/4.3_shapes_and_tables.html","title":"4.3 矢量图形和表格","lang":"zh-CN","frontmatter":{"prev":"./4.2_ui_control.md","next":"./4.4_grids.md","description":"用户可以使用 MicroCity 脚本操作 形状(Shapes) 和 表格(Tables)。有关形状(Shapes)的详细数据结构,您可以参考上一章节 2.2 (2.2searchingforcountries.md#gis-data-structure) 和 3.2 (3.2vectorshapes.md)。由于**形状(Shapes)**可以被视为...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.3_shapes_and_tables.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.3_shapes_and_tables.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.3 矢量图形和表格"}],["meta",{"property":"og:description","content":"用户可以使用 MicroCity 脚本操作 形状(Shapes) 和 表格(Tables)。有关形状(Shapes)的详细数据结构,您可以参考上一章节 2.2 (2.2searchingforcountries.md#gis-data-structure) 和 3.2 (3.2vectorshapes.md)。由于**形状(Shapes)**可以被视为..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.3 矢量图形和表格\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"表格数据操作","slug":"表格数据操作","link":"#表格数据操作","children":[]},{"level":2,"title":"地理数据操作","slug":"地理数据操作","link":"#地理数据操作","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.3_shapes_and_tables.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.3_shapes_and_tables.html-SxckQf89.js b/assets/4.3_shapes_and_tables.html-SxckQf89.js new file mode 100644 index 00000000..a9d02564 --- /dev/null +++ b/assets/4.3_shapes_and_tables.html-SxckQf89.js @@ -0,0 +1,40 @@ +import{_ as l}from"./icon_script_editor-ibm_2NsU.js";import{_ as o,r as t,o as c,c as i,a,b as n,d as s,w as p,e as d}from"./app-LOf__QKq.js";const r={},m=a("h1",{id:"_4-3-矢量图形和表格",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#_4-3-矢量图形和表格","aria-hidden":"true"},"#"),n(" 4.3 矢量图形和表格")],-1),k=a("strong",null,"形状(Shapes)",-1),v=a("strong",null,"表格(Tables)",-1),g=a("strong",null,"可以被视为带有地理数据的",-1),h=a("strong",null,"和",-1),b=a("strong",null,"中同时使用。本章节的示例代码可以在",-1),S=a("img",{src:l,alt:"icon"},null,-1),x=a("strong",null,"ScriptEditor",-1),_=d(`

表格数据操作

CreateShapes ("name", "Point|Line|Polygon")
+

返回一个 Shapes 对象。

CreateTable ("Name")
+

返回一个 Table 对象。

GetFieldCount (Shapes|Table)
+

返回 ShapesTable 中字段的数量。

GetField (Shapes|Table, iField)
+

输入字段的索引(从 1 开始)并返回字段名和类型("Int"、"Float"、"Double" 或 "String")。

AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...])
+

向 *Table 或 Shapes 添加字段,并按照顺序返回布尔值(truefalse)。

DelField (Shapes|Table, iField)
+

成功删除字段时返回 true

GetRecCount (Shapes|Table)
+

返回 ShapesTable 中的记录总数。

AddRecord (Shapes|Table)
+

ShapesTable 添加一条记录,并返回该记录的索引。

GetValue (Shapes|Table, "field_name", index1 [, index2, ...])
+

从指定字段和 ShapesTable 的索引中检索值。按照索引的顺序返回多个值。

SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...])
+

为指定字段和 ShapesTable 的索引设置值。

地理数据操作

GetSelections (Shapes)
+

Shapes中返回所选的形状对象。

GetShape (Shapes, index1 [, index2, ...])
+

按索引顺序从Shapes中返回Shape对象。

AddShape (Shapes, Shape)
+

Shape对象添加到Shapes中并返回其索引。

AddShape (Shapes [, x1, y1, x2, y2, ...])
+

将定义为点的Shape对象添加到Shapes中。返回Shape对象和索引。

DelShape (Shape|Shapes)
+

删除一个ShapeShapes对象,如果成功则返回true。

AddPoint (Shape, x, y [, iPart = 1])
+

Shape中添加一个点,如果成功则返回true。

InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
+

Shape中插入一个点,如果成功则返回true。

SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
+

设置Shape中的点坐标,如果成功则返回true。

DelPoint (Shape, iPoint [, iPart=1])
+

Shape中删除位置为iPoint的一个点,如果成功则返回true。

DelPart (Shape, iPart)
+

Shape中删除一个部分,如果成功则返回true。

GetPartCount (Shape)
+

返回Shape中部分的数量。

GetPointCount (Shape [, iPart])
+

返回Shape中点的数量。

GetPointXY (Shape [, iPoint [, iPart = 1]])
+

Shape或指定点的坐标中返回所有点的坐标:x1,y1,x2,y2,...。

CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...])
+

Shape对象复制到目标Shapes,并进行相对平移(dx,dy),返回新的Shape对象。

MoveShapeTo (dx, dy, Shape1 [, Shape2, ...])
+

Shape对象平移到其相对位置(dx,dy)。

GetCenterXY (Shapes)
+

返回Shapes的中心坐标(x,y)。

GetCenterXY (Shapes, index1 [, index2, ...])
+

返回在Shapes中由索引指定的Shape对象的中心坐标(x1,y1,x2,y2,...)。

GetCenterXY (Shape1 [, Shape2, ...])
+

返回Shape对象的中心坐标(x1,y1,x2,y2,...)。

GetDistance (x1, y1, x2, y2 [, x3, y3, ...])
+

返回每两个坐标(x,y)对之间的总距离。

GetShapeLen (Shape1 [, Shape2, ...])
+

返回Shape对象的长度。

GetShapeArea (Shape1 [, Shape2, ...])
+

返回Shape对象的面积。

GetShapeType (Shape|Shapes)
+

返回ShapesShape对象的类型("Point","Line"或"Polygon")。

GetExtent (Shapes)
+

返回Shapes的范围坐标(Lx,By,Rx,Ty)。

GetExtent (Shapes, index)
+

返回Shapes中索引为index的Shape的范围坐标(Lx,By,Rx,Ty)。

GetExtent (Shape)
+

返回Shape的范围坐标(Lx,By,Rx,Ty)。

GetIntersection (ShapeA, ShapeB)
+

返回两个Shapes的交集的ShapePointLinePolygon)对象。

GetValue (Shape, "field_name")
+

返回Shape的指定字段的值。

SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...])
+

Shape的不同字段设置值。

SetCoorSys ("Earth"|"Non-Earth")
+

设置坐标系统。如果使用"Earth",距离、长度和面积将根据地球椭球坐标系统计算。默认情况下使用"Non-Earth",即笛卡尔坐标系统。

`,80),f={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},q=a("strong",null,"反馈",-1);function y(P,T){const e=t("RouterLink"),u=t("ExternalLinkIcon");return c(),i("div",null,[m,a("p",null,[n("用户可以使用 MicroCity 脚本操作 "),k,n(" 和 "),v,n("。有关"),a("strong",null,[n("形状(Shapes)"),a("strong",null,[n("的详细数据结构,您可以参考上一章节 "),s(e,{to:"/docs/2.2_searching_for_countries.html#gis-data-structure"},{default:p(()=>[n("2.2")]),_:1}),n(" 和 "),s(e,{to:"/docs/3.2_vector_shapes.html"},{default:p(()=>[n("3.2")]),_:1}),n("。由于")]),n("形状(Shapes)"),g,n("表格(Tables)")]),n(",因此一些用于表格数据操作的嵌入函数可以在**形状(Shapes)"),h,n("表格(Tables)"),b,n('项目(Project)**选项卡的"shapes_samples"文件夹中找到,该文件夹位于 '),S,x,n("。")]),_,a("blockquote",null,[a("p",null,[n("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),a("a",f,[q,s(u)]),n("页面提交反馈。")])])])}const E=o(r,[["render",y],["__file","4.3_shapes_and_tables.html.vue"]]);export{E as default}; diff --git a/assets/4.3_shapes_and_tables.html-TBHhEBxq.js b/assets/4.3_shapes_and_tables.html-TBHhEBxq.js new file mode 100644 index 00000000..833ee93a --- /dev/null +++ b/assets/4.3_shapes_and_tables.html-TBHhEBxq.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-3aeb278c","path":"/en/docs/4.3_shapes_and_tables.html","title":"4.3 Shapes and Tables","lang":"en-US","frontmatter":{"prev":"./4.2_ui_control.md","next":"./4.4_grids.md","description":"Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 (2.2searchingforcountries.md#gis-data-...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.3_shapes_and_tables.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.3_shapes_and_tables.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.3 Shapes and Tables"}],["meta",{"property":"og:description","content":"Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 (2.2searchingforcountries.md#gis-data-..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.3 Shapes and Tables\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Tabular Data Manipulation","slug":"tabular-data-manipulation","link":"#tabular-data-manipulation","children":[]},{"level":2,"title":"Geographic Data Manipulation","slug":"geographic-data-manipulation","link":"#geographic-data-manipulation","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.3_shapes_and_tables.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.3_shapes_and_tables.html-ujzvaZYV.js b/assets/4.3_shapes_and_tables.html-ujzvaZYV.js deleted file mode 100644 index 34d29a8f..00000000 --- a/assets/4.3_shapes_and_tables.html-ujzvaZYV.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-3c0f83c0","path":"/docs/4.3_shapes_and_tables.html","title":"4.3 矢量图形和表格","lang":"zh-CN","frontmatter":{"prev":"./4.2_ui_control.md","next":"./4.4_grids.md","description":"Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 (2.2searchingforcountries.md#gis-data-...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.3_shapes_and_tables.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.3 矢量图形和表格"}],["meta",{"property":"og:description","content":"Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 (2.2searchingforcountries.md#gis-data-..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.3 矢量图形和表格"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.3 矢量图形和表格\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Tabular Data Manipulation","slug":"tabular-data-manipulation","link":"#tabular-data-manipulation","children":[]},{"level":2,"title":"Geographic Data Manipulation","slug":"geographic-data-manipulation","link":"#geographic-data-manipulation","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.3_shapes_and_tables.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.4_grids.html-1OY5s52Z.js b/assets/4.4_grids.html-1OY5s52Z.js new file mode 100644 index 00000000..765dbf8c --- /dev/null +++ b/assets/4.4_grids.html-1OY5s52Z.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-a1c74cd0","path":"/en/docs/4.4_grids.html","title":"4.4 Grids","lang":"en-US","frontmatter":{"prev":"./4.3_shapes_and_tables.md","next":"./4.5_3d_scenes.md","description":"Grids in MicroCity have simple structure (3.3 (3.3rastergrids.md)) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.4_grids.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.4_grids.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.4 Grids"}],["meta",{"property":"og:description","content":"Grids in MicroCity have simple structure (3.3 (3.3rastergrids.md)) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.4 Grids\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Cellular Data Manipulation","slug":"cellular-data-manipulation","link":"#cellular-data-manipulation","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.4_grids.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.4_grids.html-7i5R0Lmo.js b/assets/4.4_grids.html-H6iZCbel.js similarity index 77% rename from assets/4.4_grids.html-7i5R0Lmo.js rename to assets/4.4_grids.html-H6iZCbel.js index c6dc4aa3..28fc4a66 100644 --- a/assets/4.4_grids.html-7i5R0Lmo.js +++ b/assets/4.4_grids.html-H6iZCbel.js @@ -1,4 +1,4 @@ -import{_ as e}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as p,o,c as i,a as n,b as a,d as u,w as c,e as l}from"./app-DaLjD81q.js";const d={},r=n("h1",{id:"_4-4-栅格图形",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-4-栅格图形","aria-hidden":"true"},"#"),a(" 4.4 栅格图形")],-1),k=n("strong",null,"Grids",-1),m=n("strong",null,"Project",-1),v=n("img",{src:e,alt:"icon"},null,-1),g=n("strong",null,"ScriptEditor",-1),h=l(`

Cellular Data Manipulation

CreateGrid ("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]])
+import{_ as e}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as p,o,c as i,a as n,b as a,d as u,w as c,e as l}from"./app-LOf__QKq.js";const d={},r=n("h1",{id:"_4-4-grids",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-4-grids","aria-hidden":"true"},"#"),a(" 4.4 Grids")],-1),k=n("strong",null,"Grids",-1),m=n("strong",null,"Project",-1),v=n("img",{src:e,alt:"icon"},null,-1),g=n("strong",null,"ScriptEditor",-1),h=l(`

Cellular Data Manipulation

CreateGrid ("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]])
 

Returns a Grid object.

GetCellSize (Grid)
 

Returns the Cellsize value of a Grid.

GetGridMaxXY (Grid)
 

Returns XMax, YMax of a Grid.

ConvertToGridXY (Grid, x1, y1 [, x2, y2, ...])
@@ -11,4 +11,4 @@ import{_ as e}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as p,o,c as
 

Returns the real coordinates of cells' centers: x1, y1, x2, y2, ... .

GetExtent (Grid)
 

Returns the leftbottom and righttop corner of a Grid's extent: Lx, By, Rx, Ty.

GetExtent (Grid, X, Y)
 

Returns the leftbottom and righttop corner of a cell's extent: Lx, By, Rx, Ty.

GetFractalDim (Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0])
-

Calculates fractal dimension of the specified area in a Grid. Returns dimension, RSQ of linear regression, and the number of boxes in every fold.

`,27);function b(f,x){const s=p("RouterLink");return o(),i("div",null,[r,n("p",null,[k,a(" in MicroCity have simple structure ("),u(s,{to:"/docs/3.3_raster_grids.html"},{default:c(()=>[a("3.3")]),_:1}),a(') but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be found in the "grid_samples" folder of the '),m,a(" Tab in "),v,g,a(".")]),h])}const R=t(d,[["render",b],["__file","4.4_grids.html.vue"]]);export{R as default}; +

Calculates fractal dimension of the specified area in a Grid. Returns dimension, RSQ of linear regression, and the number of boxes in every fold.

`,27);function b(f,x){const s=p("RouterLink");return o(),i("div",null,[r,n("p",null,[k,a(" in MicroCity have simple structure ("),u(s,{to:"/en/docs/3.3_raster_grids.html"},{default:c(()=>[a("3.3")]),_:1}),a(') but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be found in the "grid_samples" folder of the '),m,a(" Tab in "),v,g,a(".")]),h])}const R=t(d,[["render",b],["__file","4.4_grids.html.vue"]]);export{R as default}; diff --git a/assets/4.4_grids.html-JfxVQVat.js b/assets/4.4_grids.html-JfxVQVat.js new file mode 100644 index 00000000..b4c0589f --- /dev/null +++ b/assets/4.4_grids.html-JfxVQVat.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-c670a3a8","path":"/docs/4.4_grids.html","title":"4.4 栅格图形","lang":"zh-CN","frontmatter":{"prev":"./4.3_shapes_and_tables.md","next":"./4.5_3d_scenes.md","description":"在MicroCity中,栅格图形具有简单的结构(3.3 (3.3rastergrids.md)),但是如果在其上应用算法,可以高效利用时间和空间。本章的示例代码可以在项目选项卡的\\"gridsamples\\"文件夹中找到,该选项卡位于!icon (../images/doc/iconscript_editor.png)ScriptEditor中。 栅格数据...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.4_grids.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.4_grids.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.4 栅格图形"}],["meta",{"property":"og:description","content":"在MicroCity中,栅格图形具有简单的结构(3.3 (3.3rastergrids.md)),但是如果在其上应用算法,可以高效利用时间和空间。本章的示例代码可以在项目选项卡的\\"gridsamples\\"文件夹中找到,该选项卡位于!icon (../images/doc/iconscript_editor.png)ScriptEditor中。 栅格数据..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.4 栅格图形\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"栅格数据操作","slug":"栅格数据操作","link":"#栅格数据操作","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.4_grids.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.4_grids.html-exxRQ7PN.js b/assets/4.4_grids.html-exxRQ7PN.js new file mode 100644 index 00000000..14f886b4 --- /dev/null +++ b/assets/4.4_grids.html-exxRQ7PN.js @@ -0,0 +1,14 @@ +import{_ as u}from"./icon_script_editor-ibm_2NsU.js";import{_ as o,r as s,o as c,c as i,a as n,b as a,d as e,w as l,e as d}from"./app-LOf__QKq.js";const r={},k=n("h1",{id:"_4-4-栅格图形",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-4-栅格图形","aria-hidden":"true"},"#"),a(" 4.4 栅格图形")],-1),m=n("strong",null,"栅格图形",-1),v=n("strong",null,"项目",-1),g=n("img",{src:u,alt:"icon"},null,-1),h=n("strong",null,"ScriptEditor",-1),b=d(`

栅格数据操作

CreateGrid("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]])
+

返回一个Grid对象。

GetCellSize(Grid)
+

返回Grid的Cellsize值。

GetGridMaxXY(Grid)
+

返回Grid的XMax和YMax值。

ConvertToGridXY(Grid, x1, y1 [, x2, y2, ...])
+

将实际坐标转换为Grid中的坐标。返回X1,Y1,X2,Y2,...。

ShapeToGrid(Grid, Shape, value)
+

Grid中将Shape栅格化。栅格单元值将根据覆盖面积和输入的值设置。

ShapeToGrid(Grid, Shapes, "field_name")
+

Shapes中栅格化所有的Shape对象。栅格单元值将根据覆盖面积和Shapes字段的值设置。

GetValue(Grid, X1, Y1 [, X2, Y2, ...])
+

返回指定Grid坐标的单元格值:value1,value2,...。

SetValue(Grid, value, X1, Y1 [, X2, Y2, ...])
+

设置指定Grid坐标单元的值。

GetCenterXY(Grid)
+

返回Grid的中心实际坐标(x,y)。

GetCenterXY(Grid, X1, Y1 [, X2, Y2, ...])
+

返回单元格中心的实际坐标:x1,y1,x2,y2,...。

GetExtent(Grid)
+

返回Grid范围的左下角和右上角坐标:Lx,By,Rx,Ty。

GetExtent(Grid, X, Y)
+

返回单元格范围的左下角和右上角坐标:Lx,By,Rx,Ty。

GetFractalDim(Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0])
+

计算Grid中指定区域的分形维度。返回维度,线性回归的RSQ值以及每个折叠中的盒子数。

`,27),_={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},x=n("strong",null,"反馈",-1);function G(f,X){const t=s("RouterLink"),p=s("ExternalLinkIcon");return c(),i("div",null,[k,n("p",null,[a("在MicroCity中,"),m,a("具有简单的结构("),e(t,{to:"/docs/3.3_raster_grids.html"},{default:l(()=>[a("3.3")]),_:1}),a("),但是如果在其上应用算法,可以高效利用时间和空间。本章的示例代码可以在"),v,a('选项卡的"grid_samples"文件夹中找到,该选项卡位于'),g,h,a("中。")]),b,n("blockquote",null,[n("p",null,[a("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",_,[x,e(p)]),a("页面提交反馈。")])])])}const y=o(r,[["render",G],["__file","4.4_grids.html.vue"]]);export{y as default}; diff --git a/assets/4.4_grids.html-sbNpid1M.js b/assets/4.4_grids.html-sbNpid1M.js deleted file mode 100644 index 22fe3c9e..00000000 --- a/assets/4.4_grids.html-sbNpid1M.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-c670a3a8","path":"/docs/4.4_grids.html","title":"4.4 栅格图形","lang":"zh-CN","frontmatter":{"prev":"./4.3_shapes_and_tables.md","next":"./4.5_3d_scenes.md","description":"Grids in MicroCity have simple structure (3.3 (3.3rastergrids.md)) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be ...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.4_grids.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.4 栅格图形"}],["meta",{"property":"og:description","content":"Grids in MicroCity have simple structure (3.3 (3.3rastergrids.md)) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.4 栅格图形"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.4 栅格图形\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Cellular Data Manipulation","slug":"cellular-data-manipulation","link":"#cellular-data-manipulation","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.4_grids.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.5_3d_scenes.html-FkF6l2hE.js b/assets/4.5_3d_scenes.html-FkF6l2hE.js deleted file mode 100644 index e61e2d54..00000000 --- a/assets/4.5_3d_scenes.html-FkF6l2hE.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-672fdfba","path":"/docs/4.5_3d_scenes.html","title":"4.5 3D场景","lang":"zh-CN","frontmatter":{"prev":"./4.4_grids.md","next":"./4.6_networks.md","description":"Scenes and inside 3D objects (3.4 (3.43dscenes.md)) can be scripted. Sample codes for this chapter can be found in the \\"3dsamples\\" folder of the **Project** Tab in !icon (./imgs...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.5_3d_scenes.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.5 3D场景"}],["meta",{"property":"og:description","content":"Scenes and inside 3D objects (3.4 (3.43dscenes.md)) can be scripted. Sample codes for this chapter can be found in the \\"3dsamples\\" folder of the **Project** Tab in !icon (./imgs..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.5 3D场景"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.5 3D场景\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"3D Scene and Object Manipulation","slug":"_3d-scene-and-object-manipulation","link":"#_3d-scene-and-object-manipulation","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.5_3d_scenes.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.5_3d_scenes.html-2AMaq24g.js b/assets/4.5_3d_scenes.html-IYlmTIee.js similarity index 92% rename from assets/4.5_3d_scenes.html-2AMaq24g.js rename to assets/4.5_3d_scenes.html-IYlmTIee.js index 15a5f6e6..7c231d17 100644 --- a/assets/4.5_3d_scenes.html-2AMaq24g.js +++ b/assets/4.5_3d_scenes.html-IYlmTIee.js @@ -1,4 +1,4 @@ -import{_ as t}from"./icon_script_editor-ibm_2NsU.js";import{_ as e,r as p,o,c,a as n,b as a,d as u,w as l,e as i}from"./app-DaLjD81q.js";const d={},r=n("h1",{id:"_4-5-3d场景",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-5-3d场景","aria-hidden":"true"},"#"),a(" 4.5 3D场景")],-1),k=n("strong",null,"Scenes",-1),b=n("strong",null,"3D objects",-1),v=n("strong",null,"Project",-1),m=n("img",{src:t,alt:"icon"},null,-1),g=n("strong",null,"ScriptEditor",-1),h=i(`

3D Scene and Object Manipulation

CreateScene ("Title" [, RotSpeed=1] [, TransSpeed=1])
+import{_ as e}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as p,o,c,a as n,b as a,d as u,w as l,e as i}from"./app-LOf__QKq.js";const d={},r=n("h1",{id:"_4-5-3d-scenes",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-5-3d-scenes","aria-hidden":"true"},"#"),a(" 4.5 3D Scenes")],-1),k=n("strong",null,"Scenes",-1),b=n("strong",null,"3D objects",-1),v=n("strong",null,"Project",-1),m=n("img",{src:e,alt:"icon"},null,-1),g=n("strong",null,"ScriptEditor",-1),h=i(`

3D Scene and Object Manipulation

CreateScene ("Title" [, RotSpeed=1] [, TransSpeed=1])
 

Creates a new 3d scene and returns the object.

AddZipTo3DPath (Scene, "filename.zip")
 

Adds a zip file to the search directory and returns true if succeed. It is useful for collecting a large amount of files.

LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg")
 

Loads six image files as the skybox of a 3d scene.

LoadObject (Scene, "filename.3ds" [,shadow = false [, AnimationSpeed]])
@@ -26,4 +26,4 @@ import{_ as t}from"./icon_script_editor-ibm_2NsU.js";import{_ as e,r as p,o,c,a
 

Returns selected objects from a 3d scene.

GetObjectID (Object1 [, Object2, ...])
 

Returns "id"s of objects.

SetObjectID (Object, "id")
 

Sets the id of an object.

GetObject (Scene, "id")
-

Finds an object by its id.

`,57);function f(j,x){const s=p("RouterLink");return o(),c("div",null,[r,n("p",null,[k,a(" and inside "),b,a(" ("),u(s,{to:"/docs/3.4_3d_scenes.html"},{default:l(()=>[a("3.4")]),_:1}),a(') can be scripted. Sample codes for this chapter can be found in the "3d_samples" folder of the '),v,a(" Tab in "),m,g,a(".")]),h])}const q=e(d,[["render",f],["__file","4.5_3d_scenes.html.vue"]]);export{q as default}; +

Finds an object by its id.

`,57);function f(j,x){const s=p("RouterLink");return o(),c("div",null,[r,n("p",null,[k,a(" and inside "),b,a(" ("),u(s,{to:"/en/docs/3.4_3d_scenes.html"},{default:l(()=>[a("3.4")]),_:1}),a(') can be scripted. Sample codes for this chapter can be found in the "3d_samples" folder of the '),v,a(" Tab in "),m,g,a(".")]),h])}const q=t(d,[["render",f],["__file","4.5_3d_scenes.html.vue"]]);export{q as default}; diff --git a/assets/4.5_3d_scenes.html-I_su3OaS.js b/assets/4.5_3d_scenes.html-I_su3OaS.js new file mode 100644 index 00000000..9515c5c1 --- /dev/null +++ b/assets/4.5_3d_scenes.html-I_su3OaS.js @@ -0,0 +1,29 @@ +import{_ as o}from"./icon_script_editor-ibm_2NsU.js";import{_ as c,r as s,o as u,c as l,a as n,b as a,d as t,w as i,e as d}from"./app-LOf__QKq.js";const r={},k=n("h1",{id:"_4-5-3d场景",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-5-3d场景","aria-hidden":"true"},"#"),a(" 4.5 3D场景")],-1),v=n("strong",null,"场景",-1),g=n("strong",null,"3D物体",-1),m=n("strong",null,"项目",-1),b=n("img",{src:o,alt:"图标"},null,-1),h=n("a",{href:"icon_script_editor.png"},[n("strong",null,"ScriptEditor")],-1),x=d(`

3D场景和物体操作

CreateScene ("标题" [, RotSpeed=1] [, TransSpeed=1])
+

创建一个新的3D场景并返回物体。

AddZipTo3DPath (Scene, "文件名.zip")
+

将一个zip文件添加到搜索目录中,并在成功时返回true。这对于收集大量文件很有用。

LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg")
+

将六个图像文件加载为3D场景的天空盒。

LoadObject (Scene, "文件名.3ds" [,shadow = false [, AnimationSpeed]])
+

从文件中加载一个3D物体,并返回该物体。

AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255])
+

添加一个光源物体,并返回该物体。

Add3DLabel(Scene, "标签" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]])
+

在坐标(0,0,0)处添加一个3D标签,并返回该物体。

Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0])
+

从点(x1, y1, z1)到点(x2, y2, z2)添加一个3D线物体,并返回该物体。

Add3DRect (Scene, 长度, 宽度 [, r = 180, g = 180, b = 180])
+

从(-长度/2,0,-宽度/2)到(长度/2,0,宽度/2)添加一个3D矩形物体,并返回该物体。

Add3DBox (Scene, 长度, 宽度, 高度 [, r = 180, g = 180, b = 180 [, bShowEdge = true]])
+

从(-长度/2,-高度/2,-宽度/2)到(长度/2,高度/2,宽度/2)添加一个3D盒子物体,并返回该物体。

AddSphere (Scene, 半径 [, polycount = 16 [, r = 180, g = 180, b = 180]])
+

在坐标(0,0,0)处添加一个球体,并返回该物体。如果半径参数小于0,则返回一个不可见的物体。

GetTexture (Object)
+

返回一个物体的纹理文件:"文件名1","文件名2"等等。

LoadTexture (Scene, Object, "文件名1" [, "文件名2", ...])
+

加载纹理文件到一个物体中。

SetPosition (Object, x, y, z [, absolute = false])
+

设置一个物体相对于其父物体的位置(或者绝对位置到场景)。

GetPosition (Object [, absolute = false])
+

获取一个物体相对于其父物体的位置(或者该物体在场景中的绝对位置)。

SetRotation (Object, rx, ry, rz [, absolute = false])
+

设置一个物体相对于其父物体的旋转角度(左手坐标系),以度为单位(或者该物体在场景中的绝对旋转角度)。

GetRotation (Object [, absolute = false])
+

获取一个物体相对于其父物体的旋转角度(左手坐标系),以度为单位(或者该物体在场景中的绝对旋转角度)。

SetScale (Object, sx, sy, sz)
+

设置一个物体的缩放比例。

GetScale (Object)
+

获取一个物体的缩放比例。

SetParent (Object, Parent)
+

将一个物体作为子物体附加到另一个物体上。

GetParent (Object)
+

获取一个物体的父物体。

SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]])
+

设置一个物体的id、位置、旋转和缩放。

DelObject (Object)
+

删除一个物体。

SetCamera (Scene, x, y, z [,Tx, Ty, Tz])
+

设置场景相机的位置和目标。

GetCamera (Scene)
+

获取一个3D场景的相机物体以及其位置和目标。

GetSelections (Scene)
+

从一个3D场景中返回选中的物体。

GetObjectID (Object1 [, Object2, ...])
+

返回物体的"id"。

SetObjectID (Object, "id")
+

设置一个物体的id。

GetObject (Scene, "id")
+

根据id查找一个物体。

`,57),_={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},f=n("strong",null,"反馈",-1);function q(S,j){const e=s("RouterLink"),p=s("ExternalLinkIcon");return u(),l("div",null,[k,n("p",null,[v,a("和"),g,a("("),t(e,{to:"/docs/3.4_3d_scenes.html"},{default:i(()=>[a("3.4")]),_:1}),a(")可以进行脚本编写。本章节的示例代码可以在"),m,a('标签中的"3d_samples"文件夹中的'),b,h,a("中找到。")]),x,n("blockquote",null,[n("p",null,[a("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",_,[f,t(p)]),a("页面提交反馈。")])])])}const D=c(r,[["render",q],["__file","4.5_3d_scenes.html.vue"]]);export{D as default}; diff --git a/assets/4.5_3d_scenes.html-rRFZU4Tx.js b/assets/4.5_3d_scenes.html-rRFZU4Tx.js new file mode 100644 index 00000000..d0dab1c4 --- /dev/null +++ b/assets/4.5_3d_scenes.html-rRFZU4Tx.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-672fdfba","path":"/docs/4.5_3d_scenes.html","title":"4.5 3D场景","lang":"zh-CN","frontmatter":{"prev":"./4.4_grids.md","next":"./4.6_networks.md","description":"场景和3D物体(3.4 (3.43dscenes.md))可以进行脚本编写。本章节的示例代码可以在项目标签中的\\"3dsamples\\"文件夹中的!图标 (../images/doc/iconscripteditor.png)[**ScriptEditor**](iconscript_editor.png)中找到。 3D场景和物体操作创建一个新的3D场景并...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.5_3d_scenes.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.5_3d_scenes.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.5 3D场景"}],["meta",{"property":"og:description","content":"场景和3D物体(3.4 (3.43dscenes.md))可以进行脚本编写。本章节的示例代码可以在项目标签中的\\"3dsamples\\"文件夹中的!图标 (../images/doc/iconscripteditor.png)[**ScriptEditor**](iconscript_editor.png)中找到。 3D场景和物体操作创建一个新的3D场景并..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.5 3D场景\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"3D场景和物体操作","slug":"_3d场景和物体操作","link":"#_3d场景和物体操作","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.5_3d_scenes.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.5_3d_scenes.html-wmTORBrk.js b/assets/4.5_3d_scenes.html-wmTORBrk.js new file mode 100644 index 00000000..3c0dad1d --- /dev/null +++ b/assets/4.5_3d_scenes.html-wmTORBrk.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0461258f","path":"/en/docs/4.5_3d_scenes.html","title":"4.5 3D Scenes","lang":"en-US","frontmatter":{"prev":"./4.4_grids.md","next":"./4.6_networks.md","description":"Scenes and inside 3D objects (3.4 (3.43dscenes.md)) can be scripted. Sample codes for this chapter can be found in the \\"3dsamples\\" folder of the **Project** Tab in !icon (../../...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.5_3d_scenes.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.5_3d_scenes.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.5 3D Scenes"}],["meta",{"property":"og:description","content":"Scenes and inside 3D objects (3.4 (3.43dscenes.md)) can be scripted. Sample codes for this chapter can be found in the \\"3dsamples\\" folder of the **Project** Tab in !icon (../../..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.5 3D Scenes\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"3D Scene and Object Manipulation","slug":"_3d-scene-and-object-manipulation","link":"#_3d-scene-and-object-manipulation","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.5_3d_scenes.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.6_networks.html-0YdpivDj.js b/assets/4.6_networks.html-0YdpivDj.js new file mode 100644 index 00000000..91e944fb --- /dev/null +++ b/assets/4.6_networks.html-0YdpivDj.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-34511d54","path":"/docs/4.6_networks.html","title":"4.6 网络","lang":"zh-CN","frontmatter":{"prev":"./4.5_3d_scenes.md","next":"./4.7_des_simulations.md","description":"在MicroCity中,GIS矢量数据(参见3.2 (3.2vectorshapes))可以进行拓扑操作,并应用最短路径算法和用户均衡交通分配算法。本章的示例代码可以在项目选项卡的\\"networksamples\\"文件夹中找到,具体请参考!icon (../images/doc/iconscript_editor.png)ScriptEditor。 网络...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.6_networks.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.6_networks.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.6 网络"}],["meta",{"property":"og:description","content":"在MicroCity中,GIS矢量数据(参见3.2 (3.2vectorshapes))可以进行拓扑操作,并应用最短路径算法和用户均衡交通分配算法。本章的示例代码可以在项目选项卡的\\"networksamples\\"文件夹中找到,具体请参考!icon (../images/doc/iconscript_editor.png)ScriptEditor。 网络..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.6 网络\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"网络操作","slug":"网络操作","link":"#网络操作","children":[]},{"level":2,"title":"算法","slug":"算法","link":"#算法","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.6_networks.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.6_networks.html-HJVUieG0.js b/assets/4.6_networks.html-HJVUieG0.js new file mode 100644 index 00000000..dc105775 --- /dev/null +++ b/assets/4.6_networks.html-HJVUieG0.js @@ -0,0 +1,21 @@ +import{_ as e}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as p,o,c as u,a as n,b as a,d as c,e as l}from"./app-LOf__QKq.js";const i={},d=l('

4.6 网络

在MicroCity中,GIS矢量数据(参见3.2)可以进行拓扑操作,并应用最短路径算法用户均衡交通分配算法。本章的示例代码可以在项目选项卡的"network_samples"文件夹中找到,具体请参考iconScriptEditor

网络操作

CreateNetwork ()
+

创建一个空网络对象并返回。

CreateNetwork (UnTopoLines)
+

从未进行拓扑操作的“线”形状创建网络,并返回三个对象:网络、节点(形状)和链接(形状)。

CreateNetwork (Nodes, Links)
+

从进行了拓扑操作的节点和链接形状创建网络对象。返回网络对象。

InitNetwork (Network, Nodes, Links)
+

从节点和链接形状初始化网络。如果成功返回true。

AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]])
+

向网络中添加新的链接或更新现有链接。返回linkID、oID、dID、添加结果(true/false)和更新结果(true/false)。

AddLink (Network, Shapes|Table, index1 [, index2, ...])
+

从形状记录集或表中添加或更新链接。返回布尔值。

DelLink (Network, linkID)
+

从网络中删除链接。返回布尔值。

GetNearNodeID (Network, x, y [, radius=nil])
+

获取坐标最近的网络节点。返回节点ID。

GetNodeXY (Network, nodeID1 [, nodeID2, ...])
+

返回网络中节点的坐标:x1、y1、x2、y2,等等。

算法

GenSTPTree (Network, startID [, endID])
+

从一个节点生成最短路径生成树。返回布尔值。

GetSTPPath (Network, endID, "NodeID"|"LinkID")
+

在调用GenSTPTree之后调用该函数。返回由节点ID或链接ID序列表示的最短路径:id1、id2,等等。

GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp")
+

在调用GenSTPTree之后调用该函数。返回由节点或链接形状索引序列表示的最短路径。

GetSTPPath (Network, endID, "NodeShp"|"LinkShp")
+

在调用GenSTPTree之后调用该函数。返回由节点或链接形状对象序列表示的最短路径。

GetSTPLen (Network, endID)
+

在调用GenSTPTree之后调用该函数。返回到达目标节点的最短路径距离。

GetSTPLen (Network, startID, endID)
+

在网络中从起点节点到终点节点获取最短路径。返回距离。

GetSTPLen (Network, x1, y1, x2, y2)
+

在网络中从起点坐标到终点坐标获取最短路径。返回距离。

SetTrip (Network, oID, dID, amount)
+

设置从出发地到目的地的旅行量。

SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]])
+

在调用SetTrip之后调用该函数。执行用户均衡交通分配,并返回布尔值。

GetFlow (Network, linkID)
+

返回指定链接的交通流量。

SetFlow (Network, linkID, flow)
+

设置指定链接的交通流量,并返回布尔值。

`,44),r={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},k=n("strong",null,"反馈",-1);function v(m,g){const s=p("ExternalLinkIcon");return o(),u("div",null,[d,n("blockquote",null,[n("p",null,[a("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",r,[k,c(s)]),a("页面提交反馈。")])])])}const f=t(i,[["render",v],["__file","4.6_networks.html.vue"]]);export{f as default}; diff --git a/assets/4.6_networks.html-O88jEbX0.js b/assets/4.6_networks.html-O88jEbX0.js deleted file mode 100644 index 013e4784..00000000 --- a/assets/4.6_networks.html-O88jEbX0.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-34511d54","path":"/docs/4.6_networks.html","title":"4.6 网络","lang":"zh-CN","frontmatter":{"prev":"./4.5_3d_scenes.md","next":"./4.7_des_simulations.md","description":"GIS vector data (3.2 (3.2vectorshapes)) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sa...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.6_networks.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.6 网络"}],["meta",{"property":"og:description","content":"GIS vector data (3.2 (3.2vectorshapes)) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sa..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.6 网络"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.6 网络\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Network Manipulation","slug":"network-manipulation","link":"#network-manipulation","children":[]},{"level":2,"title":"Algorithms","slug":"algorithms","link":"#algorithms","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.6_networks.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.6_networks.html-PK_mfd9Y.js b/assets/4.6_networks.html-Z1GoybBX.js similarity index 92% rename from assets/4.6_networks.html-PK_mfd9Y.js rename to assets/4.6_networks.html-Z1GoybBX.js index 6bac18d9..f5e0ecc6 100644 --- a/assets/4.6_networks.html-PK_mfd9Y.js +++ b/assets/4.6_networks.html-Z1GoybBX.js @@ -1,4 +1,4 @@ -import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as e,e as t}from"./app-DaLjD81q.js";const o={},p=t('

4.6 网络

GIS vector data (3.2) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sample codes for this chapter can be found in the "network_samples" folder of the Project Tab in iconScriptEditor.

Network Manipulation

CreateNetwork ()
+import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as e,e as t}from"./app-LOf__QKq.js";const o={},p=t('

4.6 Networks

GIS vector data (3.2) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sample codes for this chapter can be found in the "network_samples" folder of the Project Tab in iconScriptEditor.

Network Manipulation

CreateNetwork ()
 

Creates an empty network and returns the object.

CreateNetwork (UnTopoLines)
 

Creates a network from an untopologized "line" Shapes and returns three objects: Network, Nodes (Shapes) and Links (Shapes).

CreateNetwork (Nodes, Links)
 

Creates a Network object from topologized Nodes and Links Shapes. Returns the Network object.

InitNetwork (Network, Nodes, Links)
diff --git a/assets/4.6_networks.html-kqO_isZV.js b/assets/4.6_networks.html-kqO_isZV.js
new file mode 100644
index 00000000..29e7ead0
--- /dev/null
+++ b/assets/4.6_networks.html-kqO_isZV.js
@@ -0,0 +1 @@
+const t=JSON.parse('{"key":"v-10effe6a","path":"/en/docs/4.6_networks.html","title":"4.6 Networks","lang":"en-US","frontmatter":{"prev":"./4.5_3d_scenes.md","next":"./4.7_des_simulations.md","description":"GIS vector data (3.2 (3.2vectorshapes)) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sa...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.6_networks.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.6_networks.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.6 Networks"}],["meta",{"property":"og:description","content":"GIS vector data (3.2 (3.2vectorshapes)) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sa..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.6 Networks\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Network Manipulation","slug":"network-manipulation","link":"#network-manipulation","children":[]},{"level":2,"title":"Algorithms","slug":"algorithms","link":"#algorithms","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.6_networks.md","autoDesc":true}');export{t as data};
diff --git a/assets/4.7_des_simulations.html-Ie9zDG_n.js b/assets/4.7_des_simulations.html-Ie9zDG_n.js
new file mode 100644
index 00000000..62512979
--- /dev/null
+++ b/assets/4.7_des_simulations.html-Ie9zDG_n.js
@@ -0,0 +1,17 @@
+import{_ as e}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as p,o,c as u,a as n,b as a,d as c,e as l}from"./app-LOf__QKq.js";const i={},r=l('

4.7 离散事件仿真

MicroCity有一个内置的模拟时间计数和事件调度机制。它提供了几个嵌入的Lua函数来方便创建离散事件仿真,这对于动态系统分析非常有用。本章的示例代码可以在项目选项卡的“simulation_samples”文件夹中的iconScriptEditor找到。

随机数生成

CreateRandEng (seed, "uniform_01")
+

使用种子创建一个二进制分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "uniform_real" [, min = 0, max = 1])
+

使用种子创建一个服从均匀分布的实数随机数生成引擎,并返回该对象。

CreateRandEng (seed, "uniform_int" [, min = 0, max = 1])
+

使用种子创建一个服从均匀分布的整数随机数生成引擎,并返回该对象。

CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2])
+

使用种子创建一个服从三角分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "bernoulli" [, p = 0])
+

使用种子创建一个服从伯努利分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1])
+

使用种子创建一个服从柯西分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "exponential" [, lambda = 1])
+

使用种子创建一个服从指数分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "geometric" [, p = 0])
+

使用种子创建一个服从几何分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "normal" [, mean = 0, sigma = 1])
+

使用种子创建一个服从正态分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1])
+

使用种子创建一个服从对数正态分布的随机数生成引擎,并返回该对象。

GetNextRandom (Engine)
+

从随机数生成引擎中获取一个随机数。

模拟控制

CreateEvent (time, Funcion [, arg1, arg2, ...])
+

Lua FunctionLua Coroutine创建一个将来的事件,并返回一个Coroutine对象。

ExecAllEvents ()
+

最后调用这个函数。它会将所有事件作为Lua Coroutines执行。

Delay ([relativeTime = 0])
+

Lua Coroutine中调用这个函数,让它先暂停一段指定的相对时间,然后再恢复执行。如果没有设置参数relativeTime,当前的Coroutine将暂停而不会自动恢复。

Resume ([time, ] Coroutine [, arg1, arg2, ...])
+

立即或在指定的时间恢复一个已暂停的协程。

GetSimTime ()
+

返回当前的模拟时间。

`,36),d={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},k=n("strong",null,"反馈",-1);function m(g,v){const s=p("ExternalLinkIcon");return o(),u("div",null,[r,n("blockquote",null,[n("p",null,[a("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",d,[k,c(s)]),a("页面提交反馈。")])])])}const _=t(i,[["render",m],["__file","4.7_des_simulations.html.vue"]]);export{_ as default}; diff --git a/assets/4.7_des_simulations.html-JlfYhUg2.js b/assets/4.7_des_simulations.html-JlfYhUg2.js new file mode 100644 index 00000000..0d8b7daa --- /dev/null +++ b/assets/4.7_des_simulations.html-JlfYhUg2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-cd9655fa","path":"/en/docs/4.7_des_simulations.html","title":"4.7 Discrete Event Simulations","lang":"en-US","frontmatter":{"prev":"./4.6_networks.md","next":"./4.8_mixed_integer_programming.md","description":"MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, whi...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.7_des_simulations.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.7_des_simulations.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.7 Discrete Event Simulations"}],["meta",{"property":"og:description","content":"MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, whi..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.7 Discrete Event Simulations\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Random Number Generation","slug":"random-number-generation","link":"#random-number-generation","children":[]},{"level":2,"title":"Simulation Control","slug":"simulation-control","link":"#simulation-control","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.7_des_simulations.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.7_des_simulations.html-W4OcSvr1.js b/assets/4.7_des_simulations.html-W4OcSvr1.js new file mode 100644 index 00000000..5deb4fd3 --- /dev/null +++ b/assets/4.7_des_simulations.html-W4OcSvr1.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-6802fed2","path":"/docs/4.7_des_simulations.html","title":"4.7 离散事件仿真","lang":"zh-CN","frontmatter":{"prev":"./4.6_networks.md","next":"./4.8_mixed_integer_programming.md","description":"MicroCity有一个内置的模拟时间计数和事件调度机制。它提供了几个嵌入的Lua函数来方便创建离散事件仿真,这对于动态系统分析非常有用。本章的示例代码可以在项目选项卡的“simulationsamples”文件夹中的!icon (../images/doc/iconscript_editor.png)ScriptEditor找到。 随机数生成使用种子...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.7_des_simulations.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.7_des_simulations.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.7 离散事件仿真"}],["meta",{"property":"og:description","content":"MicroCity有一个内置的模拟时间计数和事件调度机制。它提供了几个嵌入的Lua函数来方便创建离散事件仿真,这对于动态系统分析非常有用。本章的示例代码可以在项目选项卡的“simulationsamples”文件夹中的!icon (../images/doc/iconscript_editor.png)ScriptEditor找到。 随机数生成使用种子..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.7 离散事件仿真\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"随机数生成","slug":"随机数生成","link":"#随机数生成","children":[]},{"level":2,"title":"模拟控制","slug":"模拟控制","link":"#模拟控制","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.7_des_simulations.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.7_des_simulations.html-8bSUiGUz.js b/assets/4.7_des_simulations.html-WnzqINmi.js similarity index 90% rename from assets/4.7_des_simulations.html-8bSUiGUz.js rename to assets/4.7_des_simulations.html-WnzqINmi.js index 8e23a3db..58560c12 100644 --- a/assets/4.7_des_simulations.html-8bSUiGUz.js +++ b/assets/4.7_des_simulations.html-WnzqINmi.js @@ -1,4 +1,4 @@ -import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as e,e as t}from"./app-DaLjD81q.js";const o={},p=t('

4.7 离散事件模拟

MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, which is very useful for dynamic system analysis. Sample codes for this chapter can be found in the "simulation_samples" folder of the Project Tab in iconScriptEditor.

Random Number Generation

CreateRandEng (seed, "uniform_01")
+import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as e,e as t}from"./app-LOf__QKq.js";const o={},p=t('

4.7 Discrete Event Simulations

MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, which is very useful for dynamic system analysis. Sample codes for this chapter can be found in the "simulation_samples" folder of the Project Tab in iconScriptEditor.

Random Number Generation

CreateRandEng (seed, "uniform_01")
 

Creates a binary distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "uniform_real" [, min = 0, max = 1])
 

Creates a uniform distributed real random generation engine from a seed and returns the object.

CreateRandEng (seed, "uniform_int" [, min = 0, max = 1])
 

Creates an uniform integer random generation engine from a seed and returns the object.

CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2])
diff --git a/assets/4.7_des_simulations.html-Ztj4rB4B.js b/assets/4.7_des_simulations.html-Ztj4rB4B.js
deleted file mode 100644
index 8173f577..00000000
--- a/assets/4.7_des_simulations.html-Ztj4rB4B.js
+++ /dev/null
@@ -1 +0,0 @@
-const t=JSON.parse('{"key":"v-6802fed2","path":"/docs/4.7_des_simulations.html","title":"4.7 离散事件模拟","lang":"zh-CN","frontmatter":{"prev":"./4.6_networks.md","next":"./4.8_mixed_integer_programming.md","description":"MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, whi...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.7_des_simulations.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.7 离散事件模拟"}],["meta",{"property":"og:description","content":"MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, whi..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.7 离散事件模拟"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.7 离散事件模拟\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Random Number Generation","slug":"random-number-generation","link":"#random-number-generation","children":[]},{"level":2,"title":"Simulation Control","slug":"simulation-control","link":"#simulation-control","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.7_des_simulations.md","autoDesc":true}');export{t as data};
diff --git a/assets/4.7_des_simulations_zh.html-PYbnXFlK.js b/assets/4.7_des_simulations_zh.html-PYbnXFlK.js
new file mode 100644
index 00000000..419ec91a
--- /dev/null
+++ b/assets/4.7_des_simulations_zh.html-PYbnXFlK.js
@@ -0,0 +1,17 @@
+import{_ as n}from"./icon_script_editor-ibm_2NsU.js";import{_ as a,o as s,c as t,e as p}from"./app-LOf__QKq.js";const e={},o=p('

4.7 离散事件模拟

MicroCity具有内部模拟时间计数和事件调度机制。它提供了几个嵌入式Lua函数,以便更容易地创建离散事件模拟,这对于动态系统分析非常有用。本章的示例代码可以在 图标ScriptEditorProject 选项卡的"simulation_samples"文件夹中找到。

随机数生成

CreateRandEng(seed, "uniform_01")
+

从种子创建一个二进制分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "uniform_real" [, min = 0, max = 1])
+

从种子创建一个均匀分布的实数随机生成引擎,并返回该对象。

CreateRandEng(seed, "uniform_int" [, min = 0, max = 1])
+

从种子创建一个均匀分布的整数随机生成引擎,并返回该对象。

CreateRandEng(seed, "triangle" [, a = 0, b = 1, c = 2])
+

从种子创建一个三角形分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "bernoulli" [, p = 0])
+

从种子创建一个伯努利分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "cauchy" [, median = 0, sigma = 1])
+

从种子创建一个柯西分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "exponential" [, lambda = 1])
+

从种子创建一个指数分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "geometric" [, p = 0])
+

从种子创建一个几何分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "normal" [, mean = 0, sigma = 1])
+

从种子创建一个正态分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "lognormal" [, mean = 0, sigma = 1])
+

从种子创建一个对数正态分布的随机生成引擎,并返回该对象。

GetNextRandom(Engine)
+

从随机生成引擎获取一个随机数。

模拟控制

CreateEvent(time, Function [, arg1, arg2, ...])
+

Lua函数Lua协程创建一个未来事件。返回一个协程对象。

ExecAllEvents()
+

最后调用此函数。它将执行所有事件作为Lua协程

Delay([relativeTime = 0])
+

Lua协程中调用此函数将使其首先暂停,然后在指定的相对时间后恢复。如果未设置relativeTime参数,则当前协程将暂停,并且不会自动恢复。

Resume([time, ] Coroutine [, arg1, arg2, ...])
+

立即或在指定时间恢复一个已暂停的协程。

GetSimTime()
+

返回当前模拟时间。

`,36),c=[o];function u(l,i){return s(),t("div",null,c)}const d=a(e,[["render",u],["__file","4.7_des_simulations_zh.html.vue"]]);export{d as default}; diff --git a/assets/4.7_des_simulations_zh.html-dVopgWmS.js b/assets/4.7_des_simulations_zh.html-dVopgWmS.js new file mode 100644 index 00000000..ccffa861 --- /dev/null +++ b/assets/4.7_des_simulations_zh.html-dVopgWmS.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-4d7828c2","path":"/en/docs/4.7_des_simulations_zh.html","title":"4.7 离散事件模拟","lang":"en-US","frontmatter":{"prev":"./4.6_networks.md","next":"./4.8_mixed_integer_programming.md","description":"MicroCity具有内部模拟时间计数和事件调度机制。它提供了几个嵌入式Lua函数,以便更容易地创建离散事件模拟,这对于动态系统分析非常有用。本章的示例代码可以在 !图标 (../../images/doc/iconscripteditor.png)ScriptEditor 中 Project 选项卡的\\"simulation_samples\\"文件夹中找...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.7_des_simulations_zh.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.7 离散事件模拟"}],["meta",{"property":"og:description","content":"MicroCity具有内部模拟时间计数和事件调度机制。它提供了几个嵌入式Lua函数,以便更容易地创建离散事件模拟,这对于动态系统分析非常有用。本章的示例代码可以在 !图标 (../../images/doc/iconscripteditor.png)ScriptEditor 中 Project 选项卡的\\"simulation_samples\\"文件夹中找..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.7 离散事件模拟\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"随机数生成","slug":"随机数生成","link":"#随机数生成","children":[]},{"level":2,"title":"模拟控制","slug":"模拟控制","link":"#模拟控制","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.7_des_simulations_zh.md","autoDesc":true}');export{t as data}; diff --git a/assets/4.8_mixed_integer_programming.html-MExXnfeH.js b/assets/4.8_mixed_integer_programming.html-MExXnfeH.js new file mode 100644 index 00000000..29a7cd76 --- /dev/null +++ b/assets/4.8_mixed_integer_programming.html-MExXnfeH.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2b4c8f66","path":"/en/docs/4.8_mixed_integer_programming.html","title":"4.8 Mixed Integer Programming","lang":"en-US","frontmatter":{"prev":"./4.7_des_simulations.md","description":"MicroCity employs the lpsolve (https://sourceforge.net/projects/lpsolve/) to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.8_mixed_integer_programming.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.8_mixed_integer_programming.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"4.8 Mixed Integer Programming"}],["meta",{"property":"og:description","content":"MicroCity employs the lpsolve (https://sourceforge.net/projects/lpsolve/) to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.8 Mixed Integer Programming\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Model Creation and Execution","slug":"model-creation-and-execution","link":"#model-creation-and-execution","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/4.8_mixed_integer_programming.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.8_mixed_integer_programming.html-TGfmzRJO.js b/assets/4.8_mixed_integer_programming.html-TGfmzRJO.js new file mode 100644 index 00000000..b3e90f93 --- /dev/null +++ b/assets/4.8_mixed_integer_programming.html-TGfmzRJO.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-64fe0a3e","path":"/docs/4.8_mixed_integer_programming.html","title":"4.8 混合整数线性规划","lang":"zh-CN","frontmatter":{"prev":"./4.7_des_simulations.md","description":"MicroCity使用lpsolve (https://sourceforge.net/projects/lpsolve/)来解决混合整数线性规划问题。开发人员可以使用嵌入的Lua函数来构建和求解模型。本章的示例代码可以在项目选项卡中的\\"optimizationsamples\\"文件夹中找到,图标为!图标 (../images/doc/iconscrip...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.8_mixed_integer_programming.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.8_mixed_integer_programming.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.8 混合整数线性规划"}],["meta",{"property":"og:description","content":"MicroCity使用lpsolve (https://sourceforge.net/projects/lpsolve/)来解决混合整数线性规划问题。开发人员可以使用嵌入的Lua函数来构建和求解模型。本章的示例代码可以在项目选项卡中的\\"optimizationsamples\\"文件夹中找到,图标为!图标 (../images/doc/iconscrip..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.8 混合整数线性规划\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"模型创建和执行","slug":"模型创建和执行","link":"#模型创建和执行","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"docs/4.8_mixed_integer_programming.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.8_mixed_integer_programming.html-bEUkQ8el.js b/assets/4.8_mixed_integer_programming.html-bEUkQ8el.js deleted file mode 100644 index 51eb47d6..00000000 --- a/assets/4.8_mixed_integer_programming.html-bEUkQ8el.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-64fe0a3e","path":"/docs/4.8_mixed_integer_programming.html","title":"4.8 混合整数线性规划","lang":"zh-CN","frontmatter":{"prev":"./4.7_des_simulations.md","description":"MicroCity employs the lpsolve (https://sourceforge.net/projects/lpsolve/) to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build ...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/4.8_mixed_integer_programming.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"4.8 混合整数线性规划"}],["meta",{"property":"og:description","content":"MicroCity employs the lpsolve (https://sourceforge.net/projects/lpsolve/) to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-05T16:00:29.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"4.8 混合整数线性规划"}],["meta",{"property":"article:modified_time","content":"2022-12-05T16:00:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.8 混合整数线性规划\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-05T16:00:29.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Model Creation and Execution","slug":"model-creation-and-execution","link":"#model-creation-and-execution","children":[]}],"git":{"updatedTime":1670256029000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"docs/4.8_mixed_integer_programming.md","autoDesc":true}');export{e as data}; diff --git a/assets/4.8_mixed_integer_programming.html-E59_LnJJ.js b/assets/4.8_mixed_integer_programming.html-ixWGOETF.js similarity index 85% rename from assets/4.8_mixed_integer_programming.html-E59_LnJJ.js rename to assets/4.8_mixed_integer_programming.html-ixWGOETF.js index 3d169f82..7b9ddc46 100644 --- a/assets/4.8_mixed_integer_programming.html-E59_LnJJ.js +++ b/assets/4.8_mixed_integer_programming.html-ixWGOETF.js @@ -1,4 +1,4 @@ -import{_ as s}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as o,o as i,c as l,a,b as e,d as u,e as c}from"./app-DaLjD81q.js";const p={},d=a("h1",{id:"_4-8-混合整数线性规划",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#_4-8-混合整数线性规划","aria-hidden":"true"},"#"),e(" 4.8 混合整数线性规划")],-1),r={href:"https://sourceforge.net/projects/lpsolve/",target:"_blank",rel:"noopener noreferrer"},m=a("em",null,"lpsolve",-1),v=a("strong",null,"Mixed Integer Linear Programming",-1),b=a("strong",null,"Project",-1),g=a("img",{src:s,alt:"icon"},null,-1),k=a("strong",null,"ScriptEditor",-1),f=c(`

Model Creation and Execution

CreateLP ([rows = 0 , columns = 0])
+import{_ as s}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as o,o as i,c as l,a,b as e,d as u,e as c}from"./app-LOf__QKq.js";const p={},d=a("h1",{id:"_4-8-mixed-integer-programming",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#_4-8-mixed-integer-programming","aria-hidden":"true"},"#"),e(" 4.8 Mixed Integer Programming")],-1),r={href:"https://sourceforge.net/projects/lpsolve/",target:"_blank",rel:"noopener noreferrer"},m=a("em",null,"lpsolve",-1),v=a("strong",null,"Mixed Integer Linear Programming",-1),g=a("strong",null,"Project",-1),b=a("img",{src:s,alt:"icon"},null,-1),k=a("strong",null,"ScriptEditor",-1),f=c(`

Model Creation and Execution

CreateLP ([rows = 0 , columns = 0])
 

Creates a Mixed Integer Linear Programming model and returns the LPModel object.

SetObjFunction (LPModel, rowTable, "MAX"|"MIN")
 

Sets the objective function of a LPModel with a Lua Table which stores coefficients of the decision variables.

AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue)
 

Adds a constraint to a LPModel with a Lua Table which stores coefficients of the decision variables.

SetInteger (LPModel, index)
@@ -12,4 +12,4 @@ import{_ as s}from"./icon_script_editor-ibm_2NsU.js";import{_ as t,r as o,o as i
 

Returns the dual value of a decision variable specified by the index.

GetDuals (LPModel)
 

Returns all dual values of the decision variables of a LPModel.

ReadLP("fileName.mps")
 

Reads a LPModel from a file (*.lp, *.mps) and returns the LPModel if succeed.

WriteLP (LPModel, "fileName.mps")
-

Writes a LPModel to a file (*.lp, *.mps) and returns true if succeed.

`,29);function h(_,x){const n=o("ExternalLinkIcon");return i(),l("div",null,[d,a("p",null,[e("MicroCity employs the "),a("a",r,[m,u(n)]),e(" to takle "),v,e(' problems. Developers can use embedded Lua functions to build and solve models. Sample codes for this chapter can be found in the "optimization_samples" folder of the '),b,e(" Tab in "),g,k,e(".")]),f])}const M=t(p,[["render",h],["__file","4.8_mixed_integer_programming.html.vue"]]);export{M as default}; +

Writes a LPModel to a file (*.lp, *.mps) and returns true if succeed.

`,29);function h(_,x){const n=o("ExternalLinkIcon");return i(),l("div",null,[d,a("p",null,[e("MicroCity employs the "),a("a",r,[m,u(n)]),e(" to takle "),v,e(' problems. Developers can use embedded Lua functions to build and solve models. Sample codes for this chapter can be found in the "optimization_samples" folder of the '),g,e(" Tab in "),b,k,e(".")]),f])}const M=t(p,[["render",h],["__file","4.8_mixed_integer_programming.html.vue"]]);export{M as default}; diff --git a/assets/4.8_mixed_integer_programming.html-spXsyES8.js b/assets/4.8_mixed_integer_programming.html-spXsyES8.js new file mode 100644 index 00000000..1081bf5d --- /dev/null +++ b/assets/4.8_mixed_integer_programming.html-spXsyES8.js @@ -0,0 +1,15 @@ +import{_ as t}from"./icon_script_editor-ibm_2NsU.js";import{_ as l,r as o,o as p,c as i,a as n,b as a,d as e,e as u}from"./app-LOf__QKq.js";const c={},d=n("h1",{id:"_4-8-混合整数线性规划",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-8-混合整数线性规划","aria-hidden":"true"},"#"),a(" 4.8 混合整数线性规划")],-1),r={href:"https://sourceforge.net/projects/lpsolve/",target:"_blank",rel:"noopener noreferrer"},m=n("em",null,"lpsolve",-1),v=n("strong",null,"项目",-1),g=n("img",{src:t,alt:"图标"},null,-1),k=n("strong",null,"ScriptEditor",-1),b=u(`

模型创建和执行

CreateLP ([rows = 0 , columns = 0])
+

创建一个混合整数线性规划模型并返回LPModel对象。

SetObjFunction (LPModel, rowTable, "MAX"|"MIN")
+

使用存储决策变量系数的Lua Table设置LPModel的目标函数。

AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue)
+

使用存储决策变量系数的Lua TableLPModel添加约束。

SetInteger (LPModel, index)
+

将由索引index指定的决策变量设置为整数变量。

SetBinary (LPModel, index)
+

将由索引index指定的LPModel的决策变量设置为二进制变量。

SetUnbounded (LPModel, index)
+

将由索引index指定的LPModel的决策变量设置为无界(正/负无穷大)。

SolveLP (LPModel [, timeoutSec = 60])
+

求解LPModel并返回0表示成功,-1表示无效LP模型,-2表示内存不足,1表示次优,2表示不可行,3表示无界,4表示退化,5表示遇到数值错误,6表示用户中止,7表示超时错误,9表示模型可由预处理解决,10表示B&B例程失败,11表示B&B因中断而停止,12表示找到可行的B&B解决方案,13表示没有可行的B&B解决方案。

GetObjective (LPModel)
+

返回LPModel的目标函数值。

GetVariable (LPModel, index)
+

返回由索引index指定的决策变量的值。

GetVariables (LPModel)
+

返回LPModel的所有决策变量的值。

GetDual (LPModel, index)
+

返回由索引index指定的决策变量的对偶值。

GetDuals (LPModel)
+

返回LPModel的所有决策变量的对偶值。

ReadLP("fileName.mps")
+

从文件(*.lp, *.mps)中读取LPModel,并在成功时返回LPModel

WriteLP (LPModel, "fileName.mps")
+

LPModel写入文件(*.lp, *.mps),并在成功时返回true。

`,29),h={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},_=n("strong",null,"反馈",-1);function x(L,f){const s=o("ExternalLinkIcon");return p(),i("div",null,[d,n("p",null,[a("MicroCity使用"),n("a",r,[m,e(s)]),a("来解决混合整数线性规划问题。开发人员可以使用嵌入的Lua函数来构建和求解模型。本章的示例代码可以在"),v,a('选项卡中的"optimization_samples"文件夹中找到,图标为'),g,k,a(".")]),b,n("blockquote",null,[n("p",null,[a("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),n("a",h,[_,e(s)]),a("页面提交反馈。")])])])}const q=l(c,[["render",x],["__file","4.8_mixed_integer_programming.html.vue"]]);export{q as default}; diff --git a/assets/404.html-G5wmh19c.js b/assets/404.html-tJ8VjSOS.js similarity index 63% rename from assets/404.html-G5wmh19c.js rename to assets/404.html-tJ8VjSOS.js index 84d187e1..a4b92a60 100644 --- a/assets/404.html-G5wmh19c.js +++ b/assets/404.html-tJ8VjSOS.js @@ -1 +1 @@ -import{_ as e,o as c,c as t}from"./app-DaLjD81q.js";const _={};function o(r,n){return c(),t("div")}const a=e(_,[["render",o],["__file","404.html.vue"]]);export{a as default}; +import{_ as e,o as c,c as t}from"./app-LOf__QKq.js";const _={};function o(r,n){return c(),t("div")}const a=e(_,[["render",o],["__file","404.html.vue"]]);export{a as default}; diff --git a/assets/6-1trend-atJpgMOK.js b/assets/6-1trend-atJpgMOK.js new file mode 100644 index 00000000..1201651f --- /dev/null +++ b/assets/6-1trend-atJpgMOK.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/problem1-AJuFUHVQ.webp",t="/MicroCityNotes/assets/无预判障碍-p5itt-RJ.gif",o="/MicroCityNotes/assets/预判障碍-hw2PZ_-s.gif",i="/MicroCityNotes/assets/optimal_layout-bCy9JRge.webp",e="/MicroCityNotes/assets/8cargo-pBqp-1Yq.gif",r="/MicroCityNotes/assets/color5-PRdlG8aV.gif",a="/MicroCityNotes/assets/color8-KLKGFsL4.gif",c="/MicroCityNotes/assets/problem2-KunKgJbC.webp",_="/MicroCityNotes/assets/old-FpQSFo63.gif",p="/MicroCityNotes/assets/new-GF873AfJ.gif",n="/MicroCityNotes/assets/auto_test-ttcTMf95.webp",m="/MicroCityNotes/assets/test_layout-3LvNhD-0.webp",y="/MicroCityNotes/assets/3trend-e8Vz-nOo.webp",C="/MicroCityNotes/assets/6trend-tHF37BNC.webp",N="/MicroCityNotes/assets/sim-result-nEPKqIkR.webp",M="/MicroCityNotes/assets/6-1trend-iFlvvd90.webp";export{t as _,s as a,o as b,i as c,e as d,r as e,a as f,c as g,_ as h,p as i,n as j,m as k,y as l,C as m,N as n,M as o}; diff --git a/assets/A2hs-LwmLJR8r.js b/assets/A2hs-LwmLJR8r.js new file mode 100644 index 00000000..b2d47a20 --- /dev/null +++ b/assets/A2hs-LwmLJR8r.js @@ -0,0 +1 @@ +import{_ as l,o as n,c as d,b as o,a,f as c}from"./app-LOf__QKq.js";const p={data(){return{added:!0,lang:void 0,deferredPrompt:null}},mounted(){lang=document.documentElement.lang,window.addEventListener("beforeinstallprompt",e=>{console.log("浏览器支持安装渐进式Web应用程序"),"standalone"in window.navigator&&window.navigator.standalone?this.added=!0:this.added=!1,e.preventDefault(),this.deferredPrompt=e})},methods:{async promptA2hs(){this.deferredPrompt.prompt(),this.deferredPrompt.userChoice.then(e=>{e.outcome==="accepted"?(console.log("用户已接受A2HS"),this.added=!0):console.log("用户已拒绝A2HS"),this.deferredPrompt=null})}}},f={key:0},m={key:0},h={key:1};function u(e,t,_,g,s,r){return s.added?c("v-if",!0):(n(),d("div",f,[s.lang=="zh-CN"?(n(),d("p",m,[o("由于本站架设于Github上,国内访问可能不稳定🤧。强烈建议您将本站添加至主屏幕,以便网络状况不佳或离线时使用。您可以 "),a("a",{onClick:t[0]||(t[0]=i=>r.promptA2hs()),style:{"font-weight":"bold"}},"点击此处"),o(" 将本站作为Web应用程序安装。")])):(n(),d("p",h,[o("You can "),a("a",{onClick:t[1]||(t[1]=i=>r.promptA2hs()),style:{"font-weight":"bold"}},"click here"),o(" to install this site as a web application 📦")]))]))}const b=l(p,[["render",u],["__file","A2hs.vue"]]);export{b as default}; diff --git a/assets/A2hs-xakqhU9I.js b/assets/A2hs-xakqhU9I.js deleted file mode 100644 index ec717b89..00000000 --- a/assets/A2hs-xakqhU9I.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,o as n,c as a,b as o,a as i,f as l}from"./app-DaLjD81q.js";const p={data(){return{added:!0,deferredPrompt:null}},mounted(){window.addEventListener("beforeinstallprompt",e=>{console.log("浏览器支持安装渐进式Web应用程序"),"standalone"in window.navigator&&window.navigator.standalone?this.added=!0:this.added=!1,e.preventDefault(),this.deferredPrompt=e})},methods:{async promptA2hs(){this.deferredPrompt.prompt(),this.deferredPrompt.userChoice.then(e=>{e.outcome==="accepted"?(console.log("用户已接受A2HS"),this.added=!0):console.log("用户已拒绝A2HS"),this.deferredPrompt=null})}}},c={key:0};function f(e,t,m,u,r,d){return r.added?l("v-if",!0):(n(),a("p",c,[o("由于本站架设于Github上,国内访问可能不稳定🤧。强烈建议您将本站添加至主屏幕,以便网络状况不佳或离线时使用。您可以 "),i("a",{onClick:t[0]||(t[0]=h=>d.promptA2hs()),style:{"font-weight":"bold"}},"点击此处"),o(" 将本站作为Web应用程序安装。")]))}const w=s(p,[["render",f],["__file","A2hs.vue"]]);export{w as default}; diff --git a/assets/DL_Heatmap-RXB-9ZZK.js b/assets/DL_Heatmap-RXB-9ZZK.js new file mode 100644 index 00000000..ca1824eb --- /dev/null +++ b/assets/DL_Heatmap-RXB-9ZZK.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/LookupTableProperties-P0W9jYQE.png",t="/MicroCityNotes/assets/TableSelect-jKGsdf_N.png",o="/MicroCityNotes/assets/LookupTableColor-VSXylHlz.png",e="/MicroCityNotes/assets/SelectLinksColor--zZDTT73.png",i="/MicroCityNotes/assets/GraduatedColorProperties-QL7AyCTd.png",r="/MicroCityNotes/assets/GraduatedColorResult-c1P6KfFi.png",a="/MicroCityNotes/assets/GraduatedColorSettings-sd7MRVbC.png",p="/MicroCityNotes/assets/RelateToMapBig-co0riIjm.png",c="/MicroCityNotes/assets/RelateToMapSmall-8yIwZc0w.png",n="/MicroCityNotes/assets/RelateToScreenBig-H3UhFI8t.png",_="/MicroCityNotes/assets/RelateToScreenSmall-RgyFR_Ap.png",l="/MicroCityNotes/assets/RangeDotRelateToMap-s6apr58V.png",m="/MicroCityNotes/assets/SizeProperties-xZe9_-WE.png",C="/MicroCityNotes/assets/LabelAttribProperties-BNSD9rBn.png",g="/MicroCityNotes/assets/SetParameterProperties-m8LPKWT1.png",y="/MicroCityNotes/assets/PlotPrice1-QAaVF6hQ.png",M="/MicroCityNotes/assets/PlotPrice2-DeodiEK_.png",N="/MicroCityNotes/assets/DL_Heatmap-uiGWW-lH.png";export{y as _,M as a,N as b,s as c,t as d,o as e,e as f,i as g,r as h,a as i,p as j,c as k,n as l,_ as m,l as n,m as o,C as p,g as q}; diff --git a/assets/RMGObjects-PwARz0cG.js b/assets/RMGObjects-PwARz0cG.js new file mode 100644 index 00000000..de54ed4e --- /dev/null +++ b/assets/RMGObjects-PwARz0cG.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/RMGObjects-yrTAIJHV.png";export{s as _}; diff --git a/assets/Result-All2-cnkq843b.js b/assets/Result-All2-cnkq843b.js new file mode 100644 index 00000000..a33d8b5d --- /dev/null +++ b/assets/Result-All2-cnkq843b.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/Banner-O--M2FyY.png",t="/MicroCityNotes/assets/Q1Banner-BxB6kPmr.png",o="/MicroCityNotes/assets/Q1ContainerProcessFlow-t0XYjgJ-.png",i="/MicroCityNotes/assets/RMG1-zXf9sSV8.png",e="/MicroCityNotes/assets/CY1-KhoqZKrQ.png",r="/MicroCityNotes/assets/CYLayout-XevrzO6A.jpg",a="/MicroCityNotes/assets/Q1Run-k0t0w3ny.gif",c="/MicroCityNotes/assets/Q2-hS2yYPEB.jpg",n="/MicroCityNotes/assets/CY2-uRljosmO.png",_="/MicroCityNotes/assets/RMG2-ea6huW81.png",p="/MicroCityNotes/assets/AGV2-cOVBigXf.png",M="/MicroCityNotes/assets/RMGQC2-BO9lyakQ.png",y="/MicroCityNotes/assets/SHIP2-pz8IHA_0.png",C="/MicroCityNotes/assets/Q2Layout-jXHR-iYn.png",g="/MicroCityNotes/assets/Q2ProcessFlow-x5H0zUKQ.png",m="/MicroCityNotes/assets/RMG-AGV-ProcessFlow-aQWltqys.png",N="/MicroCityNotes/assets/AGVQueueModel-VbkDUcno.png",l="/MicroCityNotes/assets/EventSchedulingRefresh-P9P75NgW.jpg",Q="/MicroCityNotes/assets/Result-RMG1-JQinaQsa.gif",R="/MicroCityNotes/assets/Result-RMG2-5wsDxvrc.gif",u="/MicroCityNotes/assets/Result-RMGQC-2f3rMSxL.gif",f="/MicroCityNotes/assets/Result-All1-1lFQ9mTr.gif",G="/MicroCityNotes/assets/Result-All2-nf5PPryC.gif";export{s as _,t as a,o as b,i as c,e as d,r as e,a as f,c as g,n as h,_ as i,p as j,M as k,y as l,C as m,g as n,m as o,N as p,l as q,Q as r,R as s,u as t,f as u,G as v}; diff --git a/assets/SearchBox-cTU2Stp4.js b/assets/SearchBox-cTU2Stp4.js deleted file mode 100644 index 279676d5..00000000 --- a/assets/SearchBox-cTU2Stp4.js +++ /dev/null @@ -1,1567 +0,0 @@ -import{g as f,h as w,i as A,j as L,t as D,u as I,k as z,_ as R,o as u,c as p,l as N,v as O,a as m,n as x,m as y,F as k,p as T,q as S,f as P,s as E}from"./app-DaLjD81q.js";const V=[{path:"/",title:"首页",pathLocale:"/",contents:[{header:"开始使用MicroCity Web",slug:"开始使用microcity-web",content:"打开MicroCity Web,默认加载方块旋转的示例代码。 点击运行按钮运行代码 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用技巧,可以参阅本站提供的 学习笔记"},{header:"开始使用MicroCity Desktop",slug:"开始使用microcity-desktop",content:'转到MicroCity的文档仓库下载 MicroCity的最新版本 打开 ScriptEditor 并输入: Print("hello, world!") 将脚本另存为 test.mcs 并将其拖入 MicroCity 在程序主界面左侧转到 Modules 标签页,打开 test ,双击其中的 main ,执行刚刚编写的脚本。 程序界面下方的 Messages 栏中会输出执行脚本的信息。 更多MicroCity的使用方法可以参考本站搬运自GitHub的文档:MicroCity文档,也可以参考 MicroCtiy 在GitHub上的文档。'},{header:"MicroCityNotes 仓库",slug:"microcitynotes-仓库",content:`国内用户如果不方便访问 GitHub 也可以访问本站在 Netlify 上搭建的 同步站点 -如果发现文档或笔记有问题,欢迎 Pull Request 或者提供 Issues 让它变得更完善😋`}]},{path:"/docs/1.1_what_microcity_can_do.html",title:"1.1 MicroCity能做什么",pathLocale:"/",contents:[{header:"1.1 MicroCity能做什么",slug:"_1-1-microcity能做什么",content:"MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast."},{header:"A Modeling Framework",slug:"a-modeling-framework",content:"Based on GIS, Networks and Mixed Integer Programming libraries, MicroCity can be used as a modeling framework to solve transporation problems, such as City Logistics and Shipping Planning:"},{header:"A Simulation Platform",slug:"a-simulation-platform",content:"Based on 3D CGI and Discrete Event Simulation Engine, MicroCity can be used as a simulation platform to evaluate logistic scenarios, such as Automated Warehouses and Container Terminals:"},{header:"Customized by Scriptable Modules",slug:"customized-by-scriptable-modules",content:"MicroCity can extend its functionality with modules which can be inherited from SAGA or scripted and debugged in Script Editor: Currently, MicroCity is mainly used in teaching and research. It can be freely distributed."}]},{path:"/docs/2.1_showing_a_world_map.html",title:"2.1 展示世界地图",pathLocale:"/",contents:[{header:"2.1 展示世界地图",slug:"_2-1-展示世界地图",content:"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity."},{header:"Loading Data and Creating a Map",slug:"loading-data-and-creating-a-map",content:"Download the countries.shp (ArcGIS shapefile) and the countries.dbf (dBase file) in a same folder. Open MicroCity and load or drag the countries.shp into MicroCity and select Data Tab in Workspace panel. Double click Data->Shapes->Polygon->01. countries in Workspace panel."},{header:"Visualizing Coutries' Properties",slug:"visualizing-coutries-properties",content:"Right click 01. countries in the Workspace panel. Click Attributes->Table->Show in the popup menu. In the Settings Panel, find the Colors->Type option and select Graduated Color. In its sub-option Attribute, select POP_EST which is population property of countries. In the Setting Panel, find the Chart option and click the ... button. In the popup dialog, select pie in Chart Type option and select GDP_MD_EST in Attribute (Size) option and select EXPORT and IMPORT checkboxs in Fields option and click Okay button."},{header:"Editing Shapes",slug:"editing-shapes",content:"Select Action button at toolbar. Left click some country and right click it and select Edit Selected Shape in the popup menu. Then the shape will be in editing mode. You can change its polygon points and finish your editing by right click and select Edit Selected Shape again."}]},{path:"/docs/2.2_searching_for_countries.html",title:"2.2 寻找国家",pathLocale:"/",contents:[{header:"2.2 寻找国家",slug:"_2-2-寻找国家",content:"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed."},{header:"GIS Data Structure",slug:"gis-data-structure",content:"In MicroCity, GIS data consists of three types of Shapes: Point, Polyline and Polygon, each of which can be visualized as a Map Layer. In a layer, a Shape object consists of one or more Parts, and every Part consists of one or more Points. A Shape object is also associated to a record in the Attributes Table. You can also edit the shape or its attributes (see 3.2). If you want perform a complex editing or handle a batch of shapes, you can use MicroCity Script, in which many built-in functions can be used."},{header:"Making a Query",slug:"making-a-query",content:`Suppose we want to find countries, each of which has a population of more than 100 million and is entirely in the northern hemisphere. So we need to check every point's coordinate in each shape and the population attribute of the shape. Open ScriptEditor and type following codes: -local Countries = Open("countries.shp") --Try to open the shapes layer -for i = 1, GetRecCount(Countries) do --Loop all the shape objects in the layer local country = GetShape(Countries, i) --Get the shape object of a country local north = true --Assume the country is in the northern hemisphere for j = 1, GetPartCount(country) do --Loop all of the parts in the shape for k = 1, GetPointCount(country, j) do --Loop all of the points in the shape part local x, y = GetPointXY(country, k, j) --Get coordinate of the point j if y < 0 then --If the latitude is less than 0 north = false --The north assumption is false end end end local pop = GetValue(country, "POP_EST") --Get the population property local name = GetValue(country, "NAME") --Get the country name if pop > 100000000 and north then --Check the two conditions Print(name, ": ", pop/100000000) --Print out the result end -end`},{header:"Running the Script",slug:"running-the-script",content:"Save the script to query.mcs and open it with MicroCity or drag it to MicroCity. Then you will find a query item appears in Modules Tab in Workspace panel. Double click the sub-item main. If a dialog pops up, select 01. countries and click Okay. The results will be shown in Messages panel."}]},{path:"/docs/3.1_ui_overview.html",title:"3.1 用户界面概览",pathLocale:"/",contents:[{header:"3.1 用户界面概览",slug:"_3-1-用户界面概览",content:"MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules."},{header:"The Main Window and Components",slug:"the-main-window-and-components",content:""},{header:"Supported Files",slug:"supported-files",content:"MicroCity can open ArcGIS shapefile (*.shp), Grids file (*.sgrd), dBase file (*.dbf), Tabular text file (*.csv, *.txt), Point clouds (*.spc), Image file (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) and MicroCity 3D Scene (*.m3d). These data files are maintained in the Data Tab of the Workspace Panel. Module libraries (*.dll, *.mcs) are maintained and executed through the Modules Tab of the Workspace Panel."},{header:"Project Management",slug:"project-management",content:"The information of opened data files, module libraries, settings and sub-windows can be saved or opened in a MicroCity Project (*.mprj) through the menu File->Project. The mprj file does not contain any file's data. For easy maintenance, files in a project should be put into the same folder or sub-folders of the mprj file."}]},{path:"/docs/3.2_vector_shapes.html",title:"3.2 矢量图",pathLocale:"/",contents:[{header:"3.2 矢量图",slug:"_3-2-矢量图",content:"MicroCity can open, create and edit ArcGIS shapefiles (*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7) other vector file formats, such like Scalable Vector Graphics (*.svg) and AutoCAD Drawing Exchange Format (*.dxf), can also be imported or exported."},{header:"Opening, Creating, Saving and Closing Shapes",slug:"opening-creating-saving-and-closing-shapes",content:"Users can click Load button or File->Shapes->Load menu item to open an ArcGIS shapefile (*.shp) as a Shapes. Creating a new Shapes can be done from menu File->Shapes->New and the pop-up dialog as shown below. Users can choose one shapes type from Point, Line and Polygon. The relationship between a ArcGIS shapefile (*.shp) and a same named dBase file (*.dbf) is also shown. Saving a Shapes can be done from the right click context menu Save or Save As. You can also close a Shapes from the menu and get a prompt dialog to save it."},{header:"Showing and Editing Shapes",slug:"showing-and-editing-shapes",content:"Double click a Shapes from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle Action botton and right click a Shape in a Shapes layer and choose Edit Selected Shape then go to the Editing Mode. In this mode users can add/delete parts and add/delete points in a shape (for data structure of a shape see 2.2). The associated attributes table (*.dbf) of a Shapes can be accessed through right-clicking context menu Attributes->Table->Show (see the tutorial 2.1)."},{header:"Display Settings and Data Visualization",slug:"display-settings-and-data-visualization",content:"Users can change Shapes outline, fill, labels and other display settins from the Settings Panel. Some options can connect attribute data and give visualization functionalities (for example 2.1)."}]},{path:"/docs/3.3_raster_grids.html",title:"3.3 栅格图",pathLocale:"/",contents:[{header:"3.3 栅格图",slug:"_3-3-栅格图",content:"MicroCity can open, create and edit SAGA Grid (*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) can be opened as Grid as well. By using modules (see 3.7) other raster file formats, such like ESRI Arc/Info Grid (*.adf) and Surfer Grid (*.grd), can also be imported or exported."},{header:"Opening, Creating, Saving and Closing Grids",slug:"opening-creating-saving-and-closing-grids",content:`Users can click Load button or File->Grid->Load menu item to open a Grid. Creating new Grid can be done from menu File->Grid->New and the pop-up dialog: The above right figure is the data structure and definitions of a Grid. A Grid starts from its bottom left corner which has coordinate (xMin, yMin), contains NX*NY Square Cells. Each cell has its own Integer Coordinate (X, Y), in the range of (0, 0) to (XMax, YMax). -Saving Grid can be done from the right click context menu Save or Save As. You can also close a Grid from the menu and get a prompt dialog to save it.`},{header:"Showing and Editing Grids",slug:"showing-and-editing-grids",content:"Double click a Grid from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle Action botton and select a range of cells in a Grid. Then the value of these cells can be edited in the Attributes Tab of the Settings Panel."},{header:"Display Settings and 3D View",slug:"display-settings-and-3d-view",content:"Users can show cell values, change color and set transparency of a Grid by using Settings Panel. Using button can creat a 3D surface of a Grid in which cell values are translated to elevation (see 3.6)."}]},{path:"/docs/3.4_3d_scenes.html",title:"3.4 3D场景",pathLocale:"/",contents:[{header:"3.4 3D场景",slug:"_3-4-3d场景",content:"MicroCity 3D Scene (*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (*.3ds), Wavefront OBJ (*.obj) and Stereolithography (*.stl) can be loaded as objects in a scene (see below) but not be stored in the .m3d file."},{header:"Opening, Creating, Saving and Closing 3D Scenes",slug:"opening-creating-saving-and-closing-3d-scenes",content:"Users can click Load button or File->Scene->Load menu item to open a Scene. Creating new Scene can be done from menu File->Scene->New and fill the pop-up dialog as shown below. After pressing Okay button an item will appear in the Data Tab of the Workspace Panel. Then Scene can be saved or closed through right-click menu:"},{header:"Showing and Editing 3D Scenes",slug:"showing-and-editing-3d-scenes",content:"Double click a Scene from the Data tab will give you a scene view. Left-mouse-dragging in a scene veiw will rotate the camera and right-mouse-dragging will translate the camera. Double-left-clicking a scene view can select objects and Double-right-clicking a scene view can popup a context menu (shown below). One can add objects, load objects and set objects, etc.. Note that the Rotation in the coordinate system should obey Left-hand rule. The illustration of the coordinate system and an example of the rotation around y-axis is shown below: The coordinate used in the position and rotation of an object is relative to its parent object. By default, the parent of a new object is null."},{header:"Display Settings",slug:"display-settings",content:"Users can change the background color, reference grid or other display options of a Scene by using Settings Panel."}]},{path:"/docs/3.5_tables.html",title:"3.5 表格",pathLocale:"/",contents:[{header:"3.5 表格",slug:"_3-5-表格",content:"Tabular files including dBase files (*.dbf), Text file (*.txt) and Comma Separated Values (*.csv) can be opened as Table and saved with MicroCity."},{header:"Opening, Creating, Saving and Closing Tables",slug:"opening-creating-saving-and-closing-tables",content:"Users can click Load button or File->Table->Load menu item to open a tabular file. Creating a new Table can be done from menu File->Table->New and the pop-up dialog as shown below. Saving a Table can be done from the right click context menu Save or Save As."},{header:"Showing and Editing Tables",slug:"showing-and-editing-tables",content:`Double click a Table from the Data Tab will give you a table view. Altering a table's stucture can be done by right click the table's head. If you click "Add Field" then, a dialog which guide you (as shown below). If you want insert a record to the table, you can right click the left numbers of the table and select a context menu item.`}]},{path:"/docs/3.6_maps_and_layers.html",title:"3.6 地图和图层",pathLocale:"/",contents:[{header:"3.6 地图和图层",slug:"_3-6-地图和图层",content:"In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid."},{header:"Opening, Creating, Saving, Printing and Closing Maps",slug:"opening-creating-saving-printing-and-closing-maps",content:"Because Maps are based on Shapes and Grids, they can not be saved or opened independently, but can be saved or opened along with a MicroCity Project (*.mprj). Creating a Map is by double clicking a Shapes or Grid from the Data Tab of the Workspace Panel. A Map window contains four coordinate bars which can be used to locate objects (see below). A Map can also be printed or closed from the context menu of the Maps Tab of the Workspace Panel."},{header:"Adding, Moving, Hiding and Closing Layers in a Map",slug:"adding-moving-hiding-and-closing-layers-in-a-map",content:"A Map can have multiple Layers, each of them represents a data item. One can add a Layer to a Map by double clicking a Shapes or a Grid from the Data Tab. A lower layer can be obscured by upper layers. One can move a layer by dragging, hide a layer by double clicking and close a layer through the menu (as shown below)."},{header:"Controlling Map Views",slug:"controlling-map-views",content:`When a data item or a layer is selected, this layer is called the active layer. One can toggle the Action button to select and edit an object in the active layer. By toggling the Zoom or Pan botton, the map can zoomed in, zoomed out or panned. If one lose in a map, he can use the Zoom to Full Extent button to get a full view of the map. Other zoom controlling buttons can be used to facilitate the map browsing. -The Synchronise button can be used if you want compare difference between two or more maps. The Ruler button can be used to meassure distances. Note that, by default, the unit of the distances measured is kilometer under the coordinate system of Earth. One can change the coordinate system to Non-Earth from the Settings Panel of the Map, and get Cartesian distance without unit. -One can create a 3D surface map by clicking 3D button, which need a appropriately sized Grid (see 3.3).`}]},{path:"/docs/3.7_modules.html",title:"3.7 拓展模块",pathLocale:"/",contents:[{header:"3.7 拓展模块",slug:"_3-7-拓展模块",content:"The functionality of MicroCity can be extended by modules, one type of which is SAGA Module (*.dll). SAGA Modules contains many useful libraries for Shapes and Grids. Another type of Module is MicroCity Script (*.mcs), which can be edited and debugged with ScriptEditor (see 4.1)."},{header:"Loading, Closing and Executing Modules",slug:"loading-closing-and-executing-modules",content:"Modules can be loaded to MicroCity by clicking Load button or Modules->Load Module Library menu item. The Modules Tab of the Workspace Panel will display the loaded Libraries (each of which corresponding to a file) and their inside Modules . One can close or reload a Module Library from the context menu. Executing a moule has many ways: double clicking it, clicking the Execute button from the Settings Panel, or click the Execute context menu item. One can also Debug a MicroCity Script module by clicking the Debug context menu item, that needs the ScriptEditor running in the background. MicroCity can also capture runtime errors and pause the execution of modules."},{header:"Accelerating, Stopping the Execution of a Module",slug:"accelerating-stopping-the-execution-of-a-module",content:`MicroCity Script module is created with Lua language which is very fast. In some cases, if you want much more faster execution speed, you can click the Module Libraries in the Modules Tab of the Workspace Panel and switch the Script Running Mode in the Settings Panel from the Safe Mode to the Fast Mode. Then MicroCity will use LuaJIT to execute modules. -If a module is being executed, one can stop it by click the Execute button in the corresponding Settings. In Safe Mode the execution can be immediately stopped, but in Fast Mode the stopping is depend on the GetReady() function called in the script (see 4.2.`}]},{path:"/docs/4.1_si_overview.html",title:"4.1 脚本概览",pathLocale:"/",contents:[{header:"4.1 脚本概览",slug:"_4-1-脚本概览",content:"MicroCity uses Modules (see 3.7) to extend its functionalities. One type of the modules is MicroCity Script (*.mcs) which can be edited and debugged in the ScriptEditor."},{header:"The Script Editor",slug:"the-script-editor",content:""},{header:"Coding and Debugging MicroCity Scripts",slug:"coding-and-debugging-microcity-scripts",content:"ScriptEditor is based on ZeroBrane. One can find detailed information there. For debugging, you should keep Script Editor being opened. Then right click the module from MicroCity and choose Debug item in the context menu (see 3.7). The execution can be indicated in the Code View of ScriptEditor. You can control the execution and watch variables with Debug Buttons."},{header:"The Lua Language and Embedded Functions",slug:"the-lua-language-and-embedded-functions",content:`MicroCity uses Lua 5.1 as its script language. One can find the reference manual there. MicroCity embeds many useful funtions in Lua, which can not only control user interfaces, manipulate data, but also can solve mathematical models and sun simulations. You should read following chapters for more information. -Conventions in this reference: -There are four major data types in Lua can be passed though embedded functions as parameters, namely Number, Boolean, String and Object. The type Object includes builtin Lua objects, such as Table, Function adn Thread..., as well as MicroCity objects, such as Shapes, Grid, Table and Scene.... To clarify the parameter type in embedded functions, we use capitalization, quotation mark and semantic information to avoid ambiguities in function descriptions. A lowercase word of a paramter means a Number. Sometimes, to present an integer parameter, a letter 'i' followed by a word is used, like iField. Starting with the letter 'b' and followed by a word means a Boolean, like bShow. A quoted word means a String. A capitalized word means an Object or a keyword. Following is an example of a embedded function description. -AddParameter (Module, ParentNode, "Value", "id" [, default = 0]) -In this case, the Module parameter should be a Module object. The ParentNode parameter should be a Node object, but it act as a parent Node. The "Value" parameter is a string, but it represent the builtin type Value in MicroCity, so this string can not be changed. The "id" parameter should be a user specified string. The default parameter is a number. The contents in a pair of '[' and ']' are optional. The character '|' among parameters means "or". -Encoding formats: -MicroCity uses ANSI encoding format to read and write data, such as shp, txt, csv and dbf. ScriptEditor and the embedded funtions use UTF-8 encoding format to read and write data, such as txt or csv.`}]},{path:"/docs/4.2_ui_control.html",title:"4.2 控制用户界面",pathLocale:"/",contents:[{header:"4.2 控制用户界面",slug:"_4-2-控制用户界面",content:'Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be found in the "user_interface" folder of the Project Tab in ScriptEditor.'},{header:"Basic User Interfaces",slug:"basic-user-interfaces",content:`Print ("hello" [,...]) -Prints values in the Messages Panel. -Note ("hello" [,...]) -Notifies users and pauses the execution. -SetProcessText ("processing") -Sets a text at the bottom left corner of MicroCity. -SetProgress (position, range) -Sets the progress bar of position/range that locates at the bottom right conner of MicroCity. -Sleep (milliseconds) -Pauses the execution for milliseconds. -GetReady () -MicroCity shares the same thread with the lua engine. Heavy calculations in lua will block the MicroCity interface. Use this function inside can let the MicroCity interface respond to user operations. Returns false if user cancel the current execution. -GetClickXY () -Returns x,y where a user clicked at a Map View. -GetDragExtent () -Returns bottom-left and top-right corner coordinate: Lx, By, Rx, Ty, which a user used mouse to drag a rectangle in a Map View.`},{header:"Data Objects",slug:"data-objects",content:`PATH -Internal global variable that holds a string of current working directory, such as "c:\\microcity". -Open (".\\\\shapes.shp" [, ".\\\\grid.sgrd" [, ".\\\\table.dbf" [, ".\\\\scene.m3d" , ...]]]) -Opens and returns Shapes, Table, Grid and Scene object from current working directory or opened data. -Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel) -Closes an opened or created Shapes, Table, Grid, Scene, Network, RndEngine or LPModel object. -Update (Shapes|Grid|Table [, bShow = ture]) -Update current changes of Shapes, Grid or Table object in MicroCity. The bShow indicates whether to create a view of the object. Returns false if user cancel the current execution. -CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...]) -Creates a Map View to show objects which can be arranged in layers by their order in the parameters.`},{header:"Modules and Parameters",slug:"modules-and-parameters",content:`AddModule ("Function" [, "name"]) This function can add a lua function as a module to current module library. The module's default name is the function's name. Returns a Module object. -AddParameter (Module, ParentNode, "Node", "id") -AddParameter (Module, ParentNode, "Value", "id" [, default = 0]) -AddParameter (Module, ParentNode, "Range", "id" [, low = 0 [, high = 1]]) -AddParameter (Module, ParentNode, "Check", "id" [, default = 0]) -AddParameter (Module, ParentNode, "String", "id" [, "string" = "") -AddParameter (Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]]) -AddParameter (Module, ParentNode, "File", "id" [, "c:\\\\default.txt" = ""]) -AddParameter (Module, ParentNode, "Color", "id" [, "color" = "255 255 255") -AddParameter (Module, ParentNode, "Shapes", "id") -AddParameter (Module, ParentNode, "Grid", "id") -AddParameter (Module, ParentNode, "Scene", "id") -AddParameter (Module, ParentNode, "Table", "id") -AddParameter (Module, ParentNode, "Field", "id") -These functions can add a parameter to a module's settings panel. Returns corresponding values or an object. The ParentNode can be set to the first return of a AddParameter function. If "Field" is set at the third place, the parent_node can be set to a Table or Shapes object to get its attributes table's head. -GetParameter (Shapes|Table|Grid|Scene|Module, "id") -Returns the parameter specified by "id" from the object's settings panel. -SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object) -Sets the parameter specified by "id" in the object's settings panel. Returns true if succeed. Note that the choice parameter should start from 1. A parameter's "id" can be found in the parameter's helper text shown as below.`}]},{path:"/docs/4.3_shapes_and_tables.html",title:"4.3 矢量图形和表格",pathLocale:"/",contents:[{header:"4.3 矢量图形和表格",slug:"_4-3-矢量图形和表格",content:'Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 and 3.2. Because Shapes can be treated as Tables with extra field with geographic data, some of embeded functions for tabular data manipulation can be used both in Shapes and Tables. Sample codes for this chapter can be found in the "shapes_samples" folder of the Project Tab in ScriptEditor.'},{header:"Tabular Data Manipulation",slug:"tabular-data-manipulation",content:`CreateShapes ("name", "Point|Line|Polygon") -Returns a Shapes object. -CreateTable ("Name") -Returns a Table object. -GetFieldCount (Shapes|Table) -Returns the number of fields in a Shapes or Table -GetField (Shapes|Table, iField) -Inputs the index (starts from 1) of a field and returns the field name and type ("Int", "Float", "Double" or "String). -AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...]) -Adds fields to a *Table or Shapes and returns booleans (true or false) by order. -DelField (Shapes|Table, iField) -Returns true if successfully delete a field. -GetRecCount (Shapes|Table) -Returns the total number of records in a Shapes or Table. -AddRecord (Shapes|Table) -Adds a record to a Shapes or Table and returns the index. -GetValue (Shapes|Table, "field_name", index1 [, index2, ...]) -Retrieve values from a specified field and indexes of a Shapes or Table. Returns multiple values by the order of indexes. -SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...]) -Sets values for a specified field and indexes of a Shapes or Table.`},{header:"Geographic Data Manipulation",slug:"geographic-data-manipulation",content:`GetSelections (Shapes) -Returns selected shape objects from a Shapes. -GetShape (Shapes, index1 [, index2, ...]) -Returns Shape objects from a Shapes by the order of indexes. -AddShape (Shapes, Shape) -Adds a Shape object to a Shapes and returns its index. -AddShape (Shapes [, x1, y1, x2, y2, ...]) -Adds a Shape object to a Shapes which defined as points. Returns the Shape object and index. -DelShape (Shape|Shapes) -Deletes a Shape or Shapes object and returns ture if successful. -AddPoint (Shape, x, y [, iPart = 1]) -Adds a point to a Shape and returns ture if successful. -InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]]) -Inserts a point to a Shape and returns ture if successful. -SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]]) -Sets a point coordinates in a Shape and returns ture if successful. -DelPoint (Shape, iPoint [, iPart=1]) -Deletes a point at position iPoint from a Shape and returns ture if successful.. -DelPart (Shape, iPart) -Deletes a part from a Shape and returns ture if successful. -GetPartCount (Shape) -Returns the number of parts in a Shape. -GetPointCount (Shape [, iPart]) -Returns the number of points in a Shape. -GetPointXY (Shape [, iPoint [, iPart = 1]]) -Returns all points' coordinates: x1, y1, x2, y2, ... from a Shape or a specified point's coordinate. -CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...]) -Copys Shape objects to a target Shapes with relative translation (dx, dy) and returns new Shape objects. -MoveShapeTo (dx, dy, Shape1 [, Shape2, ...]) -Translates Shape objects to its relative position (dx, dy). -GetCenterXY (Shapes) -Returns the center coordinate (x, y) of a Shapes. -GetCenterXY (Shapes, index1 [, index2, ...]) -Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects specified by indexes in a Shapes. -GetCenterXY (Shape1 [, Shape2, ...]) -Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects. -GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) -Returns the total distance between every two pairs of coordinates (x, y). -GetShapeLen (Shape1 [, Shape2, ...]) -Returns lengths of Shape objects. -GetShapeArea (Shape1 [, Shape2, ...]) -Returns areas of Shape objects. -GetShapeType (Shape|Shapes) -Returns the type ("Point", "Line" or "Polygon") of the a Shapes or Shape object. -GetExtent (Shapes) -Returns the extent coordinates (Lx, By, Rx, Ty) of a Shapes's extent. -GetExtent (Shapes, index) -Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape indexed in a Shapes. -GetExtent (Shape) -Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape. -GetIntersection (ShapeA, ShapeB) -Returns a Shape (Point, Line or Polygon) object of the intersection of two Shapes. -GetValue (Shape, "field_name") -Returns the value of specified field of a Shape. -SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...]) -Sets values in different fiedds for a Shape. -SetCoorSys ("Earth"|"Non-Earth") -Sets coordinate system. If using "Earth", distances, lenths and areas are calculated according to the earth ellipsoid coordinate system. By default the "Non-Earth" is used, which is cartesian coordinate system.`}]},{path:"/docs/4.4_grids.html",title:"4.4 栅格图形",pathLocale:"/",contents:[{header:"4.4 栅格图形",slug:"_4-4-栅格图形",content:'Grids in MicroCity have simple structure (3.3) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be found in the "grid_samples" folder of the Project Tab in ScriptEditor.'},{header:"Cellular Data Manipulation",slug:"cellular-data-manipulation",content:`CreateGrid ("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]]) -Returns a Grid object. -GetCellSize (Grid) -Returns the Cellsize value of a Grid. -GetGridMaxXY (Grid) -Returns XMax, YMax of a Grid. -ConvertToGridXY (Grid, x1, y1 [, x2, y2, ...]) -Converts real coordinates to coordinates in a Grid. Returns X1, Y1, X2, Y2, ... . -ShapeToGrid (Grid, Shape, value) -Rasterizes a Shape in a Grid. The cell values will be set according to the covering area and the inputed value. -ShapeToGrid (Grid, Shapes, "field_name") -Rasterizes all Shape objects in a Shapes. The cell values will be set according to the covering area and the values of Shapes field. -GetValue (Grid, X1, Y1 [, X2, Y2, ...]) -Returns cells' (specified by Grid coordinates) values: value1, value2, ... . -SetValue (Grid, value, X1, Y1 [, X2, Y2, ...]) -Sets values for cells specified by Grid coordinates. -GetCenterXY (Grid) -Returns the center real coordinate (x, y) of a Grid. -GetCenterXY (Grid, X1, Y1 [, X2, Y2, ...]) -Returns the real coordinates of cells' centers: x1, y1, x2, y2, ... . -GetExtent (Grid) -Returns the leftbottom and righttop corner of a Grid's extent: Lx, By, Rx, Ty. -GetExtent (Grid, X, Y) -Returns the leftbottom and righttop corner of a cell's extent: Lx, By, Rx, Ty. -GetFractalDim (Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0]) -Calculates fractal dimension of the specified area in a Grid. Returns dimension, RSQ of linear regression, and the number of boxes in every fold.`}]},{path:"/docs/4.5_3d_scenes.html",title:"4.5 3D场景",pathLocale:"/",contents:[{header:"4.5 3D场景",slug:"_4-5-3d场景",content:'Scenes and inside 3D objects (3.4) can be scripted. Sample codes for this chapter can be found in the "3d_samples" folder of the Project Tab in ScriptEditor.'},{header:"3D Scene and Object Manipulation",slug:"_3d-scene-and-object-manipulation",content:`CreateScene ("Title" [, RotSpeed=1] [, TransSpeed=1]) -Creates a new 3d scene and returns the object. -AddZipTo3DPath (Scene, "filename.zip") -Adds a zip file to the search directory and returns true if succeed. It is useful for collecting a large amount of files. -LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg") -Loads six image files as the skybox of a 3d scene. -LoadObject (Scene, "filename.3ds" [,shadow = false [, AnimationSpeed]]) -Loads a 3d object from a file and returns the object. -AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255]) -Adds a light object and returns the object. -Add3DLabel(Scene, "label" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]]) -Adds a 3D label at (0,0,0) and returns the object. -Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0]) -Adds a 3D line object frome (x1, y1, z1) to (x2, y2, z2) and retruns the object. -Add3DRect (Scene, length, width [, r = 180, g = 180, b = 180]) -Adds a 3D rectangular object from (-length/2,0,-width/2) to (length/2,0,width/2) and returns the object. -Add3DBox (Scene, length, width, height [, r = 180, g = 180, b = 180 [, bShowEdge = true]]) -Adds a 3D box object from (-length/2,-height/2,-width/2) to (length/2,height/2,width/2) and returns the object. -AddSphere (Scene, radius [, polycount = 16 [, r = 180, g = 180, b = 180]]) -Adds a sphere at (0,0,0) and returns the object. If the radius parameter is less than 0, returns an invisible object. -GetTexture (Object) -Returns the texture files of a object: "filename1", "filename2", ... . -LoadTexture (Scene, Object, "filename1" [, "filename2", ...]) -Loads texture files to an object. -SetPosition (Object, x, y, z [, absolute = false]) -Sets the position of an object relative to its parent (or the absolute position to the scene). -GetPosition (Object [, absolute = false]) -Gets the position of an object relative to its parent (or the absolute position to the scene). -SetRotation (Object, rx, ry, rz [, absolute = false]) -Sets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene). -GetRotation (Object [, absolute = false]) -Gets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene). -SetScale (Object, sx, sy, sz) -Sets the scale of an object. -GetScale (Object) -Gets the scale of an object. -SetParent (Object, Parent) -Attaches an object to another object as a child. -GetParent (Object) -Gets the parent of an object. -SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]]) -Sets the ID, position, rotation and scale of an object. -DelObject (Object) -Deletes an object. -SetCamera (Scene, x, y, z [,Tx, Ty, Tz]) -Sets the position and target of the scene camera. -GetCamera (Scene) -Gets the camera object of a 3d scene and its position and targt. -GetSelections (Scene) -Returns selected objects from a 3d scene. -GetObjectID (Object1 [, Object2, ...]) -Returns "id"s of objects. -SetObjectID (Object, "id") -Sets the id of an object. -GetObject (Scene, "id") -Finds an object by its id.`}]},{path:"/docs/4.6_networks.html",title:"4.6 网络",pathLocale:"/",contents:[{header:"4.6 网络",slug:"_4-6-网络",content:'GIS vector data (3.2) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sample codes for this chapter can be found in the "network_samples" folder of the Project Tab in ScriptEditor.'},{header:"Network Manipulation",slug:"network-manipulation",content:`CreateNetwork () -Creates an empty network and returns the object. -CreateNetwork (UnTopoLines) -Creates a network from an untopologized "line" Shapes and returns three objects: Network, Nodes (Shapes) and Links (Shapes). -CreateNetwork (Nodes, Links) -Creates a Network object from topologized Nodes and Links Shapes. Returns the Network object. -InitNetwork (Network, Nodes, Links) -Initiates a Network from a Nodes and a Links Shapes. Returns true if succeed. -AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]]) -Adds a new link or update an existing link in the Network. Returns linkID, oID, dID, true/false for adding and true/false for updating. -AddLink (Network, Shapes|Table, index1 [, index2, ...]) -Adds or updates links from the recordset of a Shapes or Table. Returns boolean values. -DelLink (Network, linkID) -Deletes a link from a Network. Returns a boolean value. -GetNearNodeID (Network, x, y [, radius=nil]) -Gets the nearest Network nodes from a coordinate. Returns node ids. -GetNodeXY (Network, nodeID1 [, nodeID2, ...]) -Returns the coordinates of nodes in a Network: x1, y1, x2, y2, ... .`},{header:"Algorithms",slug:"algorithms",content:`GenSTPTree (Network, startID [, endID]) -Generates a Shortest Path Spanning Tree from a node. Returns a boolean value. -GetSTPPath (Network, endID, "NodeID"|"LinkID") -After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link id sequence: id1, id2 ,... . -GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp") -After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shapes index sequence. -GetSTPPath (Network, endID, "NodeShp"|"LinkShp") -After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shape object sequence. -GetSTPLen (Network, endID) -After calling GenSTPTree call this function. Returns a Shortest Path Distance to a end node. -GetSTPLen (Network, startID, endID) -Gets a Shortest Path from a start node to an end node in a Network. Returns the distance. -GetSTPLen (Network, x1, y1, x2, y2) -Gets a Shortest Path from a start coordinate to an end coordinate in a Network. Returns the distance. -SetTrip (Network, oID, dID, amount) -Sets an amount of a trip from an origin to an destination. -SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]]) -After calling SetTrip call this function. Performs the User Equilibium Traffic Assignment and returns a boolean value. -GetFlow (Network, linkID) -Returns the traffic flow of a specified link. -SetFlow (Network, linkID, flow) -Set the traffic flow of a specified link and return a boolean value.`}]},{path:"/docs/4.7_des_simulations.html",title:"4.7 离散事件模拟",pathLocale:"/",contents:[{header:"4.7 离散事件模拟",slug:"_4-7-离散事件模拟",content:'MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, which is very useful for dynamic system analysis. Sample codes for this chapter can be found in the "simulation_samples" folder of the Project Tab in ScriptEditor.'},{header:"Random Number Generation",slug:"random-number-generation",content:`CreateRandEng (seed, "uniform_01") -Creates a binary distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "uniform_real" [, min = 0, max = 1]) -Creates a uniform distributed real random generation engine from a seed and returns the object. -CreateRandEng (seed, "uniform_int" [, min = 0, max = 1]) -Creates an uniform integer random generation engine from a seed and returns the object. -CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2]) -Creates a triangle distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "bernoulli" [, p = 0]) -Creates a bernoulli distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1]) -Creates a cauchy distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "exponential" [, lambda = 1]) -Creates a exponential distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "geometric" [, p = 0]) -Creates a geometric distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "normal" [, mean = 0, sigma = 1]) -Creates a normal distributed random generation engine from a seed and returns the object. -CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1]) -Creates a lognormal distributed random generation engine from a seed and returns the object. -GetNextRandom (Engine) -Gets a random number from a random generation engine.`},{header:"Simulation Control",slug:"simulation-control",content:`CreateEvent (time, Funcion [, arg1, arg2, ...]) -Creates a future event from a Lua Function or a Lua Coroutine. Returns a Coroutine object. -ExecAllEvents () -Calls this at last. It will execute all events as Lua Coroutines. -Delay ([relativeTime = 0]) -Calls this function in a Lua Coroutine will let it first yield then resume it after the specified relative time. If the parameter relativeTime is not set, the current Coroutine will yield and won' be resumed automatically. -Resume ([time, ] Coroutine [, arg1, arg2, ...]) -Resumes a yielded coroutine immediately or at a specified time. -GetSimTime () -Returns the current simulation time.`}]},{path:"/docs/4.8_mixed_integer_programming.html",title:"4.8 混合整数线性规划",pathLocale:"/",contents:[{header:"4.8 混合整数线性规划",slug:"_4-8-混合整数线性规划",content:'MicroCity employs the lpsolve to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build and solve models. Sample codes for this chapter can be found in the "optimization_samples" folder of the Project Tab in ScriptEditor.'},{header:"Model Creation and Execution",slug:"model-creation-and-execution",content:`CreateLP ([rows = 0 , columns = 0]) -Creates a Mixed Integer Linear Programming model and returns the LPModel object. -SetObjFunction (LPModel, rowTable, "MAX"|"MIN") -Sets the objective function of a LPModel with a Lua Table which stores coefficients of the decision variables. -AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue) -Adds a constraint to a LPModel with a Lua Table which stores coefficients of the decision variables. -SetInteger (LPModel, index) -Sets a decision variable specified by the index as an integer variable. -SetBinary (LPModel, index) -Sets a decision variable of a LPModel specified by the index as a binary variable. -SetUnbounded (LPModel, index) -Sets a decision variable of a LPModel to be unbounded(+/- infinity). -SolveLP (LPModel [, timeoutSec = 60]) -Solves a LPModel and returns 0 as success, -1 as invalid LP model, -2 as nomemory, 1 as suboptimal, 2 as infeasible, 3 as unbounded, 4 as degenerate, 5 as a numerical failure encountered, 6 as the user abort, 7 as a timeout error, 9 as the model could be solved by presolve, 10 as the B&B routine failed, 11 as the B&B was stopped because of a break-at-first, 12 as a feasible B&B solution was found, 13 as no feasible B&B solution found. -GetObjective (LPModel) -Returns the objective function value of a LPModel. -GetVariable (LPModel, index) -Returns the value of a decision variable specified by the index. -GetVariables (LPModel) -Returns all values of the decision variables of a LPModel. -GetDual (LPModel, index) -Returns the dual value of a decision variable specified by the index. -GetDuals (LPModel) -Returns all dual values of the decision variables of a LPModel. -ReadLP("fileName.mps") -Reads a LPModel from a file (*.lp, *.mps) and returns the LPModel if succeed. -WriteLP (LPModel, "fileName.mps") -Writes a LPModel to a file (*.lp, *.mps) and returns true if succeed.`}]},{path:"/docs/",title:"MicroCity文档",pathLocale:"/",contents:[{header:"MicroCity文档",slug:"microcity文档",content:""},{header:"目录",slug:"目录",content:`1 Introduction 介绍 1.1 What MicroCity can Do MicroCity能干什么 2 Getting Started 开始使用 2.1 Showing a World Map 展示世界地图 -2.2 Searching for Countries 寻找国家 3 User Interfaces 用户界面 3.1 UI Overview 用户界面概览 -3.2 Vector Shapes 矢量图 -3.3 Raster Grids 栅格图 -3.4 3D Scenes 3D场景 -3.5 Tables 表格 -3.6 Maps and Layers 地图和图层 -3.7 Modules 拓展模块 4 Scripting Interfaces 脚本接口 4.1 SI Overview 脚本概览 -4.2 UI Control 控制用户界面 -4.3 Shapes and Tables 矢量图形和表格 -4.4 Grids 栅格图形 -4.5 3D Scenes 3D场景 -4.6 Networks 网络 -4.7 Discrete Event Simulations 离散事件模拟 -4.8 Mixed Integer Programming 混合整数线性规划 声明:本网站文档部分内容来自microcity.github.io,版权归原作者所有。`}]},{path:"/notes/3d-objects-en.html",title:"3D Objects",pathLocale:"/",contents:[{header:"3D Objects",slug:"_3d-objects",content:"This section will introduce the objects and their control functions in a 3D scene."},{header:"Adding Objects",slug:"adding-objects",content:`To add objects to the scene, use the following function: -local obj = scene.addobj([type], {key1 = value1, key2 = value2, ...})`},{header:"Optional Object Properties",slug:"optional-object-properties",content:`Objects added to the scene typically support setting some of the following properties: Object Property -Meaning color -The color of the object. The format of the color can support built-in colors, hexadecimal, and RGB. Same as the background color of the scene opacity -Opacity hcolor -The color when the object is selected size -The size of the object. The default value is 1 length -The length of the object, commonly used for box width -The width of the object, commonly used for box height -The height of the object, commonly used for box radius -The size of the object's rounded corners segments -The number of segments, usually used to set the precision of the sphere drawn selectable -Whether the object can be selected name -The name of the object text -The text value of the object font -The font of the text vertices -The set of points that make up the corresponding object The following are the types of objects that can be added to the scene:`},{header:"Object Types",slug:"object-types",content:""},{header:"List of Object Types",slug:"list-of-object-types",content:`label: Text label -points: Set of points -polyline: Set of line segments -box: Cube -sphere: Sphere -polygon: Polygon -light: Light source -mesh: Face made up of points For the sake of brevity, the key properties of the optional objects shown in the example below only display the relevant attributes of the object. Other common properties can be added by referring to the Optional Object Properties.`},{header:"label",slug:"label",content:`label is a text label. The text of the label can be set in the text attribute. -local obj = scene.addobj('label', {text = "Hello World!"})`},{header:"points",slug:"points",content:`points is a collection of points. You can create a single point or multiple points. Each point has three-dimensional coordinates to determine its position in three-dimensional space. The number of points is determined by the vertices attribute. -Here is an example of creating a points object: --- create a point at position (5,5,5) -scene.addobj("points", {vertices = {5,5,5}, size = 5}) -- create two points, the first at (0,0,0), the second at (5,5,5) -scene.addobj("points", {vertices = {0,0,0, 5,5,5}, size = 5})`},{header:"polyline",slug:"polyline",content:`polyline is a collection of line segments. When multiple points are input in the vertices attribute, line segments will be generated based on the order of the coordinates. -Therefore, although the same coordinates are used in the two examples below, the results are different because the order of the input coordinates is different. -scene.addobj("polyline", {vertices = {0,0,0, 4,6,7, -2,3,5}}) -scene.addobj("polyline", {vertices = {0,0,0, -2,3,5, 4,6,7}}) polyline point order comparison polyline does not have a size attribute.`},{header:"box",slug:"box",content:`box is a cuboid. Its shape can be modified mainly through the length, width, and height attributes. -local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) -Important optional properties of the box object: Property -Meaning length -The length of the cuboid width -The width of the cuboid height -The height of the cuboid Based on the above three attributes, we can modify the shape of the rotating box in the default sample code. --- Add the length, width, and height attributes (default to 1 if not added) -local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) local x = 1 -local y = 1 -local z = 0 -while scene.render() do x = x + 0.1 y = y + 0.1 obj:setrot(x, y, z) -end Boxes with different lengths, widths, and heights.`},{header:"sphere",slug:"sphere",content:`sphere is used to create a sphere object. Its size can be modified by the radius attribute, and its model quality can be set by setting the segments attribute. Refer to the example of the Earth in the built-in samples for more details. -local obj = scene.addobj('sphere', {radius=15, segments=360}) -Optional attributes for sphere objects: Attribute -Meaning radius -The radius of the sphere. It can be used to control the size of the sphere. segments -The number of rendered surfaces of the sphere. The higher the value, the more detailed the sphere model will be. The impact of different segments on the same sphere`},{header:"polygon",slug:"polygon",content:`polygon is used to create a polygon object, mainly set through the vertices attribute. -local obj = scene.addobj("polygon", {vertices = {-1,-1,0, -1,1,-0, 1,1,0, 1,-1,0}}) Because the polygon in this example is a square, it looks no different from the box introduced above. However, when the shape is set to other types of polygons (such as triangles, pentagons, etc.), the meaning of the polygon can be reflected. Attribute -Meaning -Explanation vertices -The vertices of the polygon -You can set the three-dimensional coordinates of each point in turn in the vertices attribute. The third dimension coordinates do not have an impact but play a placeholder role. size -Volume -Since the third dimension coordinates do not have an impact, and the area is already determined by the vertices of the polygon, the size attribute controls the volume by controlling the third dimension coordinate values of each point. The impact of different size on the same polygon volume`},{header:"External model",slug:"external-model",content:`Reference external files. However, for MicroCityWeb, only the built-in files on the website can be referenced at present. -For example, in the built-in example, a box-type truck is generated in the view by referencing the internal file: -local obj = scene.addobj('/res/2axle.glb') -You can also reference an external model by referencing the URL of the file: -local obj = scene.addobj('https://microcityweb.gitee.io/res/agv.glb') If you have 3D model resources at hand, you can view them in 3D Viewer and export them as .glb models through this website.`},{header:"Light",slug:"light",content:"Set the direction of the light, and the optional parameter vertices is a three-dimensional vector that represents the direction of the light. Since a strong light source has already been set in the MicroCityWeb scene, this will not be discussed in detail here."},{header:"Mesh",slug:"mesh",content:"A face composed of multiple points, commonly found in referenced external models. Due to its limited application, it will not be introduced here."},{header:"Object Control Functions",slug:"object-control-functions",content:"Assuming the 3D object to be manipulated is obj."},{header:"getpos()",slug:"getpos",content:`Gets the position coordinates (x, y, z) of obj. -local x, y, z = obj:getpos()`},{header:"setpos()",slug:"setpos",content:`Sets the position coordinates of obj to (x, y, z). -obj:setpos(x, y, z)`},{header:"getrot()",slug:"getrot",content:`Gets the rotation angles (rx, ry, rz) of obj in the x, y, and z directions. -local rx, ry, rz = obj:getrot()`},{header:"setrot()",slug:"setrot",content:`Sets the rotation angles of obj in the x, y, and z directions to (rx, ry, rz). -obj:setrot(rx, ry, rz)`},{header:"getscale()",slug:"getscale",content:`Gets the scaling ratios (sx, sy, sz) of obj in the x, y, and z directions. -local sx, sy, sz = obj:getscale()`},{header:"setscale()",slug:"setscale",content:`Sets the scaling ratios of obj in the x, y, and z directions to (sx, sy, sz). -obj:setscale(sx, sy, sz)`},{header:"getchildren()",slug:"getchildren",content:`Gets the table of child objects of obj. -local children = obj:getchildren()`},{header:"setchildren()",slug:"setchildren",content:`Sets the table of child objects of obj to children_table. -obj:setchildren(children_table)`},{header:"getparent()",slug:"getparent",content:`Gets the parent object of obj. -local num = obj:getparent()`},{header:"setparent()",slug:"setparent",content:`Sets the parent object of obj to obj0. -obj:setparent(obj0)`},{header:"delete()",slug:"delete",content:`Delete obj. -obj:delete()`}]},{path:"/notes/3d-objects.html",title:"3D 对象",pathLocale:"/",contents:[{header:"3D 对象",slug:"_3d-对象",content:"本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。"},{header:"添加对象",slug:"添加对象",content:`向场景中添加对象,函数形式如下 -local obj = scene.addobj([类型], {key1 = value1, key2 = value2, ...})`},{header:"对象可选属性列表",slug:"对象可选属性列表",content:`添加到场景中的对象通常支持设置以下属性中的某些属性 对象属性 -含义 color -对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 的设置相同 opacity -透明度 hcolor -选中时的颜色 size -对象的大小,默认值为1 length -对象的长度,常用于 box(立方体) width -对象的宽度,常用于 box(立方体) height -对象的高度,常用于 box(立方体) radius -对象圆角大小 segments -份数,通常用于设置 sphere(球体) 绘制的精度 selectable -是否可被选中 name -对象名称 text -对象文本值 font -文本字体 vertices -构成对应对象的点集合 支持添加到场景中的类型如下`},{header:"对象类型",slug:"对象类型",content:""},{header:"对象类型列表",slug:"对象类型列表",content:`label:文本标签 -points:点集合 -polyline:线段集合 -box:立方体 -sphere:球体 -polygon:多边形 -light:光源 -mesh:点构成的面 注释 -为了简洁起见,下方示例的对象可选属性中只展示对应对象的关键属性。其他通用的属性可以参考 对象可选属性列表 自行添加。`},{header:"label",slug:"label",content:`label 是文本标签。可以在 text 属性中设置label的文本。 -local obj = scene.addobj('label', {text = "Hello World!"})`},{header:"points",slug:"points",content:`points 是点集合。可以只创建单个点,也可以创建多个点。每个点都有三个维度的坐标以确定其在三维空间中的位置。点的个数通过 vertices 属性确定。 -下面是一个创建 points 点集对象的示例 --- 在坐标为(5,5,5)的位置创建一个点 -scene.addobj("points", {vertices = {5,5,5}, size = 5}) -- 第一个点的坐标为(0,0,0),第二个点的坐标为(5,5,5) -scene.addobj("points", {vertices = {0,0,0, 5,5,5}, size = 5})`},{header:"polyline",slug:"polyline",content:`polyline 是线段集合。当在vertices属性中输入多个点的坐标时,将会依次根据点坐标连线,得到线段集合。 -因此,虽然下面两个例子中使用了相同的点坐标,但是由于点坐标输入顺序不同,得到的结果也不同。 -scene.addobj("polyline", {vertices = {0,0,0, 4,6,7, -2,3,5}}) -scene.addobj("polyline", {vertices = {0,0,0, -2,3,5, 4,6,7}}) polyline点顺序对比图 polyline 没有 size 属性`},{header:"box",slug:"box",content:`box 是长方体。主要通过 length、width 和 height 属性修改其形状。 -local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) -box 对象的重要可选属性 属性 -含义 length -立方体的长度 width -立方体的宽度 height -立方体的高度 基于以上三个属性,我们可以修改默认示例代码中旋转的box的形状。 ---添加了length, width, height三个属性(不添加默认都为1) -local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) local x = 1 -local y = 1 -local z = 0 -while scene.render() do x = x + 0.1 y = y + 0.1 obj:setrot(x, y, z) -end 不同长宽高设置的box`},{header:"sphere",slug:"sphere",content:`sphere 是球体。可以通过 radius 属性修改其大小,还可以通过设置 segment 属性设置其模型质量。具体可以参考内置示例中地球的例子。 -local obj = scene.addobj('sphere', {radius=15, segments=360}) -sphere 对象的可选属性 属性 -含义 radius -球体的圆角大小。可以用于控制球体的大小。 segments -球体的渲染面数。设置值越高球体的模型越精细。 不同segment对于相同sphere的影响`},{header:"polygon",slug:"polygon",content:`polygon 是多边形。主要通过 vertices 属性对其进行设置。 -local obj = scene.addobj("polygon", {vertices = {-1,-1,0, -1,1,-0, 1,1,0, 1,-1,0}}) 由于此处举例的多边形为正方形,因此看上去与上面介绍的 box 没什么差别。但是当形状设置为其他类型的多边形时(如三角形、五边形等),多边形的意义就能被体现出来了。 属性 -含义 -说明 vertices -多边形的顶点 -可以在 vertices 属性中依次设置每个点的三维坐标。第三维的坐标不会产生影响,但是起到占位作用。 size -体积 -由于第三维的坐标不影响,且多边形的顶点确定后面积就已经确定,因此 size 属性通过控制每个点的第三维坐标值来控制体积。 不同size对于相同polygon体积的影响`},{header:"外部模型",slug:"外部模型",content:`引用外部文件。但是目前对于MicroCityWeb来说,暂时只能引用网站中内置的文件。 -例如内置示例中引用网站内部文件在视图中生成一辆厢式货车: -local obj = scene.addobj('/res/2axle.glb') -还可以通过引用文件的网址引用外部模型: -local obj = scene.addobj('https://huuhghhgyg.github.io/ModelResource/models/F16-lite.glb') 提示 -如果需要外部模型,可以到 ModelResource仓库 中找有没有合适的模型。如果其中没有合适的模型,但是你手上又有特别想用的模型,可以按照 ModelResource仓库提供的指引 进行Pull Request请求上传模型。一旦你的Pull Request被同意,Github工作流会立即将你上传的模型部署到仓库网页中供使用并以邮件形式通知。 相关信息 -如果手中有三维模型资源,可以在3D Viewer中查看,也可以通过这个网站导出为 .glb 模型`},{header:"light",slug:"light",content:"设置光源的方向,可选参数 vertices 为一个三维向量,表示光的照射方向。由于MicroCity Web的场景中已经设置了很强的光源,因此此处不过多做介绍。"},{header:"mesh",slug:"mesh",content:"多个点构成的面,多见于引用的外部模型中。由于应用较少此处不做介绍。"},{header:"对象控制函数",slug:"对象控制函数",content:"下面假定要操作的三维对象为 obj"},{header:"getpos()",slug:"getpos",content:`获取 obj 对象的位置坐标 (x, y, z) -local x, y, z = obj:getpos()`},{header:"setpos()",slug:"setpos",content:`设置 obj 对象的位置坐标为 (x, y, z) -obj:setpos(x, y, z)`},{header:"getrot()",slug:"getrot",content:`获取 obj 对象在 x, y, z 方向上的旋转弧度值 (rx, ry, rz) -local rx, ry, rz = obj:getrot()`},{header:"setrot()",slug:"setrot",content:`设置 obj 对象在 x, y, z 方向上的旋转弧度值为 (rx, ry, rz) -obj:setrot(rx, ry, rz)`},{header:"getscale()",slug:"getscale",content:`获取 obj 对象在 x, y, z 方向上的缩放比例 sx, sy, sz -local rx, ry, rz = obj:getrot()`},{header:"setscale()",slug:"setscale",content:`设置 obj 对象在 x, y, z 方向上的缩放比例 sx, sy, sz -local rx, ry, rz = obj:getrot()`},{header:"getchildren()",slug:"getchildren",content:`获取 obj 对象的子对象表 -local children = obj:getchildren()`},{header:"getchildren()",slug:"getchildren-1",content:`设置 obj 对象的子对象表 -obj:setchildren(children_table)`},{header:"getparent()",slug:"getparent",content:`获取 obj 对象的父对象 -local num = obj:getparent() 此处只返回一个数值`},{header:"setparent()",slug:"setparent",content:`设置 obj 对象的父对象为 obj0 -obj:setparent(obj0)`},{header:"delete()",slug:"delete",content:`删除 obj 对象 -obj:delete()`}]},{path:"/notes/3d-scene-en.html",title:"3D Scene",pathLocale:"/",contents:[{header:"3D Scene",slug:"_3d-scene",content:"This section introduces 3D scenes and their settings."},{header:"MicroCityWeb 3D Scene Coordinate System",slug:"microcityweb-3d-scene-coordinate-system",content:"The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate system, and the specific direction of each coordinate axis is shown in the following figure. Coordinate system in MicroCityWeb Note that the three-dimensional coordinate axes x, y, and z here are manually drawn to show the coordinate system in MicroCityWeb and do not directly exist in the three-dimensional scene."},{header:"Setting up a Scene",slug:"setting-up-a-scene",content:`Setting up a scene requires the use of the setenv function, with the specific usage as follows: -local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true}) -It can be simplified as follows: -local s = scene.setenv({key1 = value1, key2 = value2, ...}) -The variable s holds the returned environment object. The optional parameters of the function will be described in detail below.`},{header:"Optional Parameters of a Scene",slug:"optional-parameters-of-a-scene",content:""},{header:"Parameter List",slug:"parameter-list",content:`grid: background grid of the scene -bgcolor: background color of the scene -camtype: camera view -clear: whether to clear the scene -rotspeed & transpeed*: adjustment of mouse operation speed`},{header:"grid: Background grid of the scene",slug:"grid-background-grid-of-the-scene",content:`Optional values Value -Meaning "none" -default, no grid "plane" -flat grid "sphere" -spherical grid`},{header:"bgcolor: Background color of the scene",slug:"bgcolor-background-color-of-the-scene",content:`Optional value types: Value Type -Example Built-in colors -"black", "white", "gray", etc. Hexadecimal colors -"#ffffff", "#fff", "#000000", "#000", etc. Colors represented by RGB -"rgb(255, 255, 255)", "rgb(0, 0, 0)", etc. Example: -scene.setenv({bgcolor='gray'}) -- Sets the background color to the built-in color "gray" -scene.setenv({bgcolor='#eee'}) -- Sets the background color to the hexadecimal color "#eee" -scene.setenv({bgcolor='rgb(255, 255, 255)'}) -- Sets the background color to white`},{header:"camtype: Camera angle of view",slug:"camtype-camera-angle-of-view",content:`Optional values: Value -Meaning "ortho" -Orthographic. Equivalent to a projection onto the x and y plane. User's view is in two-dimensional space. "persp" -Perspective (default). User's view is in three-dimensional space.`},{header:"clear: Whether to clear the scene",slug:"clear-whether-to-clear-the-scene",content:"When the value is set to true, the scene is cleared. The setenv function does not clear the original scene by default, unless the value of the clear parameter is manually set to true."},{header:"rotspeed & transpeed",slug:"rotspeed-transpeed",content:`Value -Meaning rotspeed -Sets the speed of rotating a 3D object with the mouse. transpeed -Sets the speed of translating a 3D object with the mouse. These two parameters usually do not need to be set specially, and the default values can be used.`},{header:"Others",slug:"others",content:""},{header:"Regarding high-frequency setting scenarios",slug:"regarding-high-frequency-setting-scenarios",content:`2023/03/21: It has been found that setting the scene too frequently can cause excessive memory usage and browser crashes. Therefore, it is recommended to avoid calling the scene.setenv() function in a loop as much as possible. -If it is necessary to do so, make sure that the frequency of calls is relatively low. This allows the browser to have enough time for garbage collection, otherwise it may cause the browser to crash.`}]},{path:"/notes/3d-scene.html",title:"3D 场景",pathLocale:"/",contents:[{header:"3D 场景",slug:"_3d-场景",content:"本节将介绍 MicroCity Web 中的三维场景及其设置。"},{header:"MicroCityWeb三维场景坐标系",slug:"microcityweb三维场景坐标系",content:`MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。 MicroCity Web中的坐标系 手动绘制上图坐标轴的代码 -scene.setenv({grid="plane"}) -- x -scene.addobj("polyline", {vertices = {0,0,0, 10,0,0}, color = "blue"}) -scene.addobj("points", {vertices = {10,0,0}, color = "blue", size = 5}) -local labelx = scene.addobj("label",{text="x"}) -labelx:setpos(10,1,0) --- y -scene.addobj("polyline", {vertices = {0,0,0, 0,10,0}, color = "green"}) -scene.addobj("points", {vertices = {0,10,0}, color = "green", size = 5}) -local labelx = scene.addobj("label",{text="y"}) -labelx:setpos(0,11,0) --- z -scene.addobj("polyline", {vertices = {0,0,0, 0,0,10}, color = "red"}) -scene.addobj("points", {vertices = {0,0,10}, color = "red", size = 5}) -local labelx = scene.addobj("label",{text="z"}) -labelx:setpos(0,1,10) scene.render()`},{header:"设置场景",slug:"设置场景",content:`设置场景需要用到 setenv 函数,具体用法如下 -local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true}) -可以简单地表示为如下形式 -local s = scene.setenv({key1 = value1, key2 = value2, ...}) -其中变量 s 存放返回的环境对象。下面将详细介绍函数的可选参数。`},{header:"场景可选参数",slug:"场景可选参数",content:""},{header:"参数列表",slug:"参数列表",content:`grid:场景的背景网格 -bgcolor:场景背景颜色 -camtype:摄像机视角 -clear:是否清除场景 -rotspeed & transpeed*:鼠标操作速度调整`},{header:"grid:场景的背景网格",slug:"grid-场景的背景网格",content:`可选值 值 -含义 "none" -默认值,无网格 "plane" -平地网格 "sphere" -球形网格`},{header:"bgcolor:场景背景颜色",slug:"bgcolor-场景背景颜色",content:`可选值类型 值类型 -示例 内置颜色 -"black", "white", "gray" 等 十六进制颜色 -"#ffffff", "#fff", "#000000", "#000"等 RGB表示的颜色 -"rgb(255, 255, 255)", "rgb(0, 0, 0)" 等 实例 -scene.setenv({bgcolor='gray'}) --设置背景颜色为内置的gray -scene.setenv({bgcolor='#eee'}) --设置背景颜色为#eee -scene.setenv({bgcolor='rgb(255, 255, 255)'}) --设置背景颜色为白色`},{header:"camtype:摄像机视角",slug:"camtype-摄像机视角",content:`可选值 值 -含义 "ortho" -正视。相当于向x和y构成的平面投影,用户视角在二维空间中。 "persp" -透视(默认值)。用户视角在三维空间中。`},{header:"clear:是否清除场景",slug:"clear-是否清除场景",content:"值设置为 true 时,清除场景 setenv 函数默认不清除原来的场景,除非手动设置参数 clear 的值为 true"},{header:"rotspeed & transpeed",slug:"rotspeed-transpeed",content:`值 -含义 rotspeed -设置鼠标的旋转三维对象的速度 transpeed -设置鼠标平移三位对象的速度 提示 -这两个参数通常不需要特别设置,使用默认值即可。`},{header:"其他",slug:"其他",content:""},{header:"有关高频率设置场景",slug:"有关高频率设置场景",content:`2023/03/21:目前发现过高频次设置场景会导致内存占用过高,进而导致浏览器崩溃的问题。因此建议尽量不要循环调用 scene.setenv() 函数。 -如果必须这么做,请确保调用频率相对较低,这样允许浏览器有一定的时间进行GC(垃圾清理),否则可能导致浏览器崩溃。`}]},{path:"/notes/",title:"笔记",pathLocale:"/",contents:[{header:"笔记",slug:"笔记",content:""},{header:"通用知识",slug:"通用知识",content:`Lua语言快速上手 -MicroCity的版本 -时间推进法 -面向对象编程 -有关工具`},{header:"MicroCity(桌面版)",slug:"microcity-桌面版",content:`结果可视化 -操作网络 -模型求解`},{header:"MicroCityWeb",slug:"microcityweb",content:`用户界面简介 [EN] -3D 场景 [EN] -3D 对象 [EN] -离散事件模拟和程序控制 [EN] -混合整数规划 [EN] -调试相关`},{header:"思路",slug:"思路",content:`仓库仿真 -通用绘图代码 -港口AGV服务流程三维仿真思路 本页目录所指的笔记内容适用于相应版本的MicroCity。特别感谢在编写和整理的过程中 孙卓老师(MicroCity作者) 给予的指导和帮助。`}]},{path:"/notes/cy-simulation.html",title:"港口AGV服务流程三维仿真思路",pathLocale:"/",contents:[{header:"港口AGV服务流程三维仿真思路",slug:"港口agv服务流程三维仿真思路",content:"本文思路仅供参考。 集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。"},{header:"实现场桥对集装箱的抓取",slug:"实现场桥对集装箱的抓取",content:""},{header:"总体思路",slug:"总体思路",content:"实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽象为对象。"},{header:"总体结构",slug:"总体结构",content:`具体的想法是将堆场对象作为数据模型(DataModel),主要存放各种数据,如存放集装箱实体、对应位置(行、列、高度)的集装箱坐标等数据;将场桥对象作为操作器(Operator),主要实现场桥的三维动画、实现对堆场对象中数据的管理。 -这样做的好处是可以将场桥和堆场解耦合,方便后续的扩展。此外,如果对象属性考虑得比较周全,可以方便地在同一个场景中创建多个对象,实现多个场桥对堆场的操作。`},{header:"事件和任务",slug:"事件和任务",content:"我打算为整体流程中涉及到需要移动的主要实体对象创建任务序列。这样可以做到在同一个场景中实现多个场桥的并行操作,各个场桥执行各自的任务,互不干扰。此外,还需要一个总控制程序控制每个时间节点的任务执行情况,并控制场桥的三维动画。"},{header:"业务流程",slug:"业务流程",content:"在这部分的仿真中主要业务流程聚焦于集装箱的移动。因此,最重要的就是集装箱所有权的流转。集装箱的所有权流转流程如下图所示: 集装箱对象流转过程"},{header:"对象结构",slug:"对象结构",content:"以下是这个仿真中主要涉及到的对象的结构"},{header:"实现方法",slug:"实现方法",content:""},{header:"堆场规模",slug:"堆场规模",content:`对于堆场对象,由于它的功能主要是存放集装箱对象及其相关数据(比如对应位置的坐标),那么就还会出现一个问题,堆场的规模有多大?因此确定堆场的规模是一个必要的步骤。在创建堆场对象时需要确定所创建的堆场的规模,即行数、列数、高度。这样可以在创建堆场对象时就确定堆场的规模,方便后续的操作。 -我的做法是首先确定堆场对象的占地大小和集装箱层数,然后由相关数据去计算最多能摆放几行几列的集装箱。 堆场占地大小方面,通过在创建对象时输入两点坐标来确定,根据两点连成的对角线构成一个矩形,从而确定堆场的占地面积。 -集装箱层数方面,通过在创建对象时输入一个数字来确定。根据这两个输入就就可以确定堆场的规模。`},{header:"事件和任务",slug:"事件和任务-1",content:`由于在这个仿真中需要移动的对象主要是场桥,因此每次循环执行任务的时候只需要操作场桥即可。 -因此,我打算将场桥的任务序列作为一个队列,每次循环执行任务的时候,从对象的任务序列中取出第一个任务执行,执行完毕后判断是否满足任务执行完毕的条件,如果满足则删除这个任务,执行下一个任务。这样可以保证每次循环执行任务的时候,场桥对象能够按照次序执行任务。 -执行任务的方法为 executeTask(dt) ,对象根据推进时间的长短 dt 执行任务。在 executeTask(dt) 中存放了处理任务的逻辑,包括判断任务类型、执行任务、删除任务等。 -如果场景中存在多个场桥,只需要将这些对象添加到执行任务对象的列表中即可。主控程序每次循环执行任务时,会遍历这个对象列表,依次执行每个对象的任务。 提示 -注意此处任务执行虽然在时间点上看是同时执行的,但是其实和对象所处的序列位置有关。 -一个例子就是:假设两个对象同时需要抢占位置A,那么按照任务序列的顺序,先执行的对象会抢占到位置A,后执行的对象会抢占失败,尽管它们在同一时刻都在抢占位置A。因此,此处不是严格的同时执行,而是同一时刻按照任务序列的顺序执行。`},{header:"业务流程",slug:"业务流程-1",content:`场桥首先从堆场中获取对应位置(行、列、高度)集装箱的坐标,并将吊具移动到堆场指定集装箱位置,抓取集装箱。集装箱所有权从堆场(cy.containers)转移到场桥吊具(rmg.attached)(通过解除表引用实现,将值设为 nil)。 -场桥将集装箱移动到过道并放下集装箱。以同样的方式将集装箱所有权从场桥吊具(rmg.attached)移动到过道(rmg.stash),表明集装箱可以被提取。 -如果有车辆将集装箱接走,则可以进一步将集装箱所有权从场桥过道(rmg.stash)移动到车辆上。`},{header:"运行结果",slug:"运行结果",content:""},{header:"实现AGV到达至服务的全流程",slug:"实现agv到达至服务的全流程",content:""},{header:"问题描述",slug:"问题描述",content:"使用事件调度法实现以上流程的三维化形式"},{header:"What's New",slug:"what-s-new",content:`上一个仿真的实现是实现这个仿真的基础。相比于上一个仿真,这个仿真最为显著的改进体现在: 使用面向对象编程模式,创建场桥、堆场(数据模型)、AGV、岸桥、船(数据模型)共4个类型的对象,并实现对象本体和其各部件的移动方法。 如果不了解面向对象编程,可以参考通用知识-面向对象编程 延续面向事件的仿真的思路,实现了总控制流程,实现同一时刻对多个对象同时进行控制(主要通过对象的 executeTask(dt) 和 maxStep() 及相关函数实现)。在面向对象的编程模式中,可以将 executeTask(dt) 和 maxStep() 视为接口,主程序通过实现这两个接口,实现对对象的控制。(尽管lua中似乎没有这部分的概念) -使用任务序列实现各个对象的流程,实现场桥和AGV之间、AGV和岸桥之间的相互等待,实现不同对象之间的任务协同。 -尝试将流程从堆场至AGV延伸至岸桥、船,实现两级排队等待。`},{header:"对象设计",slug:"对象设计",content:`由于属性和函数实在太多,因此使用思维导图的形式展示对象的设计。 提示 -此处占用篇幅较大,您也可以直接跳转到下一部分总体布局`},{header:"堆场",slug:"堆场",content:"堆场仍然作为数据模型。"},{header:"场桥",slug:"场桥",content:""},{header:"AGV",slug:"agv",content:""},{header:"岸桥",slug:"岸桥",content:"岸桥的代码和涉及结构主要衍生自堆场,因此后面不详细叙述。"},{header:"船",slug:"船",content:"船对象的主要作用也是作为数据模型,设计思路同堆场。"},{header:"总体布局",slug:"总体布局",content:""},{header:"总体流程",slug:"总体流程",content:"集装箱流转流程 相比于之前的仿真,这个仿真在流程上更进了一步,添加了AGV到达、排队的流程,还添加了岸桥服务、集装箱装船的流程。"},{header:"流程分析",slug:"流程分析",content:`AGV出现后,场桥、岸桥和AGV之间的流程也变得更加复杂。首先,AGV的到达是随机的,因此可能造成排队现象。其次,AGV的到达会触发场桥和AGV的流程,而场桥和AGV的流程又会触发岸桥的流程。因此,这个仿真的流程是一个多级流程,需要考虑多个对象之间的流程协同。 -特别是AGV和场桥之间的流程,其中存在AGV和场桥的相互等待。AGV到达的时候需要通知场桥提取货物。在场桥提取的过程中: 场桥需要等待AGV到达指定位置后,才能将货物移动到AGV上 -AGV需要等待场桥的抓取并将集装箱放在AGV上以后,才能将集装箱的所有权从场桥转移到AGV上 因此,AGV和场桥之间的流程是一个相互等待的流程。具体流程可以参考下图。 而岸桥的流程和场桥的流程类似,也是一个相互等待的流程。主要体现在: 当AGV到达指定位置时,岸桥可能在服务别的AGV,此时AGV要进行等待 -当AGV刚进入岸桥的服务区域时,通知岸桥到达指定位置,如果岸桥先到达指定位置,则此时岸桥要进行等待`},{header:"实现方法",slug:"实现方法-1",content:""},{header:"排队流程的实现",slug:"排队流程的实现",content:`AGV排队的情况我选择使用元胞自动机作为停车位的数据模型。其中,停车位的长度为: -停车位长度=对应数据模型中1个集装箱的长度+集装箱间隔长度 -\\text{停车位长度}=\\text{对应数据模型中1个集装箱的长度}+\\text{集装箱间隔长度} -停车位长度=对应数据模型中1个集装箱的长度+集装箱间隔长度 -由于AGV的长度比1个集装箱略长,因此需要占用2个停车位的长度。每次执行任务时,AGV会判断前方空间是否被阻塞,如果没被阻塞则向前移动。如果前方位置为目标bay,则前进后等待场桥作业,获取集装箱后继续以元胞为单位向前移动直到离开。场桥部分排队和岸桥部分排队原理也相同。 AGV元胞自动机排队模型示意图`},{header:"事件调度法的实现",slug:"事件调度法的实现",content:`在之前的仿真中,我使用了非固定步长的时间推进法来实现仿真。在这个仿真中,我使用了事件调度法来实现仿真。相比于时间推进法,事件调度法的特点是可以准确地将事件推进到发生的时刻,从而执行对应事件。 -你可能注意到了对象设计部分我将 executeTask() 和 maxstep() 标记为(interface),这是由于为了计算准确的推进时间,我需要在每个对象中实现 executeTask() 和 maxstep() 方法。其中,executeTask() 方法用于执行任务,maxstep() 方法用于计算距离到达下一个事件的发生时间(当前任务还剩多久能执行完),然后得到最大能够推进的时间,再去跟系统运行得到的间隔时间dt进行比较得到最大的推进时间。 -我认为课件中的下面这张图能够很好地表示如何使用事件调度法来进行仿真并刷新场景。其中,第一行指的是仿真的业务流程,第二行Refresh部分指的是刷新场景。`},{header:"运行结果",slug:"运行结果-1",content:`注意 -由于以下部分内容均为动图且图片体积较大。由于本站托管于GitHubPage,因此如果您没有的特殊网络环境可能会造成动图加载缓慢甚至加载失败。 提示 -如果您直接观看动图的时候动图区域出现了摩尔纹,可以尝试将动图点开放大看,再看看是否有改善。 场桥运行过程 岸桥运行过程 总体运行过程`}]},{path:"/notes/debug.html",title:"调试相关",pathLocale:"/",contents:[{header:"调试相关",slug:"调试相关",content:"本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。"},{header:"清除输出",slug:"清除输出",content:"右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。"},{header:"调试器快捷键",slug:"调试器快捷键",content:`在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。 F9 Step Over:跳过当前行,执行下一行 -F10 Step Into:进入当前行,如果当前行是函数调用,则进入函数内部 -F11 Step Out:跳出当前函数,执行函数调用的下一行`},{header:"Debug命令",slug:"debug命令",content:""},{header:"监视变量",slug:"监视变量",content:`在控制台使用 debug.watch() 命令监视变量。 -例如,在调试的过程中想要监视 a 变量的值,可以使用 debug.watch('a') 命令。 右键输出区域可以输入命令`},{header:"堆栈跟踪",slug:"堆栈跟踪",content:`使用 debug.traceback() 函数可以打印出当前的堆栈跟踪信息 -function myFunction() -- 某些代码逻辑 print(debug.traceback("Stack trace")) -- 其他代码逻辑 -end function anotherFunction() myFunction() -end anotherFunction() -输出结果 -Stack trace -stack traceback: -[string "function myFunction() ..."]:3: in function 'myFunction' -[string "function myFunction() ..."]:8: in function 'anotherFunction' -[string "function myFunction() ..."]:11: in main chunk`},{header:"运行状态",slug:"运行状态",content:`debug.debug() 进入Debug模式。常用于在程序运行过程中进入Debug模式。如果想要启动时就进入Debug模式,可以右键顶部▶️按钮。详见 用户界面简介 - 运行状态。 -debug.pause() 暂停程序运行。顶部运行按钮▶️会亮起,暂停按钮⏸️熄灭。`},{header:"其他调试命令",slug:"其他调试命令",content:`Lua 的 Debug 函数大多都适用于 MicroCity Web,可以参考: The Debug Library | Lua 5.4 Reference Manual -Lua 调试(Debug) | 菜鸟教程`}]},{path:"/notes/event-scheduling-en.html",title:"Discrete Event Simulation and Program Control",pathLocale:"/",contents:[{header:"Discrete Event Simulation and Program Control",slug:"discrete-event-simulation-and-program-control",content:""},{header:"Coroutines",slug:"coroutines",content:"MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling."},{header:"coroutine.queue",slug:"coroutine-queue",content:`Adds a function or coroutine to the coroutine queue for execution after a specified relative time. -coroutine.queue(rt, f|co [, argument list...]) -Parameters Parameter -Description rt -Relative time from the current queue. It should be greater than or equal to 0. In other words, it specifies the time after which the input function or coroutine will be executed. f/co -Function or coroutine. If it's a function, you only need to input the function name.`},{header:"coroutine.qtime",slug:"coroutine-qtime",content:`Retrieves the current time of the queue. -local time = coroutine.qtime()`},{header:"Example",slug:"example",content:`Here are two examples provided: Adding Coroutines to the Queue: Demonstrates how to add coroutines to the queue and display the current queue time within the function. -Vehicle Movement: Shows how to use coroutines to refresh the scene based on real-world time.`},{header:"Adding Coroutines to the Queue",slug:"adding-coroutines-to-the-queue",content:`This example demonstrates how to add coroutines to the queue and display the current queue time within the function. -function Show() print("Current time:", coroutine.qtime()) -end function ShowShort() print("Current time (short):", coroutine.qtime()) -end coroutine.queue(10, Show) -coroutine.queue(20, Show) -coroutine.queue(15, ShowShort) -coroutine.queue(5, Show) -- Result: --- Current time: 5.0 --- Current time: 10.0 --- Current time (short): 15.0 --- Current time: 20.0`},{header:"Vehicle Movement",slug:"vehicle-movement",content:`This example demonstrates how to use coroutines to refresh the scene based on real-world time. -scene.setenv({grid='plane'}) -- Set the scene background grid -- Vehicle -local car = scene.addobj('/res/2axle.glb') -car.speed = 1 -- Car speed -- Initial time -local t = os.clock() -local dt = 0 -- Refresh time state t and dt (based on CPU intervals to synchronize with real-world time) -function refreshtime() dt = os.clock() - t t = os.clock() -end -- Coroutine updates the scene -function update() if not scene.render() then return end -- Render the scene and check if the program is terminated coroutine.queue(dt, update) -- Add the next update based on CPU step time carmove() -- Move the vehicle refreshtime() -- Calculate the current dt -end -- Vehicle movement -function carmove() print("Car moves at", t) local x, y, z = car:getpos() car:setpos(x, y, z + dt * car.speed) -end -- Initial update (add the first update) --- Since subsequent updates are added within the function, the updates will loop automatically -coroutine.queue(dt, update)`},{header:"Random Numbers",slug:"random-numbers",content:""},{header:"Creating a Random Seed",slug:"creating-a-random-seed",content:`local seed = math.randomseed(x [, dist]) -Parameters Parameter -Description x -Random seed. Different input values will produce different random numbers. To get different values each time, consider setting the random seed x to the current time. dist -Random distribution (optional). If not set, the default is a uniform distribution. If this parameter is set, you can also specify mu and sigma as parameters for the corresponding distribution. The dist parameter can be set to one of three distributions: 'normal': Normal distribution -'exponential': Exponential distribution -'poisson': Poisson distribution In addition, you can set parameters for these distributions, where the mu key represents the mean and the sigma key represents the standard deviation.`},{header:"Example",slug:"example-1",content:`-- Create a random seed with a Poisson distribution -local seed = math.randomseed(os.time(), {distribution = "poisson", mu = "3"}) -- Poisson distribution with a mean of 3 -- Output a random number -print(seed:random())`},{header:"Program Control",slug:"program-control",content:`Program control, in this context, mainly refers to controlling the execution of a program using the buttons in the user interface, including pause, resume, and stop. Command Bar This mainly refers to the first three buttons in the command bar. In MicroCityWeb, program control refers to the pause, resume, and stop of the 3D interface rendering implemented through the scene object. The specific function is as follows: -local state = scene.render() -Here, the return value of scene.render() is stored in the state variable. The state variable can be either true or false, representing the running or terminated state of the program (button 3 in the command bar). -Pausing the rendering of 3D objects is also achieved by calling scene.render(). If the refresh of 3D objects is implemented by continuously calling the scene.render() function and the refresh interval is not controlled by os.sleep(), it is possible to pause the rendering of the 3D interface at a certain state. This is because if os.sleep() is used to control the speed of 3D object movement and the pause button is clicked while the program is in the os.sleep() process, the program may not respond immediately, resulting in the pause button becoming ineffective. Therefore, it is recommended not to use os.sleep() for controlling the speed of 3D object movement, but to use other parameters to control the duration of advancement in order to control the speed of 3D object movement.`}]},{path:"/notes/event-scheduling.html",title:"离散事件模拟和程序控制",pathLocale:"/",contents:[{header:"离散事件模拟和程序控制",slug:"离散事件模拟和程序控制",content:"本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。"},{header:"协程",slug:"协程",content:"MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 部分了解相关概念。"},{header:"coroutine.queue",slug:"coroutine-queue",content:`将函数或协程添加到协程队列中等待 -coroutine.queue(rt, f|co [, 参数列表...]) -参数 参数 -含义 rt -相对当前队列的时间,要求大于等于0。换句话说,也就是再过rt执行输入的函数或协程 f/co -函数或协程。如果是函数,只需要输入函数名`},{header:"coroutine.qtime",slug:"coroutine-qtime",content:`获取当前队列的时间 -local time = coroutine.qtime()`},{header:"示例",slug:"示例",content:`此处提供两个示例 协程添加任务:使用协程添加任务,并在函数中显示当前队列时间 -车辆移动:使用协程实现以真实世界的时间刷新场景`},{header:"协程添加任务",slug:"协程添加任务",content:`这个示例中展示了如何使用协程添加任务,并在函数中显示当前队列时间 -function Show() print("当前时间:",coroutine.qtime()) -end -function ShowShort() print("当前时间short:",coroutine.qtime()) -end coroutine.queue(10, Show) -coroutine.queue(20, Show) -coroutine.queue(15, ShowShort) -coroutine.queue(5, Show) -- 结果: --- 当前时间: 5.0 --- 当前时间: 10.0 --- 当前时间short: 15.0 --- 当前时间: 20.0`},{header:"车辆移动",slug:"车辆移动",content:`这个示例中展示了如何使用协程实现以真实世界的时间刷新场景 -scene.setenv({grid='plane'}) -- 设置场景网格背景 -- 车辆 -local car = scene.addobj('/res/2axle.glb') -car.speed = 1 --车速度 -- 初始时间 -local t = os.clock() -local dt = 0 -- 刷新时间状态t和dt(按照CPU间隔步进,达到和真实时间同步) -function refreshtime() dt = os.clock() - t t = os.clock() -end -- 协程更新场景 -function update() if not scene.render() then return end --渲染场景并检查程序是否中止 coroutine.queue(dt, update) --根据CPU步进时间添加下一次更新 carmove() --移动车辆 refreshtime() --计算本次dt -end -- 车辆移动 -function carmove() print("car move at ",t) local x, y, z = car:getpos() car:setpos(x,y,z+dt*car.speed) -end -- 初始更新(添加第一次更新) --- 由于函数中涉及到添加后续更新,因此更新会自动循环 -coroutine.queue(dt,update) -在MicroCityWeb中打开`},{header:"随机数",slug:"随机数",content:""},{header:"创建随机数种子",slug:"创建随机数种子",content:`local seed = math.randomseed(x [, dist]) -参数 参数 -含义 x -随机数种子,会根据输入的不同数值返回不同的随机数。如果需要每次的值都不一样,可以考虑将随机数种子x设置为当前时间 dist -随机数分布(可选参数)。如果不设置,默认为均匀分布。如果设置这个参数,还可以设置 mu 和 sigma 作为对应分布的参数 dist参数可以设置键值为三种分布: 'normal':正态分布 -'exponential':指数分布 -'poisson':泊松分布 此外,还可以设置这几种分布的参数,其中 mu 键为均值,sigma 键为方差。`},{header:"示例",slug:"示例-1",content:`-- 创建泊松分布的随机数种子 -local seed = math.randomseed(os.time(), {distribution = "poisson", mu = "3"}) -- 泊松分布,均值为3 -- 输出随机数 -print(seed:random())`},{header:"程序控制",slug:"程序控制",content:`本文中的程序控制主要是指如何使用用户界面中的按钮控制程序的运行,包括暂停、恢复、停止等。 命令栏 主要是指命令栏的前3个按钮 MicroCity Web中的程序控制主要是指3D界面渲染中通过 scene 对象实现的3D界面运动的暂停、恢复、停止,具体的函数如下: -local state = scene.render() -此处将 scene.render() 的返回值存放于 state 变量中,state 变量的值为 true 或者 false,分别代表程序的运行状态为运行或者被终止(命令栏中按下按钮3)。 -3D对象的暂停渲染也是通过调用 scene.render() 来实现的。如果刷新3D对象是通过不断调用 scene.render() 函数实现,并且刷新间隔时间不是通过 os.sleep() 来控制,那么可以实现在3D界面上将渲染暂停在某个状态。这是因为如果使用 os.sleep() 来控制3D对象的运动速度,那么当点击暂停按钮时,很可能正好处于 os.sleep() 的过程中,导致程序无法立即响应,从而导致暂停按钮无效。因此,建议在控制3D对象的运动速度时避免使用 os.sleep(),而是通过添加其他参数的方式来控制推进时长,以达到控制3D对象运动速度的目的。`}]},{path:"/notes/lp.html",title:"模型求解",pathLocale:"/",contents:[{header:"模型求解",slug:"模型求解",content:`在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。 -规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划 提示 -本页内容基于 MicroCity 桌面版。如果你在寻找 MicroCity Web 版的混合整数规划求解方法,请参考 MicroCity Web 笔记中对应的 混合整数规划 部分。`},{header:"创建模型对象",slug:"创建模型对象",content:`创建规划模型对象,存入变量lp中。 -local lp = CreateLP() 官方文档中将创建的数学模型对象存入变量LPModel中,作用同本文的lp`},{header:"写入数学模型",slug:"写入数学模型",content:`此时,数学模型的对象已经创建并存入了变量lp中,可以对其进行更进一步的操作。数学模型一般分为两个部分: 目标函数 -约束方程 接下来,先介绍创建目标函数的具体做法。`},{header:"创建目标函数",slug:"创建目标函数",content:`MicroCity中,使用SetObjectFunction()设置模型对象的目标函数。允许选择目标函数求最大值或最小值。具体用法如下: 最大值 -最小值 SetObjFunction(lp, coeff, "max") --求最大值 SetObjFunction(lp, coeff, "min") --求最小值 "min"和"max"不区分大小写,写"MIN"和"MAX"也可以`},{header:"参数说明及示例",slug:"参数说明及示例",content:`参数 -作用 lp -数学模型对象。将数学模型输入函数中,为模型设置目标函数 coeff -目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。 "min"或"max" -确定目标函数求最大还是求最小。 coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​的最小值,则添加目标函数的做法如下: --- 假设你已经创建了模型对象,并存入变量lp中 -- 4*x1 + 12*x2 + 18*x3 -local coeff = {4, 12, 18} -- 设置目标函数:求最小 -SetObjFunction(lp, coeff, "min")`},{header:"添加约束方程",slug:"添加约束方程",content:`在MicroCity中,添加模型约束的函数为AddConstraint(),用法如下: ≤ -≥ -= -- 使用符号表达 -AddConstraint(lp, cons, "<=", b) -- 或者可以使用缩写表达 -AddConstraint(lp, cons, "le", b) -- 使用符号表达 -AddConstraint(lp, cons, ">=", b) -- 或者可以使用缩写表达 -AddConstraint(lp, cons, "ge", b) -- 使用符号表达 -AddConstraint(lp, cons, "==", b) -- 或者可以使用缩写表达 -AddConstraint(lp, cons, "eq", b)`},{header:"参数说明",slug:"参数说明",content:`参数 -作用 lp -数学模型对象。将数学模型输入函数中,为模型添加约束 cons -约束方程系数。和设置目标函数中的cons一样,也是一个table类型的变量。用于确定约束方程中各个变量的系数。 "<=" 或 ">=" 或 "==",或其对应的字母表达 -确定约束方程与右端项的关系 b -一个数字,表示约束方程的右端项。可以是变量也可以是常量`},{header:"示例",slug:"示例",content:`上面已经设置了目标函数为4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​,假设你要为这个函数添加两个约束方程: -{x1+3x3≥32x2+2x3≥5 -\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ -添加对应约束方程: --- 添加约束:x1+3*x3≥3 -cons = { 1, 0, 3 } -AddConstraint(lp, cons, ">=", 3) -- 添加约束:2*x2+2*x3≥5 -cons = { 0, 2, 2 } -AddConstraint(lp, cons, ">=", 5) -不难注意到,系数的个数和目标函数中变量的个数一致。因此,在编程求解之前首先要搞清楚变量的总数,并安排好各个变量的位置。`},{header:"设置变量类型",slug:"设置变量类型",content:`MicroCity中的数学规划支持整数规划。如果没有对变量设置SetUnbounded(),默认变量的取值范围是非负实数(≥0)。下面介绍变量类型设置的详细做法。 -你可以将模型中第i个变量设置为整数变量或0-1变量。如果不将变量设置为这些类型,则默认变量为非负实数。 整数变量 -0-1变量 SetInteger(lp, i) --整数变量 SetBinary(lp, i) --0-1变量 让第i个变量的值可以是负数(默认取不到负数): -SetUnbounded(lp, i)`},{header:"模型求解和输出",slug:"模型求解和输出",content:""},{header:"模型求解",slug:"模型求解-1",content:`由于目标函数和约束方程都已经添加完毕,因此模型的求解就很简单了,只需要一步: -SolveLP(lp) -执行完这条语句后,存放于变量lp内的数学模型就求解完毕了🎉`},{header:"输出",slug:"输出",content:`求解完还需要输出,否则就不知道求解的结果如何。以下是常用的输出求解结果的函数。 -获取目标函数值: -GetObjective(lp) -获取第i个变量的值: -GetVariable(lp, i)`},{header:"SolveLP",slug:"solvelp",content:`SolveLP()函数在求解完毕后也有输出,输出代码的含义如下: 输出代码 -含义 0 -成功 -1 -无效的LP模型 -2 -无内存 1 -次优 2 -无可行解 3 -无界解 4 -退化 5 -遇到数值错误 6 -用户终止了求解 7 -超时错误 其他返回值表示的含义请参阅文档 4.8混合整数线性规划 中的SolveLP()函数。`},{header:"模型求解示例",slug:"模型求解示例",content:`这里提供一个简单的从建模至求解的示例供参考。(其实就是将前面的拼起来) -算例: -minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N -minf=4x_1+12x_2+18x_3\\\\ -s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N -\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N表示自然数(非负整数集合) 脚本 --- 创建线性规划对象 -local lp = CreateLP() local n = 3 --设置目标函数个数 -- 目标函数:4*x1 + 12*x2 + 18*x3 --- 设置目标函数系数,目标函数求最小 -local coeff = { 4, 12, 18 } -SetObjFunction(lp, coeff, "min") -- 添加约束1:x1 + 3*x3 ≥ 3 -cons = { 1, 0, 3 } -AddConstraint(lp, cons, ">=", 3) -- 添加约束2:2*x2 + 2*x3 ≥ 5 -cons = { 0, 2, 2 } -AddConstraint(lp, cons, ">=", 5) -- 由于没有设置SetUnbounded(), --- 默认所有变量取值非负, --- 因此不用针对变量非负添加约束。 -- 设置所有变量为整数 -for i = 1, n do SetInteger(lp, i) -end -- 求解模型 -SolveLP(lp) -- 输出目标函数值 -print("目标函数值:",GetObjective(lp)) -- 输出各个变量的值 -for i = 1, n do print("x",i,"=",GetVariable(lp, i)) -end -输出结果 -目标函数值:42 -x1=0 -x2=2 -x3=1`},{header:"建模的一些技巧",slug:"建模的一些技巧",content:""},{header:"线性化",slug:"线性化",content:`有时候我们会遇到多下标的建模问题,如决策变量为xijx_{ij}xij​,这个时候就要将其进行线性化编码。 -假设决策变量本身的形状共有3行4列,即: 列1 -列2 -列3 -列4 x11x_{11}x11​ -x12x_{12}x12​ -x13x_{13}x13​ -x14x_{14}x14​ x21x_{21}x21​ -x22x_{22}x22​ -x23x_{23}x23​ -x24x_{24}x24​ x31x_{31}x31​ -x32x_{32}x32​ -x33x_{33}x33​ -x34x_{34}x34​ 假设目标函数要将这些决策变量求和,即 F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​ 如果要将其输入目标函数,此时可以将其线性化为 x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​ -由于只有两个维度,因此可以使用两个for实现: -local cons = {} -for i = 1, 3 do -- 第一维 for j = 1, 4 do -- 第二维 cons[4 * (i - 1) + j] = 1 -- 填入系数 -- 其中 4 * (i - 1) + j 的思想类似于进位 end -end --结果: --- cons长度为12,值都为1`},{header:"例题:指派模型",slug:"例题-指派模型",content:`下面以一个实际的例题来看看多维线性化的具体使用方法及其方便之处。 -甲、乙、丙、丁四人配送A,B,C,D四种货物,所需时间如表所示。若一种货物只交一人送货,则应指派何人配送何种货物,能使总的时间最少? 人\\工件 -A -B -C -D 甲 -14 -9 -4 -15 乙 -11 -7 -9 -10 丙 -13 -2 -10 -5 丁 -17 -9 -15 -13 假设货物A、B、C、D对应的编号依次为1、2、3、4,设 xij=1x_{ij}=1xij​=1 时表示第i个人送j货,xij=0x_{ij}=0xij​=0 时表示第i个人不送j货。 -则上述问题的数学模型可以表示为 -minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 -minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ -s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 -\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ -求解代码 --- 效率矩阵 -local cost = { { 14, 9, 4, 15 }, { 11, 7, 9, 10 }, { 13, 2, 10, 5 }, { 17, 9, 15, 13 } -} local lp = CreateLP() -- 创建目标函数 -local coeff = {} -for i = 1, 4 do for j = 1, 4 do -- 此处可以轻松将二维数组转换为一维数组 coeff[4 * (i - 1) + j] = cost[i][j] end -end SetObjFunction(lp, coeff, "min") --添加约束 -for k = 1, 4 do -- 第i维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- j求和,判断i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) -end for k = 1, 4 do -- 第j维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then --i求和,判断j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) -end -- 求解模型 -SolveLP(lp) -- 输出目标函数值 -print("目标函数值:",GetObjective(lp)) -- 输出决策变量 -for i = 1, 4 do -- 第一维 for j = 1, 4 do -- 第二维 local x = GetVariable(lp, 4 * (i - 1) + j) if x~=0 then print("x[", i, "][", j, "]=", x) end end -end -输出 -目标函数值:29 -x[1][3]=1 -x[2][1]=1 -x[3][4]=1 -x[4][2]=1 结果 -人 -配送工件 x13=1x_{13}=1x13​=1 -甲 -C x21=1x_{21}=1x21​=1 -乙 -A x34=1x_{34}=1x34​=1 -丙 -D x42=1x_{42}=1x42​=1 -丁 -B`},{header:"中间变量的处理",slug:"中间变量的处理",content:`有时候模型中会存在一些中间变量,这些变量必须要在矩阵中有对应的位置才能对其进行求解,而这些中间变量不参与目标函数值的运算。可以将中间变量对应位置的系数设为0。 -假设x1,x2,x3,x4x_1,x_2,x_3,x_4x1​,x2​,x3​,x4​为决策变量,y1,y2y_1,y_2y1​,y2​为中间变量。目标函数为: -z=∑i=14xi -z=\\sum_{i=1}^4x_i -z=i=1∑4​xi​ -则目标函数系数可以设为: -local fcons = {1, 1, 1, 1, 0, 0} -接下来按照一般流程做就可以啦😎`}]},{path:"/notes/lua.html",title:"Lua语言快速上手",pathLocale:"/",contents:[{header:"Lua语言快速上手",slug:"lua语言快速上手",content:"由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。"},{header:"变量和函数定义",slug:"变量和函数定义",content:`lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。 -a = 1.5 -b = "string" -c = {} -- c为表,见下文介绍 -函数的定义 -function add(a, b) return a + b -end -上方简单定义了一个add()函数,目的是把输入的两个变量相加返回结果。 -变量分为全局变量和局部变量,函数也是如此。局部变量和函数的定义如下。 --- 定义局部函数 -local function show(msg) print(msg) -end -- 定义局部变量 -local a = 1 -如果局部定义的内容(函数或变量)和全局定义的内容有冲突,以局部的内容优先。存在这种冲突时,你操作的内容是局部的内容。 -如果没有明确需要操作全局变量,建议尽量将变量定义为局部变量。这种做法可能会减少bug的出现,也是更加安全的做法。`},{header:"条件",slug:"条件",content:`就是if,具体实现形式有如下几种: 普通形式 if condition then print("condition==true") -end 带else的形式 if condition then print("condition==true") -else print("condition==false") -end 以及使用elseif的形式 if number > 0 then print("number>0") -elseif number < 0 then print("number<0") -else print("number==0") -end -Lua中相等判断的运算符为==,不等判断的运算符为~=。您可以将运算符运用于条件表达式。下面是一个简单的举例: -print(1==1) -- true -print(1~=1) -- false`},{header:"循环",slug:"循环",content:"记录一下最常用的两种循环: for&while"},{header:"for",slug:"for",content:`最普通的形式 --- 输出1到10共10个数 -for i = 1:10 do print(i) -end -如果你比较熟悉C语言或C类语言,以上代码对应的形式如下 -for(int i=1; i<=10; i++){ printf("%d\\n",i); -} -考虑步长 --- 输出10到1共10个数,步长为-1 -for i = 10:1:-1 do print(i) -end 步长为负数时,需要注意开始和结束的数字也应该为倒序 泛型循环 -可以直接遍历一个表中的所有元素。 -i为表元素的下标,从1开始;v为表元素的值。 -a = {4,7,9} -for i,v in ipairs(a) do print("index=",i,"\\tvalue=",v) -end ipairs适用于数组(i估计是integer的意思),pairs适用于对象,因为数组也是对象,所以pairs用于数组也没问题。`},{header:"while",slug:"while",content:`while的常用方法就一个 -local condition = true -while condition do print("while==true") condition = false -end -和C类语言一样。只要condition为true的时候while就会一直执行。当condition被设置为false的时候,while就会结束运行。`},{header:"循环操作符",slug:"循环操作符",content:`同其他语言的规定一样,break关键字用于跳出循环。 -LUA中没有continue,只有break。但是可以可以通过使用if+break的形式实现continue的功能。`},{header:"Lua的小特性:表",slug:"lua的小特性-表",content:`虽然Lua里面把它自己的数组称作table,但是我认为这个数据结构更类似于Python的集合或者json,里面可以存储任何东西,不受结构约束。 -collection = {{"a", 1, 2}, "abc", {2, 3}} -如果需要查询数组的长度,只需要在数组名前面添加#即可得到 -list = {1, 2, 3, 4, 5} -for i=1,#list do print(list[i]) -end -Lua的数组(表)下标从1开始,不同于C类语言的0。此处以前面定义的collection为例: --- collection = {{"a", 1, 2}, "abc", {2, 3}} -print(collection[1][1]) --a -print(collection[2]) --abc -print(collection[3][2]) --3`},{header:"索引",slug:"索引",content:`Lua的表的索引非常灵活,可以是数字,也可以是字符串,甚至是其他类型的数据。 -下面是一些简单的例子: -local list = {} -- 以数字为索引 -list[1] = "a" -- 以字符串为索引 -list["b"] = 2 -list.message = "hello world" -- 等价于list["message"] = "hello world" print(list[1]) -- a -print(list["b"]) -- 2 -print(list.message) -- hello world`},{header:"添加元素",slug:"添加元素",content:`向指定位置添加 -table.insert(table, pos, value) --在指定位置(pos)添加元素 -或者 -table.insert(table, value) --向最后添加元素 -示例 -list = {1, 2, 3, 4, 5} -table.insert(list, 6) --- {1, 2, 3, 4, 5, 6}`},{header:"删除元素",slug:"删除元素",content:`table.remove(table, pos) -示例 -list = {1, 2, 3, 4, 5} -table.remove(list, 2) --- {1, 3, 4, 5}`},{header:"table的排序",slug:"table的排序",content:""},{header:"默认排序方法",slug:"默认排序方法",content:`可以使用函数对列表进行排序,最简单的用法如下 -table.sort(list) -- 默认升序排序 -此处提供一个实验案例 --- 函数:打印列表 -function PrintList(list) -- 输出列表 local listStr = "" for i = 1, #list do listStr = listStr .. list[i] .. " " end print(listStr) -end local list = { 3, 7, 2, 5, 4 } -- 原始列表 PrintList(list) -- 输出原始列表 -table.sort(list) -- 对列表进行排序 -PrintList(list) -- 输出排序后的列表 -- 结果: --- 3 7 2 5 4 (原始列表) --- 2 3 4 5 7 (排序后的列表)`},{header:"自定义排序方法",slug:"自定义排序方法",content:`table.sort函数也可以使用自定义排序规则,但是这个规则你需要写在函数里。 -table.sort(list, function(a, b)) -function(a, b)是自定义的排序规则,要求最终返回一个bool值(true或false)。a和b分别为列表中的任意两项,如果函数返回true,则a在b的前面,否则b在a的前面。 -下面提供了2个示例供参考。`},{header:"示例1:上面代码改为降序输出",slug:"示例1-上面代码改为降序输出",content:`-- 此处省略PrintList()函数,函数代码与上方相同 local list = { 3, 7, 2, 5, 4 } -- 原始列表 PrintList(list) -- 输出原始列表 -table.sort(list, function(a, b) -- 对列表进行排序 return a > b -- 降序排序,如果a>b,则a在b前面 -end) -PrintList(list) -- 输出排序后的列表 -- 结果: --- 3 7 2 5 4 (原始列表) --- 7 5 4 3 2 (排序后的列表)`},{header:"示例2:二维数组中的排序",slug:"示例2-二维数组中的排序",content:`-- 函数:打印列表 -function PrintList(list) -- 输出列表 local listStr = "" for i = 1, #list do listStr = listStr .. "\\n" .. list[i][1] .. ", " .. list[i][2] end print(listStr) -end -- 原始列表 -local list = { { 3, 5 }, { 7, 6 }, { 2, 2 }, { 5, 1 }, { 4, 3 } } PrintList(list) -- 输出原始列表 -- 以列表中每项的第1维降序排序 -table.sort(list, function(a, b) return a[1] > b[1] -end) -PrintList(list) -- 输出排序后的列表 -- 以列表中每项的第2维降序排序 -table.sort(list, function(a, b) return a[2] > b[2] end) -PrintList(list) -- 输出排序后的列表 -- 结果: --- 原始列表: --- 3, 5 --- 7, 6 --- 2, 2 --- 5, 1 --- 4, 3 -- 以第1维降序排序: --- 7, 6 --- 5, 1 --- 4, 3 --- 3, 5 --- 2, 2 -- 以第2维降序排序: --- 7, 6 --- 3, 5 --- 4, 3 --- 2, 2 --- 5, 1`},{header:"table的引用",slug:"table的引用",content:`当没有对table进行对拷,而直接复制的时候,刚刚新得到的list2相当于原list1的引用,称为浅拷贝。当你修改浅拷贝得到的list2中的元素时,由于两个table是引用的关系,list1中的元素也会随之改变。 -上面的示例代码也遵循了这一原理。下面将用一个新的例子突出这一特点。`},{header:"示例:浅拷贝",slug:"示例-浅拷贝",content:`function PrintList(list) -- 输出列表 local listStr = "" for i = 1, #list do listStr = listStr .. list[i] .. " " end print(listStr) -end list1 = { 1, 2, 3, 4, 5 } -PrintList(list1) --- 1 2 3 4 5 list2 = list1 -PrintList(list2) --- 1 2 3 4 5 -- 修改list2的第2个元素 -list2[2] = 10 -PrintList(list2) --- 1 10 3 4 5 PrintList(list1) --- 1 10 3 4 5`},{header:"示例:深拷贝",slug:"示例-深拷贝",content:`而如果想要复制一个全新的列表list2怎么办呢?那么你就需要对table中的元素进行逐个复制,也称深拷贝。 --- PrintList函数代码与上方相同 list1 = { 1, 2, 3, 4, 5 } -PrintList(list1) --- 1 2 3 4 5 list2 = {} -- 新建一个空列表 -- 将list1的元素复制到list2 -for index, value in pairs(list1) do table.insert(list2, value) -end -PrintList(list2) --- 1 2 3 4 5 -- 修改list2的第2个元素 -list2[2] = 10 -PrintList(list2) --- 1 10 3 4 5 PrintList(list1) --- 1 2 3 4 5 (没有发生变化) -在这个例子中,修改深拷贝得到的list2中的元素并不会对原来的list1产生影响。`}]},{path:"/notes/mip-en.html",title:"Mixed integer programming",pathLocale:"/",contents:[{header:"Mixed integer programming",slug:"mixed-integer-programming",content:`Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web. Translate info -This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.`},{header:"Creating a Mixed-Integer Programming Model",slug:"creating-a-mixed-integer-programming-model",content:`Creating an integer programming model object. -local mip = math.newmip() -- Assign the created model object to mip`},{header:"Setting the Objective Function",slug:"setting-the-objective-function",content:`In MicroCity Web, the first line of the model is the objective function, added using the mip:addrow() function. -You can choose to maximize or minimize the objective function. The usage is as follows: Maximize -Minimize mip:addrow(coeff, 'max') -- Maximize the objective function mip:addrow(coeff, 'min') -- Minimize the objective function`},{header:"Parameter Description and Examples",slug:"parameter-description-and-examples",content:`Parameter -Purpose mip -Mathematical model object. Sets the objective function for the model coeff -Coefficients of the objective function, a table variable. Determines the coefficients of the objective function in the model. "min" or "max" -Determines whether to minimize or maximize the objective function. coeff is a list of coefficients for the objective function, a table variable. Suppose you want to minimize the function -4x1+12x2+18x3 -4x_1+12x_2+18x_3 -4x1​+12x2​+18x3​ -the approach to adding the objective function is as follows: --- Assuming you have already created the model object and stored it in the variable mip --- Set the objective function to 4*x1 + 12*x2 + 18*x3, minimize -mip:addrow({4, 12, 18}, "min")`},{header:"Adding Constraints",slug:"adding-constraints",content:""},{header:"Adding Constraint Equations",slug:"adding-constraint-equations",content:`In MicroCity Web, use mip:addrow() to add the remaining constraint equations. The usage is as follows: ≥ -= mip:addrow(cons, ">=", b) mip:addrow(cons, "==", b)`},{header:"Parameter Description",slug:"parameter-description",content:`Parameter -Purpose mip -The integer programming model object created at the beginning cons -Coefficients of the constraint equation. Like cons in setting the objective function, it's a table variable. Determines the coefficients of the variables in the constraint equation. "<=" or ">=" or "==" -Determines the relationship between the constraint equation and the right-hand side. b -The right-hand side of the constraint equation.`},{header:"Example",slug:"example",content:`The objective function has been set to 4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​. Suppose you want to add two constraint equations for this function: -{x1+3x3≥32x2+2x3≥5 -\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ -Add the corresponding constraint equations: --- Add constraint: x1 + 3*x3 ≥ 3 -mip:addrow({ 1, 0, 3 }, ">=", 3) -- Add constraint: 2*x2 + 2*x3 ≥ 5 -mip:addrow({ 0, 2, 2 }, ">=", 5) -It can be noticed that the number of coefficients is the same as the number of variables in the objective function. Therefore, before programming, it is necessary to determine the total number of variables and arrange the positions of each variable.`},{header:"Setting Variable Types",slug:"setting-variable-types",content:`MicroCity's mathematical programming supports integer programming. The default variable range is non-negative real numbers (≥0). Below is a detailed method for setting variable types. -You can set the i-th variable in the model as an integer variable or a 0-1 variable. If you don't set the variable to these types, it defaults to a non-negative real number. Integer Variable -0-1 Variable -- Set the first variable (first column, col 1) as an integer variable -mip:addrow('c1', 'int') -- Set the second variable (second column, col 2) as a 0-1 variable -mip:addrow('c2', 'bin')`},{header:"Model Solution and Output",slug:"model-solution-and-output",content:""},{header:"Model Solution",slug:"model-solution",content:`Since the objective function and constraint equations have been added, solving the model is straightforward: -mip:solve() -After executing this statement, the mathematical model stored in the variable mip is solved 🎉`},{header:"Output",slug:"output",content:`After solving, you still need to output; otherwise, you won't know the results. Below are some commonly used functions for outputting the solution. -Get the value of the objective function: -mip['obj'] -Get the value of the i-th variable: -mip['c'..i] -Here is a simple example from modeling to solving for reference. (It's just putting the pieces together) -Example: -minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N -minf=4x_1+12x_2+18x_3\\\\ -s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N -\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N represents the set of natural numbers (non-negative integers) Script -local mip = math.newmip() -- Set objective functio -mip:addrow({4, 12, 18}, "min") -- Add constraints -mip:addrow({ 1, 0, 3 }, ">=", 3) -- x1 + 3*x3 ≥ 3 -mip:addrow({ 0, 2, 2 }, ">=", 5) -- 2*x2 + 2*x3 ≥ 5 -- Set all variables as integers -for i = 1, 3 do mip:addrow('c'..i, 'int') -end -- Solve the model -mip:solve() -- Output the value of the objective function -print("Objective function value:", mip['obj']) -- Output the value of each variable -for i = 1, 3 do print("x"..i.."=",mip['c'..i]) -end -Output -Objective function value: 42.0 -x1= 0.0 -x2= 2.0 -x3= 1.0 Online Execution -Check this example in MicroCityWeb`},{header:"Some Modeling Techniques",slug:"some-modeling-techniques",content:""},{header:"Linearization",slug:"linearization",content:`Sometimes we encounter modeling problems with multiple subscripts, such as decision variables xijx_{ij}xij​, where iii and jjj are indices. In such cases, linearization encoding is necessary. -Suppose the decision variable itself has a shape of 3 rows and 4 columns, i.e.: Col 1 -Col 2 -Col 3 -Col 4 x11x_{11}x11​ -x12x_{12}x12​ -x13x_{13}x13​ -x14x_{14}x14​ x21x_{21}x21​ -x22x_{22}x22​ -x23x_{23}x23​ -x24x_{24}x24​ x31x_{31}x31​ -x32x_{32}x32​ -x33x_{33}x33​ -x34x_{34}x34​ Suppose the objective function wants to sum these decision variables, i.e. F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​. If you want to input this into the objective function, you can linearize it as x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​. -Since there are only two dimensions, you can use two for loops to achieve this: -local cons = {} -for i = 1, 3 do -- First dimension for j = 1, 4 do -- Second dimension cons[4 * (i - 1) + j] = 1 -- Fill in the coefficient -- The idea here is similar to carrying in arithmetic end -end`},{header:"Example: Assignment Model",slug:"example-assignment-model",content:`Now let's look at the specific usage of multi-dimensional linearization and its convenience using a practical example. -People A, B, C, and D deliver goods A, B, C, and D, respectively. The required time is shown in the table below. If each person delivers only one type of goods, which person should be assigned to deliver which type of goods to minimize the total time? Person\\Item -A -B -C -D A -14 -9 -4 -15 B -11 -7 -9 -10 C -13 -2 -10 -5 D -17 -9 -15 -13 Assuming goods A, B, C, D correspond to indices 1, 2, 3, 4, respectively, let xij=1x_{ij}=1xij​=1 represent person i delivering goods j, and xij=0x_{ij}=0xij​=0 represent person i not delivering goods j. -The mathematical model for the above problem can be represented as -minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 -minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ -s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 -\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ -Solution code --- Efficiency matrix -local cost = { {14, 9, 4, 15}, {11, 7, 9, 10}, {13, 2, 10, 5}, {17, 9, 15, 13} -} local mip = math.newmip() -- Create the objective function -local coeff = {} -for i = 1, 4 do for j = 1, 4 do -- Easily convert the 2D array to a 1D array here coeff[4 * (i - 1) + j] = cost[i][j] end -end mip:addrow(coeff, "min") -- Add constraints -for k = 1, 4 do -- Control the value of the first dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- Sum for j, check i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) -end for k = 1, 4 do -- Control the value of the second dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then -- Sum for i, check j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) -end -- Solve the model -mip:solve() -- Output the value of the objective function -print("Objective function value:", mip['obj']) -- Output the decision variables -for i = 1, 4 do -- First dimension for j = 1, 4 do -- Second dimension local x = mip['c' .. 4 * (i - 1) + j] if x ~= 0 then print("x[" .. i .. "][" .. j .. "]=", x) end end -end -Output -Objective function value: 29.0 -x[1][3]= 1.0 -x[2][1]= 1.0 -x[3][4]= 1.0 -x[4][2]= 1.0 Online Execution -Check this example in MicroCityWeb Result -Person -Item x13=1x_{13}=1x13​=1 -A -C x21=1x_{21}=1x21​=1 -B -A x34=1x_{34}=1x34​=1 -C -D x42=1x_{42}=1x42​=1 -D -B`},{header:"Handling Intermediate Variables",slug:"handling-intermediate-variables",content:`Sometimes, there are intermediate variables in a model that must have corresponding positions in the matrix to be solved, and these intermediate variables do not participate in the calculation of the objective function value. The coefficients of the intermediate variables at their corresponding positions can be set to 0. -Suppose x1,x2,x3,x4x_1, x_2, x_3, x_4x1​,x2​,x3​,x4​ are decision variables, and y1,y2y_1, y_2y1​,y2​ are intermediate variables. The objective function is: -z=∑i=14xi -z=\\sum_{i=1}^4x_i -z=i=1∑4​xi​ -The coefficients of the objective function can be set as follows: -local fcons = {1, 1, 1, 1, 0, 0} --- The first 4 elements correspond to decision variables, --- and the last 2 elements correspond to intermediate variables -Afterward, you can proceed with the general process 😎`}]},{path:"/notes/mip.html",title:"混合整数规划",pathLocale:"/",contents:[{header:"混合整数规划",slug:"混合整数规划",content:"本文档介绍MicroCity Web中混合整数规划的建模方法。"},{header:"创建混合整数规划模型",slug:"创建混合整数规划模型",content:`创建整数规划模型对象 -local mip = math.newmip() -- 将创建的模型对象赋值给 mip`},{header:"设置目标函数",slug:"设置目标函数",content:`MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。 -允许选择目标函数求最大值或最小值。具体用法如下: 最大值 -最小值 mip:addrow(coeff, 'max') --求最大值 mip:addrow(coeff, 'min') --求最小值`},{header:"参数说明及示例",slug:"参数说明及示例",content:`参数 -作用 mip -数学模型对象。将数学模型输入函数中,为模型设置目标函数 coeff -目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。 "min"或"max" -确定目标函数求最大还是求最小。 coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数 -4x1+12x2+18x3 -4x_1+12x_2+18x_3 -4x1​+12x2​+18x3​ -的最小值,则添加目标函数的做法如下: --- 假设你已经创建了模型对象,并存入变量mip中 --- 设定目标函数为 4*x1 + 12*x2 + 18*x3,求最小 -mip:addrow({4, 12, 18}, "min")`},{header:"添加约束",slug:"添加约束",content:""},{header:"添加约束方程",slug:"添加约束方程",content:`在MicroCity Web中,使用mip:addrow()添加剩下的约束方程,用法如下: ≤ -≥ -= mip:addrow(cons, "<=", b) mip:addrow(cons, ">=", b) mip:addrow(cons, "==", b)`},{header:"参数说明",slug:"参数说明",content:`参数 -作用 mip -一开始创建的整数规划模型对象 cons -约束方程系数。和设置目标函数中的cons一样,也是一个table类型的变量。用于确定约束方程中各个变量的系数。 "<=" 或 ">=" 或 "==" -确定约束方程与右端项的关系 b -约束方程的右端项。`},{header:"示例",slug:"示例",content:`上面已经设置了目标函数为4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​,假设你要为这个函数添加两个约束方程: -{x1+3x3≥32x2+2x3≥5 -\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ -添加对应约束方程: --- 添加约束:x1+3*x3≥3 -mip:addrow({ 1, 0, 3 }, ">=", 3) -- 添加约束:2*x2+2*x3≥5 -mip:addrow({ 0, 2, 2 }, ">=", 5) -不难注意到,系数的个数和目标函数中变量的个数一致。因此,在编程求解之前首先要搞清楚变量的总数,并安排好各个变量的位置。`},{header:"设置变量类型",slug:"设置变量类型",content:`MicroCity Web 中的数学规划支持整数规划。默认变量的取值范围是非负实数(≥0)。下面介绍变量类型设置的详细做法。 -你可以将模型中第i个变量设置为整数变量或0-1变量。如果不将变量设置为这些类型,则默认变量为非负实数。 整数变量 -0-1变量 mip:addrow('c1', 'int') --将第1个变量(第一列,col 1)设置为整数变量(Integer) mip:addrow('c2', 'bin') --将第2个变量(第二列,col 2)设置为0-1变量(Binary)`},{header:"模型求解和输出",slug:"模型求解和输出",content:""},{header:"模型求解",slug:"模型求解",content:`由于目标函数和约束方程都已经添加完毕,因此模型的求解就很简单了,只需要一步: -mip:solve() -执行完这条语句后,存放于变量mip内的数学模型就求解完毕了🎉`},{header:"输出",slug:"输出",content:`求解完还需要输出,否则就不知道求解的结果如何。以下是常用的输出求解结果的函数。 -获取目标函数值: -mip['obj'] -获取第i个变量的值: -mip['c'..i] -这里提供一个简单的从建模至求解的示例供参考。(其实就是将前面的拼起来) -算例: -minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N -minf=4x_1+12x_2+18x_3\\\\ -s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N -\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N表示自然数(非负整数集合) 脚本 -local mip = math.newmip() -- 设置目标函数 -mip:addrow({4, 12, 18}, "min") -- 添加约束 -mip:addrow({ 1, 0, 3 }, ">=", 3) -- x1+3*x3≥3 -mip:addrow({ 0, 2, 2 }, ">=", 5) -- 2*x2+2*x3≥5 -- 设置所有变量为整数 -for i = 1, 3 do mip:addrow('c'..i, 'int') -end -- 求解模型 -mip:solve() -- 输出目标函数值 -print("目标函数值:", mip['obj']) -- 输出各个变量的值 -for i = 1, 3 do print("x"..i.."=",mip['c'..i]) -end -输出结果 -目标函数值: 42.0 -x1= 0.0 -x2= 2.0 -x3= 1.0 在线运行 -在MicroCity Web中查看这个示例`},{header:"建模的一些技巧",slug:"建模的一些技巧",content:""},{header:"线性化",slug:"线性化",content:`有时候我们会遇到多下标的建模问题,如决策变量为xijx_{ij}xij​,这个时候就要将其进行线性化编码。 -假设决策变量本身的形状共有3行4列,即: 列1 -列2 -列3 -列4 x11x_{11}x11​ -x12x_{12}x12​ -x13x_{13}x13​ -x14x_{14}x14​ x21x_{21}x21​ -x22x_{22}x22​ -x23x_{23}x23​ -x24x_{24}x24​ x31x_{31}x31​ -x32x_{32}x32​ -x33x_{33}x33​ -x34x_{34}x34​ 假设目标函数要将这些决策变量求和,即 F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​ 如果要将其输入目标函数,此时可以将其线性化为 x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​ -由于只有两个维度,因此可以使用两个for实现: -local cons = {} -for i = 1, 3 do -- 第一维 for j = 1, 4 do -- 第二维 cons[4 * (i - 1) + j] = 1 -- 填入系数 -- 其中 4 * (i - 1) + j 的思想类似于进位 end -end --结果: --- cons长度为12,值都为1`},{header:"例题:指派模型",slug:"例题-指派模型",content:`下面以一个实际的例题来看看多维线性化的具体使用方法及其方便之处。 -甲、乙、丙、丁四人配送A,B,C,D四种货物,所需时间如表所示。若一种货物只交一人送货,则应指派何人配送何种货物,能使总的时间最少? 人\\工件 -A -B -C -D 甲 -14 -9 -4 -15 乙 -11 -7 -9 -10 丙 -13 -2 -10 -5 丁 -17 -9 -15 -13 假设货物A、B、C、D对应的编号依次为1、2、3、4,设 xij=1x_{ij}=1xij​=1 时表示第i个人送j货,xij=0x_{ij}=0xij​=0 时表示第i个人不送j货。 -则上述问题的数学模型可以表示为 -minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 -minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ -s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 -\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ -求解代码 --- 效率矩阵 -local cost = {{14, 9, 4, 15}, {11, 7, 9, 10}, {13, 2, 10, 5}, {17, 9, 15, 13}} local mip = math.newmip() -- 创建目标函数 -local coeff = {} -for i = 1, 4 do for j = 1, 4 do -- 此处可以轻松将二维数组转换为一维数组 coeff[4 * (i - 1) + j] = cost[i][j] end -end mip:addrow(coeff, "min") -- 添加约束 -for k = 1, 4 do -- 第i维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- j求和,判断i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) -end for k = 1, 4 do -- 第j维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then -- i求和,判断j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) -end -- 求解模型 -mip:solve() -- 输出目标函数值 -print("目标函数值:", mip['obj']) -- 输出决策变量 -for i = 1, 4 do -- 第一维 for j = 1, 4 do -- 第二维 local x = mip['c' .. 4 * (i - 1) + j] if x ~= 0 then print("x[" .. i .. "][" .. j .. "]=", x) end end -end -输出 -目标函数值: 29.0 -x[1][3]= 1.0 -x[2][1]= 1.0 -x[3][4]= 1.0 -x[4][2]= 1.0 在线运行 -在MicroCity Web中查看这个示例 结果 -人 -配送工件 x13=1x_{13}=1x13​=1 -甲 -C x21=1x_{21}=1x21​=1 -乙 -A x34=1x_{34}=1x34​=1 -丙 -D x42=1x_{42}=1x42​=1 -丁 -B`},{header:"中间变量的处理",slug:"中间变量的处理",content:`有时候模型中会存在一些中间变量,这些变量必须要在矩阵中有对应的位置才能对其进行求解,而这些中间变量不参与目标函数值的运算。可以将中间变量对应位置的系数设为0。 -假设x1,x2,x3,x4x_1,x_2,x_3,x_4x1​,x2​,x3​,x4​为决策变量,y1,y2y_1,y_2y1​,y2​为中间变量。目标函数为: -z=∑i=14xi -z=\\sum_{i=1}^4x_i -z=i=1∑4​xi​ -则目标函数系数可以设为: -local fcons = {1, 1, 1, 1, 0, 0} -- 前面4位为决策变量,后面2位为中间变量 -接下来按照一般流程做就可以啦😎`}]},{path:"/notes/network.html",title:"操作网络",pathLocale:"/",contents:[{header:"操作网络",slug:"操作网络",content:""},{header:"网络拓补化",slug:"网络拓补化",content:`网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题: 这条路是单向通行的还是双向通行? -这条路的起点是哪?终点是哪? 一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 这样,每条路就有了通行方向。一般规定出发点的符号为O,目的点的符号为D,这样,使用O和D就能清晰地描述每条路的方向。 -对于上图的示例,上方的道路O=1,D=2,所以方向描述为从1到2;下方的道路O=2,D=1,方向描述为从2到1。`},{header:"使用函数对网络进行拓补",slug:"使用函数对网络进行拓补",content:`MicroCity可以处理网络,所有函数的具体用法见参考文档:4.6 网络 -此处简单列举几种创建MicroCity中网络对象的方法: -local network = CreateNetwork() 创建一个空网络对象并返回此对象。network就是返回得到的空网络对象。 -创建对象后,可以使用AddLink和DelLink等函数在网络对象中创建连接。具体用法见参考文档。 -local network, nodes, links = CreateNetwork(Lines) -此处的Lines为一个矢量图形对象,类型为Line。MicroCity中的CreateNetwork()函数在这种用法中可以直接帮你在道路连线上添加起点和终点,并自动在返回的links对象中标上O点和D点的编号。 -也就是说,你只需要提供网络连线即可,剩下的拓补化工作可以由函数自动完成。我认为这可能是最常用的创建网络图并进行拓补化的方法。`},{header:"网络拓补的简单示例",slug:"网络拓补的简单示例",content:`-- 打开连线图层 -Shapes = Open("Shapes.shp") -- 拓补化网络 -network, network_nodes, network_links = CreateNetwork(Shapes) -- 创建图层,用于存放拓补后的网络节点 -Nodes = CreateShapes("Nodes", "point") --- 将拓补化网络得到的网络节点复制到图层中 -AddField(Nodes, "ID", "int") -for i = 1, GetRecCount(network_nodes) do CopyShapeTo(Nodes, 0, 0, GetShape(network_nodes, i)) -end -- 创建图层,用于存放拓补后的网络连线 -Links = CreateShapes("Links", "line") --- 将网络连线中原有的属性字段复制到图层中 -for i = 1, GetFieldCount(Shapes) do AddField(Links, GetField(Shapes, i)) -end --- 为连线添加属性字段,稍后会通过函数将对应的数据添加到其中 -AddField(Links, "ID", "int") -AddField(Links, "O", "int") -AddField(Links, "D", "int") -AddField(Links, "IMPEDANCE", "double") --阻抗 -AddField(Links, "DIRECTION", "int") --方向 -AddField(Links, "CAPACITY", "double") --容量 --- 将拓补化网络得到的网络线路复制到图层中(包括对应数据) -for i = 1, GetRecCount(network_links) do CopyShapeTo(Links, 0, 0, GetShape(network_links, i)) -end -- 更新图层 -Update(Nodes) -Update(Links) 示例改自MicroCity自带的编辑器 虽然一开始就输入了网络连线,但是在拓补化的过程中可能由于连线上的节点重合,在拓补化的过程中会把连续的连线拆成多段,因此得到的Links图层可能与输入的图层存在不同。而拓补化得到的节点Nodes和得到的连线Links是对应的,因此推荐使用拓补化处理完的Links图层作为网络节点之间的连线。`},{header:"踩坑经验:创建网络对象",slug:"踩坑经验-创建网络对象",content:`如果需要使用CreateNetwork(Nodes, Links)函数再次建立网络,需要保留以下在拓补化过程中添加的属性,否则将会出现网络初始化错误的问题: -AddField(Links, "ID", "int") -AddField(Links, "O", "int") -AddField(Links, "D", "int") -AddField(Links, "IMPEDANCE", "double") --阻抗 -AddField(Links, "DIRECTION", "int") --方向 -AddField(Links, "CAPACITY", "double") --容量 -如果只是一次性地进行网络拓补,不会再用拓补化过的网络重新创建网络对象,也需要先创建以上属性。拓补化后数据并不会根据属性名称填入,而是根据位置填入。 -如果只创建了O和D两个属性,则O的属性中会被填入ID数据,而D的属性中会被填入O的数据。而如果只根据上面的顺序创建了ID、O、D三个属性,由于数据顺序根据位置填入,则最终的填入的数据是正确的。`},{header:"CopyShapeTo函数",slug:"copyshapeto函数",content:`拓补的操作中使用了CopyShapeTo()函数,其作用是将一个Shape对象复制到Shapes图层中的对应位置,并根据输入的dx和dy在Shapes图层中进行位置变换。其中,dx和dy分别为在x和y方向上的位移量(理解为deltax和deltay)。 -CopyShapeTo(TargetShapes, dx, dy, Shape1 [, Shape2, ...]) -根据函数的用法可以看到,还支持复制到多个图层上的对应位置后再进行变换。 -如果只想将图形复制到对应图层的对应位置,而不进行变换,可以将dx和dy设为0,像这样: -CopyShapeTo(TargetShapes, 0, 0, Shape1 [, Shape2, ...]) -CopyShapeTo()函数的具体用法见 4.3 矢量图形和表格`},{header:"网络拓补化后算法的使用",slug:"网络拓补化后算法的使用",content:"对网络进行拓补化后,可以使用自带的函数求解很多问题,如:最短路径生成树、最短路径、最短距离等。本文以计算最短路径和最短路长为例介绍一下计算最短路径的流程及踩过的坑"},{header:"计算最短路径和最短路长",slug:"计算最短路径和最短路长",content:"要计算最短路径,首先必须要清楚计算网络中哪两个点之间的最短路径。这里以startID和endID分别表示起点和终点。本文假设你已经创建了网络对象,并存入名为Network的变量中。如果你不知道该如何创建一个网络图,可以参考上方介绍的 网络拓补化 流程。"},{header:"创建最小生成树",slug:"创建最小生成树",content:`第一步,先要以startID为开始点创建最短路径生成树。理论上以始点创建最短路径生成树后,就可以获取始点到网络上任意一点的最短距离。创建最短路径生成树可以调用GenSTPTree()函数实现。 -GenSTPTree(Network, startID [, endID]) -此处的endID不是必须的,如果有可以提供给函数。也就是说,您共有两种做法实现这一步: -GenSTPTree(Network, startID) --方法1 -GenSTPTree(Network, startID , endID) --方法2(建议) -一般认为提供的信息越完备,执行的效果越好。由于在计算最短路径之前就知道endID,因此建议将其提供给函数。 此处已经对函数的这种中括号写法进行了解释,后文中将会直接使用这种写法。 第二步,获取最短路径对应的信息。前面提到,确定起点和终点后才能确定两点之间的最短线路。由于前面使用始点startID创建了最小生成树,因此现在只需要提供终点endID就能获取到最短路径和最短路长。下面介绍了使用网络对象Network获取最短路长和最短路径的方法。`},{header:"获取最短路长",slug:"获取最短路长",content:`MicroCity的文档中提供了3种获取最短路径的方式。 -第一种,由于前面计算了最短路径生成树,已经输入了起始点的信息。因此现在只需要提供终点信息即可。(即使刚刚可能已经提供了终点信息)函数需要网络对象Network和终点endID用法如下。 -local len = GetSTPLen(Network, endID) -第二种,通过提供始点startID和终点endID计算两个点在网络上的最短路长。这种用法不要求在计算最短路径前先生成最短路径生成树,可以直接使用。Network为网络对象,用法如下: -local len = GetSTPLen(Network, startID, endID) -第三种,通过提供始点和终点的xy坐标计算两个点在网络上的最短路长。这种用法也不需要在计算最短路径前先生成最短路径生成树,可以直接使用。起点的坐标设为x1,y1;终点的坐标设为x2,y2,Network为网络对象,用法如下: -local len = GetSTPLen(Network, x1, y1, x2, y2)`},{header:"获取最短路径",slug:"获取最短路径",content:`MicroCity的文档中提供了3种信息可供获取,分别为: 点或线的ID序列 -点或线的索引(index)序列 -点或线的形状(Shape)序列。 函数的详细用法请参阅 4.6 网络 - 算法,此处仅以第2种:点或线的索引序列作为示例。 -返回点的序列: -GetSTPPath (Network, endID, "iNodeShp") -返回线的序列: -GetSTPPath (Network, endID, "iLinkShp") -这样就能返回所有点或线的索引序列了。`},{header:"踩坑经验:序列",slug:"踩坑经验-序列",content:`在Lua语言快速上手中介绍过Lua中的集合,它提供了丰富的特性帮助编写代码。但是没有听说过序列。序列是下面这个东西: -local x, y = GetCenterXY(Shapes) --借用一下这个函数 -里面的x,y就是一个序列。还有这种情况: -GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) --再次借用一个函数 -在这种情况下,输入的点越多,返回值也越多。如果输入4个点,可以这样处理: --- 正常情况 -d1, d2, d3, d4 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -- 也可以仅取前两个返回值 -d1, d2 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -- 当然,只取一个返回值也可以 -d1 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -上面的函数输入参数数量和输出参数数量是有关系的。如果输入了n个点的参数,就会返回n个点的距离。但是对于网络拓补来说,在返回最短路径的时候返回的都是参数序列,而我并不知道函数会给我传出多少个参数;而且当输出参数的个数太多的时候,也不太可能手动创建很多个变量存放这些参数。 --- 错误做法: -local indexList = GetSTPPath(Network, endID, "iLinkShp") --- GetSTPPath()函数不会返回一个table --- 这里获取到的indexList只是第一个Link的index,是一个数值。 -既然等号左边没有办法改变,就从等号右边做出改变。还记得怎么定义一个最简单的table吗? -local list = {1, 2, 3, 4, 5} -右边的1, 2, 3, 4, 5其实可以看做一个序列。所以,只要给函数的返回值加上括号就能把他们全部捞起来 ( •̀ ω •́ )✧ -local indexList = { GetSTPPath(Network, endID, "iLinkShp") } -上面的这种做法得到的indexList就是一个table类型的变量了。然后就可以开始执行集合的各种操作了捏😋`}]},{path:"/notes/oop.html",title:"面向对象编程",pathLocale:"/",contents:[{header:"面向对象编程",slug:"面向对象编程",content:`面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。 网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实现过对象的消息传递,如果实现了会继续更新本文。因此下面主要介绍一下如何在适用于MicroCity的lua代码中使用封装。 提示 -本文中的代码示例适用于MicroCityWeb,对于桌面版的MicroCity不一定适用。此外,本文均为个人感悟,不保证概念绝对的正确性。`},{header:"面向对象编程的基本概念",slug:"面向对象编程的基本概念",content:""},{header:"类和对象",slug:"类和对象",content:`通俗来说,类是对象的模板,对象是类的实例(实体)。 -类是面向对象编程的基本概念,它是对一类事物的抽象。类的概念可以理解为一类对象,比如AGV、货架、场桥等。你可以把类理解为一类事物的模板,而对象则是根据这个模板创建出来的具体的事物。 -一个比较好的例子是上面提到的货架。货架是一个类,那么具体的货架就是一个对象。货架类中包含了货架的各种属性,比如货架的位置,装载的货物等。通过货架类创建出来的不同的货架对象都属于货架类,比如货架1、货架2等,尽管它们的属性可能不同,但是它们都是货架类的对象。`},{header:"类的属性和方法",slug:"类的属性和方法",content:"在MicroCity的仿真中,就我个人遇到的情况而言,类一般会有属性,但是不一定会有方法。延续上面举的货架的例子来说,属性是类的特征,比如货架的位置、货架上的货物等。方法是类的行为,通常使用函数体现,比如AGV将货架抬起、放下、AGV移动或者带动货架移动。"},{header:"仿真中使用面向对象的优点和缺点",slug:"仿真中使用面向对象的优点和缺点",content:""},{header:"优点",slug:"优点",content:`在MicroCity中,就涉及到多个同类物体移动、播放物体移动动画等场景而言(如AGV、货架、场桥移动等),需要进行比较大量的坐标计算和位置设置。如果对每个对象都实现一次,那么修改各个对象坐标的代码将会非常冗长,而且不易于维护。如果使用面向对象的编程思想,可以将数据处理的代码封装成一个个的对象,也能使代码更加更具有可读性和可维护性。 -此外,如果在场景中创建多个同类对象,各个对象的参数也可能各不相同。如果使用面向对象的方法封装,可以将各个对象的参数封装在各个对象自身中。当仿真流程或者规模变得复杂时,能够增加代码的复用性。 -对于仿真来说,最重要的是搞清楚仿真的业务流程和业务逻辑。使用面向对象编程可以使仿真的业务流程和业务逻辑体现得更清晰,使代码的可读性提高,更具有可维护性。 此外,当需要修改一类对象的业务逻辑时,只需要进入类中修改即可。比如修改一个港口中所有场桥的调度算法,由于所有场桥共用一套调度算法,因此只需要修改一次即可。 -就我个人的情况而言,采用面向对象的方法封装对象时大多是希望创建一个通用的对象,然后在后续的仿真中通过自动或手动的方式创建多个同类对象,而各个对象的参数各不相同。这么做会使得代码通用性增加,而且也能够使得代码更加易懂,为后续的维护和修改提供便利,为大规模的仿真打下基础。`},{header:"缺点",slug:"缺点",content:"如果仿真规模很小,代码量不大的简单的操作,不建议使用面向对象的方法封装代码。 使用面向对象的方法会增加代码行数,甚至会使代码看起来显得比原问题更加复杂。(当然你要用也不会有什么后果,只是看起来会比较奇怪而已)具体可以参考下文提供的代码示例,不难发现,代码主要篇幅用在描述类及其业务逻辑上,而业务流程的代码很简单,且占比很小。"},{header:"面向对象在Lua中的实现",slug:"面向对象在lua中的实现",content:"在Lua中,面向对象的概念通常使用table实现。table是Lua中的一种数据结构,它可以用来表示数组、字典、对象等。在面向对象的编程中,table也可以用来表示对象。"},{header:"示例",slug:"示例",content:`由于MicroCity中创建的对象都是table,因此我们可以在创建对象时,将对象的属性直接封装在table中,然后返回这个table。 -下面是一个例子: --- 函数将返回一个AGV对象 -function AGV() -- 在MicroCity中创建一个AGV的3d对象 local agv = scene.addobj('/res/agv.glb') -- 设置对象的属性 agv.position = {0, 0, 0} -- 设置对象的位置 agv.speed = 1 -- 设置对象的速度 function agv:move(dx, dy, dz) agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- 修改对象坐标 agv:setpos(agv.position[1], agv.position[2], agv.position[3]) -- 设置对象位置 scene.render() -- 渲染场景,不建议在这里调用,这里只是为了演示 end return agv -- 返回对象 -end -- 对象的使用 -local obj = AGV() --创建对象 -obj:move(1, 0, 0) --对象向x方向移动1个单位 -或者你也可以选择在创建对象后,将对象的封装在一个table中,然后返回这个table。 --- 函数将返回一个AGV对象 -function AGV() -- 直接在要返回的table中设置对象属性 local agv = { object = scene.addobj('/res/agv.glb'), position = {0, 0, 0}, speed = 1 } function agv:move(dx, dy, dz) agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- 修改对象坐标 agv.object:setpos(agv.position[1], agv.position[2], agv.position[3]) -- 设置对象位置 scene.render() -- 渲染场景,不建议在这里调用,这里只是为了演示 end return agv -- 返回对象 -end -- 对象的使用 -local agv = AGV() --创建对象 -agv:move(1, 0, 0) --对象向x方向移动1个单位 -还有一种创建对象的方法是使用setmetatable,这属于高级用法,但是感觉用到的场景不多后来我也用得比较少了。但是使用这种方法好像可以实现类的继承,如果你感兴趣可以自行搜索。这里提供我早期作业中创建货架类的代码实现供参考。(现在感觉这个类写得不算很好😂,比如 x,y 可以用 pos = {x, y} 代替,x_origin 和 y_origin 可以使用 origin = {x, y} 代替) --- 货架 -Shelf = { x = 1, y = 1, cargo = {"box"}, -- 货物 x_origin = 1, -- 货架原始x坐标 y_origin = 1 -- 货架原始y坐标 -} function Shelf:New(x, y) local self = {} setmetatable(self, { __index = Shelf }) self.__index = self self.x = x self.y = y -- 设置原始坐标 self.x_origin = x self.y_origin = y return self -end`},{header:"类的类型",slug:"类的类型",content:`我在这里还想总结一下我创建过的类主要有什么类型。 3D实体类。 主要控制3D实体的运动,如AGV、场桥等,它们大多具有实体且需要移动。有的甚至还包含子对象,比如场桥对象具有吊具、绳索、吊车等子对象。 -数据模型。 比如堆场,货架、货物。具体来说比如堆场类中包含堆场的长宽、堆场中的货物、堆场中的集装箱等数据。 需要注意的是,我认为这些类型也不是严格区分的,某些类甚至共同具有这些类的特性,严格区分这个类属于哪种类型也没有太大意义。比如AGV类中也包含了AGV的位置、速度等数据,而货架类只是存储了货架模型,货架模型的移动还是交由AGV控制,而其更重要的功能是记录货架上货物的信息。因此,我认为这些类型只是一种大致的划分,具体的实现还是要根据实际业务流程和需求情况来。`}]},{path:"/notes/plots.html",title:"通用绘图代码",pathLocale:"/",contents:[{header:"通用绘图代码",slug:"通用绘图代码",content:`本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。 相关信息 -本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。`},{header:"直方图",slug:"直方图",content:`直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的分布情况。 -以下是用我包装的直方图对象绘制的直方图的示例`},{header:"导入直方图",slug:"导入直方图",content:'首先导入直方图的代码。目前有两种选择: 下载代码文件并导入(推荐):下载直方图代码文件 Histogram.lua,在MicroCityWeb中导入该文件,再引用该文件后即可使用。引用的代码如下: require("Histogram") --引用直方图 复制代码:直接将Histogram.lua文件中的代码复制到你的代码中,代码见下方。'},{header:"创建直方图对象",slug:"创建直方图对象",content:`创建一个直方图对象 -local plot = Histogram(list) -- list为数据集 -还可以在创建对象时对图的属性进行设置。 -local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end}) -属性的设置不是必须的,可以仅根据需要设置。此处就只设置了range、scale、fdisp属性。`},{header:"直方图属性设置",slug:"直方图属性设置",content:`上面提供了直方图属性设置的简单例子。根据代码,还可以设置更多的属性。具体见下表: 属性值 -作用 -示例 origin -设置图原点(左下角点) -origin = {-50, -50},将图的原点设置在(-50,-50)的位置 size -设置图横纵轴长度,可以理解为图的大小 -size = {100, 100},将图的x轴和y轴长度分别设置为100、100 scale -设置横纵坐标轴的分度值 -scale = {3, 2},将图的x轴和y轴分度值分别设置为3和2 axislabel -设置横纵轴标题 -axislabel = {"x", "y"},将图的x轴和y轴标题分别设置为"x"和"y" range -设置横纵坐标轴的显示范围 -range = {0, 10, 0, 20},将图的x轴范围设置为[0,10],y轴范围设置为[0,20] filled -设置是否填充柱状图 -filled = false,将柱状图设置为空心。默认样式为填充 fdisp -数据标签的显示函数,默认返回数量。设置数据标签显示函数时也会影响y轴刻度的显示。 -fdisp = function(v) return (v/n*100).."%" end,将数据标签改为按照比例显示(假设n为样本数)`},{header:"直方图高级用法",slug:"直方图高级用法",content:"动态刷新数据图 修改图中的数据。此处以向图中添加数据为例。其中假设rnd为添加的数据。也可以直接修改plot.data的值。 table.insert(plot.data, rnd) 刷新图 plot:refresh()"},{header:"示例",slug:"示例",content:""},{header:"基本用法示例:绘制泊松分布",slug:"基本用法示例-绘制泊松分布",content:`require("Histogram") --引用直方图 local seed = math.randomseed(1, { distribution = "poisson", mu = "3" -}) -local list = {seed:random()} --静态绘制 -for i = #list, 400 do table.insert(list, seed:random()) -end local histplot = Histogram(list, { range = {0, 10, 0, 50}, scale = {1, 5} -}) -scene.render()`},{header:"高级用法示例:动态刷新绘制泊松分布",slug:"高级用法示例-动态刷新绘制泊松分布",content:`这是一个绘制泊松分布并动态刷新数据图的示例。假设已经导入了Histogram对象,并将场景设为二维显示。 -require("Histogram") --引用直方图 local seed = math.randomseed(1, { distribution = "poisson", mu = "3" -}) -local list = {seed:random()} local histplot = Histogram(list, { range = {0, 10, 0, 50}, scale = {1, 8} -}) -scene.render() -- 动态绘制 -local count = 1 -while count < 1000 do local rnd = seed:random() table.insert(histplot.data, rnd) histplot:refresh() count = count + 1 scene.render() -end`},{header:"子图",slug:"子图",content:"子图(Subplot)是为了解决同时在界面中放置多个图的图定位和尺寸问题。名称借鉴自MATLAB。"},{header:"导入子图",slug:"导入子图",content:'首先导入直方图的代码。与直方图一样,导入有两种选择: 下载代码文件并导入(推荐):下载子图代码文件,在MicroCityWeb中导入Subplot.lua文件,再引用该文件后即可使用。引用的代码如下: require("Subplot") --引入子图代码 复制代码:直接将Subplot.lua文件中的代码复制到你的代码中。这样就不需要导入了。代码见下方。'},{header:"创建子图对象",slug:"创建子图对象",content:`创建子图时必须输入子图的行数和列数。子图的行数和列数决定了子图的数量。 -local subplot = Subplot(rows, cols) -还可以设置附加属性,对子图的位置和尺寸进行设置。这是一个在创建时设置子图位置和尺寸的例子。 -local subplot = Subplot(rows, cols, {span=10, diag={-80, -70, 80, 70}})`},{header:"子图属性设置",slug:"子图属性设置",content:`此处将对子图的属性进行详细说明。属性的设置不是必须的,可以仅根据需要设置。 属性 -作用 -示例 span -设置子图之间的间隔 -span=10,设置子图上下左右之间的间隔为10 diag -通过输入对角线两个点的坐标设置子图位置和大小 -diag = {-80, -70, 80, 70},设置子图的对角线范围从坐标 (−80,−70)(-80,-70)(−80,−70) 到坐标 (80,70)(80,70)(80,70)`},{header:"子图值读取",slug:"子图值读取",content:`通过属性创建子图后,或者修改子图属性并刷新后,可以对子图的计算值进行读取,获取Subplot中各个子图的原点位置和尺寸。主要通过以下几个属性值进行读取。 注 -此处假设子图对象创建后存放于 subplot 变量中。 计算属性 -含义 -示例 originpt -Subplot对象中各个子图的原点位置 -通过subplot.originpt[i][j][1]和subplot.originpt[i][j][2]能够获取到第i行j列的子图对应的原点位置 psize -Subplot对象中各个子图的尺寸 -通过subplot.psize[1]和subplot.psize[2]能够获取到subplot中子图对应的宽度和高度。(假设子图中所有图所需尺寸相同)`},{header:"示例",slug:"示例-1",content:`这是一个绘制子图范围的示例。假设已经导入了Subplot对象,并将场景设为二维显示。 -此处将一个2行3列子图中各个子图的显示范围绘制为一个矩形。其中子图范围用四个灰色点表示,子图位置用蓝色矩形表示。 -require("Subplot") --引入子图代码 local subplot = Subplot(2, 3, {span = 10}) -- 绘制Subplot对象边界点 -local lb = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[2],0}}) -local lt = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[4],0}}) -local rb = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[4],0}}) -local rt = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[2],0}}) -- 绘制范围 -for i = 1, subplot.row do for j = 1, subplot.col do scene.addobj("polyline", {size = 8, color = "blue", vertices={ subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0, subplot.originpt[i][j][1], subplot.originpt[i][j][2], 0, subplot.originpt[i][j][1], subplot.originpt[i][j][2]+subplot.psize[2], 0, subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2]+subplot.psize[2], 0, subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0, } }) end -end -scene.render()`},{header:"代码",slug:"代码",content:"可以根据代码的组合情况删去开头的 scene.setenv 代码。代码中的 scene.render() 是为了在动态绘制时刷新图像。"},{header:"代码文件下载",slug:"代码文件下载",content:`代码文件列表见 ModelResource/libs 名称 -链接 直方图 -ModelResource/libs/Histogram.lua 子图 -ModelResource/libs/Subplot.lua`},{header:"直方图代码",slug:"直方图代码",content:`Histogram --- 初始场景设置 -local s = scene.setenv({camtype = "ortho"}) -- 返回一个直方图对象 -function Histogram(data, ...) local plot = { -- 默认值设置 origin = {-50, -50}, --坐标原点坐标 size = {100, 100}, --坐标轴长度 scale = {3, 2}, --坐标轴刻度分度值 range = {0, 10, 0, 20}, --xy轴范围 axislabel = {"x", "y"}, filled = true, --是否填充 fdisp = function(v) --数据标签显示 return v end, } -- 导入参数和fallback if ... ~= nil then for k, v in pairs(...) do plot[k] = v end end local barShape = "polygon" if plot.filled==false then barShape = "polyline" end -- 初始化 plot.axes = {} -- 坐标轴 plot.originlabel = {} -- 零点可能存在双坐标 plot.bars = {} -- 数据条 plot.xvalue = {} -- x轴刻度值(不包括最小值) plot.data = data function plot:deldata() --删除数据(private) if #plot.bars == 0 then return end for i = #plot.bars, 1, -1 do -- print("plot.bar:",i) plot.bars[i][2]:delete() plot.bars[i][1]:delete() end plot.zero:delete() for i = #plot.originlabel, 1, -1 do plot.originlabel[i]:delete() end for i = #plot.axes, 1, -1 do for j = #plot.axes[i], 1, -1 do plot.axes[i][j][2]:delete() plot.axes[i][j][1]:delete() end end end function plot:refresh() --反复绘图时调用(public) plot:deldata() -- 计算坐标刻度参数 local xmax = math.max(math.max(table.unpack(plot.data)), plot.range[2]) local xmin = math.min(math.min(table.unpack(plot.data)), plot.range[1]) local valueRange = xmax - xmin plot.range[1], plot.range[2] = xmin, xmax -- 绘图值统计 local barData = {} for i = 1, #data do -- 深拷贝 table.insert(barData, data[i]) end plot.barValue = {} -- 绘制零点 plot.zero = scene.addobj("points", { vertices = {plot.origin[1], plot.origin[2], 0}, size = 10 }) if plot.range[1] == plot.range[3] then -- 都是0 plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1] - 4, plot.origin[2] - 4, 0) else plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1], plot.origin[2] - 4, 0) plot.originlabel[2] = scene.addobj("label", { text = plot.range[3], size = 4 }) plot.originlabel[2]:setpos(plot.origin[1] - 4, plot.origin[2], 0) end -- X坐标刻度 local xaxis = {} -- x坐标轴对象,其中元素为{point,label} for j = 1, (plot.range[2] - plot.range[1]) / plot.scale[1] do -- 第几个刻度 local xpt = plot.origin[1] + j * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] -- X刻度位置 local pt = scene.addobj("points", { vertices = {xpt, plot.origin[2], 0}, size = 5 }) -- 刻度点 local label = scene.addobj("label", { text = string.format("%.1f", plot.range[1] + j * plot.scale[1]), size = 4 }) -- 刻度标签 table.insert(plot.xvalue, plot.range[1] + j * plot.scale[1]) -- 当前x刻度值 label:setpos(xpt, plot.origin[2] - 4, 0) xaxis[j] = {pt, label} -- 对象加入x轴集合 end plot.axes[1] = xaxis for i = 1, #plot.axes[1] do -- 根据x轴分值 local ub = plot.xvalue[i] -- 本次循环最大值 -- print("循环", i, "ub=", ub) -- for debug local value = 0 for j = #barData, 1, -1 do if barData[j] <= ub then value = value + 1 table.remove(barData, j) end end plot.barValue[i] = value -- 录入值 end local ymax = math.max(table.unpack(plot.barValue)) plot.range[4] = math.max(ymax, plot.range[4]) -- Y坐标刻度 local yaxis = {} -- y坐标轴对象,其中元素为{point,label} for i = 1, (plot.range[4] - plot.range[3]) / plot.scale[2] do -- 第几个刻度 local ypt = plot.origin[2] + i * plot.size[2] / (plot.range[4] - plot.range[3]) * plot.scale[2] -- Y刻度位置 local pt = scene.addobj("points", { vertices = {plot.origin[1], ypt, 0}, size = 5 }) -- 刻度点 local label = scene.addobj("label", { text = plot.fdisp(plot.range[3] + i * plot.scale[2]), size = 4 }) -- 刻度标签 label:setpos(plot.origin[1] - 4, ypt, 0) yaxis[i] = {pt, label} end plot.axes[2] = yaxis -- 绘制数据 local xunit = plot.size[1] / (plot.range[2] - plot.range[1]) * #plot.axes[1] -- x轴分度值 local yunit = plot.size[2] / (plot.range[4] - plot.range[3]) -- y轴分度值 -- 根据数值绘制直方图 for i = 1, #plot.axes[1] do -- 绘图 local xl = plot.origin[1] + (i - 1) * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] local xr = plot.origin[1] + i * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] local yb, yt = plot.origin[2], plot.origin[2] + plot.barValue[i] * yunit local bar = scene.addobj(barShape, { vertices = {xl, yb, 0, xr, yb, 0, xr, yt, 0, xl, yt, 0, xl, yb, 0} }) local label = scene.addobj("label", { text = plot.fdisp(plot.barValue[i]), size = 4 }) label:setpos((xl + xr) / 2, yt + 2, 0) plot.bars[i] = {bar, label} end end function plot:draw() --初始化绘制 -- 坐标轴对象 plot.coord = scene.addobj("polyline", { vertices = {plot.origin[1] + plot.size[1], plot.origin[2], 0, plot.origin[1], plot.origin[2], 0, plot.origin[1], plot.origin[2] + plot.size[2], 0} }) -- 坐标轴标题 if plot.axislabel~=nil then plot.axislabel[1] = scene.addobj("label", { text = plot.axislabel[1], size = 4 }) plot.axislabel[1]:setpos(plot.origin[1] + plot.size[1], plot.origin[2] - 8, 0) plot.axislabel[2] = scene.addobj("label", { text = plot.axislabel[2], size = 4, }) plot.axislabel[2]:setpos(plot.origin[1]-4, plot.origin[2] + plot.size[2]+6, 0) plot.axislabel[2]:setrot(0,0,1) end end plot:draw() plot:refresh() scene.render() return plot -end`},{header:"子图代码",slug:"子图代码",content:`Subplot --- 属性参数 --- local diag = {-80, -70, 80, 70} --lbx,lby,rtx,rty --- local span = 10 --- local row, col = 2, 2 -function Subplot(row, col, ...) local subplot = { span = 10, diag = {-80, -70, 80, 70}, originpt = {}, --存放各行列点坐标 psize = {} --子图大小 } subplot.row, subplot.col = row, col -- 导入参数和fallback if ... ~= nil then for k, v in pairs(...) do subplot[k] = v end end function subplot:refresh() -- 计算参数 subplot.psize = { (subplot.diag[3]-subplot.diag[1] - (subplot.col-1)*subplot.span)/subplot.col, (subplot.diag[4]-subplot.diag[2] - (subplot.row-1)*subplot.span)/subplot.row } local gwidth, gheight = subplot.psize[1]+subplot.span, subplot.psize[2]+subplot.span -- 重新计算originpt subplot.originpt = {} for i = 1, subplot.row do subplot.originpt[i]={} for j = 1, subplot.col do subplot.originpt[i][j] = {subplot.diag[1]+(j-1)*gwidth, subplot.diag[2]+(i-1)*gheight} end end end subplot:refresh() return subplot -end`}]},{path:"/notes/timelapse.html",title:"时间推进法",pathLocale:"/",contents:[{header:"时间推进法",slug:"时间推进法",content:"仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。"},{header:"时间推进法的分类",slug:"时间推进法的分类",content:`常见的仿真时间推进方法有三大类: 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。 -固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。 -主导时钟推进法:主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。`},{header:"实例",slug:"实例",content:""},{header:"事件调度法",slug:"事件调度法",content:`事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。在仿真过程中,仿真系统会根据当前仿真时间和各个事件发生的时间来确定下一个要发生的事件,并将仿真时间推进到该事件发生的时间。 -事件调度法主要分为以下3个主要步骤,这3个步骤也是控制事件调度法的主控程序的主要步骤: 时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻 -事件辨识:正确地辨识当前要发生的事件 -事件执行:正确地执行当前发生的事件 事件调度法基本原理流程图如下: -事件调度法在MicroCityWeb中的具体实现参见 离散事件模拟和程序控制 - 协程`},{header:"固定增量推进法",slug:"固定增量推进法",content:"固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。在每个步长内,若无事件发生,则仿真钟再推进一个单位时间T;若在该步内有若干个事件发生,则认为这些事件均发生在该步的结束时刻。 例题"},{header:"代码流程示例",slug:"代码流程示例",content:`while scene.render() do t = t + dt if t % cycle ~= work_time then d = d + v * dt print("出发后", t, "小时") else print("出发后", t, "小时,休息") end car:setpos(CastToLine(d)) --直线轨迹 os.sleep(200) -end 此为代码主要流程,无法直接使用`},{header:"主导时钟推进法",slug:"主导时钟推进法",content:`主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。主导时钟推进法可以分为两类:同步主导时钟和异步主导时钟。同步主导时钟是指所有模块都使用相同的主导时钟进行推进;异步主导时钟是指不同模块使用不同的主导时钟进行推进。 -自动化仓库仿真思路的最后一部分提到了改进空间,最终实现了同步主导时钟的主导时钟推进法。 实现了但是没有放出代码`},{header:"自动化仓库仿真向主导时钟推进法的改变",slug:"自动化仓库仿真向主导时钟推进法的改变",content:`具体来说,只在原来的基础上做了如下改动: 删除大部分与事件调度法有关的 os.sleep()。由于仿真流程比较简单,保留了与装卸货有关的事件调度法,优化资源占用。 -设置全局仿真时钟,将 Agv:Move() 函数的思路从“固定步长执行任务并刷新场景”的改为“监测仿真时钟时长变化,根据时长变化执行任务并刷新场景” -新增仿真速度调整。 从以上的改动可以看出,仿真的核心从事件任务转向了仿真时钟。其中,场景刷新的部分使用了 os.clock() 实现。`},{header:"主导时钟推进法实例",slug:"主导时钟推进法实例",content:`下面是一个有关于主导时钟推进法和 os.clock() 函数的简单的示例,修改自MicroCityWeb中内置的方块旋转案例。 -local obj = scene.addobj('box') -- 初始位置 -local x = 1 -local y = 1 -local z = 0 local rx, ry = 0.1, 0.1 -- x方向和y方向的旋转速度 -local simspeed = 10 -- 仿真速度 local t = 0 -- 全局仿真时钟 -local t0 = os.clock() -- 记录仿真开始的时间 -while scene.render() do local dt = os.clock() - t0 -- 计算自上次记录时间以来的时间差 t = t + dt -- 仿真时钟走过相应时间差长度的时间 -- 设置方块此刻的旋转位置 x = x + rx * dt * simspeed y = y + ry * dt * simspeed obj:setrot(x, y, z) t0 = os.clock() -- 记录仿真时间 -end -相关说明 当仿真速度 simspeed 为1时,表示仿真时钟与真实世界时钟的速度相同。simspeed 可以视作加速倍率。 -dt 表示两次记录时间之间的时间差,仿真中的时间步进根据 dt*simspeed 计算得到。 -相关信息 -需要注意的是,时间增量 dt 的数值在每个循环周期一般都不相同,dt 的具体大小一般取决于电脑的运算能力 提示 -有时两次记录时间之间没有太多耗时的操作,计算得到的 dt 可能为0。一般两次时间记录之间存在一个 scene.render(),这样一般能够保证两次采样的时间之间能够计算得到一个不为0的时间差值。`}]},{path:"/notes/tools.html",title:"有关工具",pathLocale:"/",contents:[{header:"有关工具",slug:"有关工具",content:`可能能够用到的工具 MapShaper 地图编辑器。可以编辑.geojson文件并导出为.shp文件 -Three.js Editor Three.js的在线3D对象编辑器。 🔨 持续更新...`}]},{path:"/notes/versions.html",title:"MicroCity的版本",pathLocale:"/",contents:[{header:"MicroCity的版本",slug:"microcity的版本",content:""},{header:"MicroCity",slug:"microcity",content:"MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwind)意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他操作系统,比如MacOS、Linux等。"},{header:"MicroCityWeb",slug:"microcityweb",content:`🎯访问MicroCity Web 📍(离线版)下载 -为了解决这个问题,开发者决定开发 MicroCity Web,这是一个可以直接在浏览器中运行的版本。 MicroCity Web 不需要任何安装,只需要使用现代浏览器(如Google Chrome、Microsoft Edge)访问它的网站即可。虽然相比于桌面版,运行在浏览器上可能会造成一定的性能损失,但是这使得用户可以在几乎任何操作系统上使用该软件,比如电脑系统Windows、MacOS、Linux和手机/平板系统Android等。 -尽管MicroCity的开发者推出了 MicroCity Web,您仍然可以继续使用以前开发的桌面版MicroCity。然而,桌面版本将不再更新新功能,所有新的功能和改进都将集中在 MicroCity Web 版中。这个决定的目的是确保 MicroCity 能够专注于一种版本,并在这个版本中提供最好的体验。这也使得 MicroCity 更容易管理和维护,避免了版本控制问题。 -值得一提的是,尽管桌面版本不再更新新功能,它仍然可以继续使用。如果用户已经习惯使用桌面版本,他们可以继续使用它。然而,如果用户希望体验最新的功能和改进,则需要改用 MicroCity Web 版。 -MicroCity Web 版也提供使用浏览器打包导出的离线版本(见上方 🔗链接)。 注意 -但是由于 Chromium 浏览器内核的更新,某些老旧的系统版本可能不受支持(如 Windows 8.1 及以下的 Windows 版本、32 位的 Windows 操作系统等)`},{header:"兼容性",slug:"兼容性",content:`MicroCity Web 版使用 Lua 5.4 作为脚本语言编写脚本。您可以在 MicroCity Web 运行环境或编辑器中输入 print(_VERSION) 指令查看使用的 Lua 版本。 -由于使用了实验性的 JavaScript函数,MicroCity Web 可能在以下浏览器内核中运行存在兼容性问题: iOS和iPad OS上的大多数浏览器(由于Apple强制使用Safari的浏览器内核) -FireFox浏览器 2023/9/29测试遇到的兼容性问题及部分技术细节 iOS 和 iPad OS: 无法打开本地文件(由于使用了 showOpenFilePicker() 方法) FireFox: 无法打开本地文件(由于使用了 showOpenFilePicker() 方法) 关于 showOpenFilePicker() 方法的影响参见 MDN Web Docs | showOpenFilePicker()`},{header:"总结",slug:"总结",content:`MicroCity Web 版的推出使得软件更加易用和普及,让更多的用户可以从中受益。同时,MicroCity 桌面版本仍然可用,使得那些已经习惯于使用该版本的用户可以继续使用,并让他们更容易地过渡到 MicroCity Web 版。 -本文作者在写这篇笔记的时候 MicroCity Web 正在被第一次用于教学环境中,已经基本能够正常运行并实现一定的仿真功能。本文作者的学习经历如下: MicroCity(桌面版):物流信息管理 -MicroCity Web :物流系统仿真 本站笔记内容仅供参考。如果本文内容由于时间的因素出现偏差,也欢迎各位在 Github 上通过 Pull Request 的方式对本站内容进行修正🥳`}]},{path:"/notes/visualization.html",title:"结果可视化",pathLocale:"/",contents:[{header:"结果可视化",slug:"结果可视化",content:"本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。"},{header:"改变形状颜色",slug:"改变形状颜色",content:`在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项: Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。 -Lookup Table:通过数值查询表格显示对应的颜色。 -Graduated Color:根据表中数值大小设置渐变色。`},{header:"Lookup Table 通过表中值改变颜色",slug:"lookup-table-通过表中值改变颜色",content:"将Type的属性值改为Lookup Table,根据表格中的数值改变图形的颜色,达到选中指定图形的效果。 此处示例将Lookup Table中的Attribute改为表格中的SELECT,通过表中的SELECT列值控制线的颜色(属性设置见上图)。当值为0时显示黑色,值为1时显示红色。表格中SELECT列的值和Lookup Table中的具体设置如下图。 最终实现的效果"},{header:"Graduated Color 根据值的大小显示渐变色",slug:"graduated-color-根据值的大小显示渐变色",content:"将Type的属性值改为Graduated Color,根据表格中不同数值的大小显示不同的颜色,达到显示渐变色的效果。 此处示例根据每个国家的人口数量显示渐变色。可以看到中国人口数量大,因此显示红色,印度人口数量也较大,因此显示橙色。其他地区人口数量较低,但也能通过颜色看出一些差别。 Graduated Color下的Colors属性中还可以调整其他配色方案。设置界面如下图,此处就不不一一列举了。 如果感兴趣可以参考文档2.1 展示世界地图中的示例手动尝试更改此属性。"},{header:"更改图形和标签的显示大小",slug:"更改图形和标签的显示大小",content:""},{header:"参考系的选择",slug:"参考系的选择",content:`显示内容尺寸的参考系有2个,一个是以地图为参考系,一个是以屏幕为参考系。此处将图形和标签的显示尺寸都设置为相同的参考系。 -内容以地图为参考系时,显示内容的大小会根据地图大小同步缩放,如下图: (以地图为参考系放大) (以地图为参考系缩小) 内容以屏幕为参考系时,无论地图怎么缩放内容的大小都差不多,如下图: (以屏幕为参考系放大) (以屏幕为参考系缩小) 因此,绘图的时候要根据绘图的目的选定参考系。 如果需要在地图上绘制确定尺寸的形状或者标明确定尺寸的标签,如绘制一个半径为10km的圆,此时应选用以地图为参考系。 -如果仅需要在任何尺寸下都能清晰显示标签和图形,此时可以选择以屏幕为参考系。`},{header:"参考系应用实例",slug:"参考系应用实例",content:"在图中绘制圆点,将圆的半径设置为圆的大小,并将圆的中心设置在每个绿点的中心上,灰色圆的大小表示每个绿点的覆盖范围大小。 图中以地图为参考系(Map Units),以16为半径为每个绿点都绘制了一个灰色的圆,表示每个绿点的覆盖范围。这些灰色的圆存放在名为Range.shp的图层内,图层类型为Points。"},{header:"参考系的设定",slug:"参考系的设定",content:`在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。 如图标记的两个位置可以分别调整图形尺寸的参考系和标签尺寸的参考系。 图形尺寸参考系设置:Size栏目下的Size relates to...调整图形尺寸的参考系,Default Size调整图形的相对于坐标系的尺寸。 -标签尺寸参考系设置:Labels栏目下的Size relates to...调整标签尺寸的参考系,Default Size调整的是标签(Labels)相对于坐标系的尺寸。`},{header:"更改显示的标签",slug:"更改显示的标签",content:""},{header:"手动更改显示的标签",slug:"手动更改显示的标签",content:`在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。上图中显示的标签为ID,如果需要改为表格中的其他列,可以更改Lables栏目下的Attribute属性实现。 -需要更改的属性位置如图,图中需要显示表中对应MSG列的值,只需要将Labels栏目下的Attribute属性值改为MSG即可。 但是每次更改图形并执行Update()函数后标签(Label)会取消显示。如果需要执行的脚本中含有此对于此图层的Update()函数,不必在每次执行完脚本后手动重新设置显示的标签,可以通过脚本自动选择显示的标签。`},{header:"自动更改显示的标签",slug:"自动更改显示的标签",content:`通过SetParameter()函数可以更改属性值。以上图Labels栏目下的Attribute属性为例,选中这条属性后可以看到底栏显示其ID为LABEL_ATTRIB,其类型为Choice。 需要注意的是,当类型为Choice时,参数值从1开始编号,编号顺次对应下拉菜单的内容。 点开这条属性以后,可以看到MSG在第二个。 由于Lua中编号一般由1开始,因此此处ID的编号对应1,MSG的编号对应2。需要操作对象为MSG,所以函数中需要填入Choice类型的参数值为2。 -此时已经得到了所有需要的参数,可以使用SetParameter()函数对显示的标签进行更改。 --- transports为图形图层 -SetParameter(transports, "LABEL_ATTRIB", 2) SetParameter()函数需要在Update()函数执行后再执行,否则效果会被Update()函数覆盖。 现在回过头来再看看SetParameter()函数的具体用法: -SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object) 参数 -含义 参数1 -输入的对象,可以是Shapes、Table、Grid、Scene、Module 参数2 -其中的id为属性对应的ID。如果是上文的情况,就是LABEL_ATTRIB 参数3 -如果需要更改属性值,只接受数值(Number)、字符串(String)、对象(Object)三种类型 SetParameter()函数的介绍出现在文档 4.2 控制用户界面 中,请参阅。`},{header:"借助栅格图",slug:"借助栅格图",content:`栅格图也可以用于可视化,我认为栅格图最常用的场景就是绘制热力图。热力图的绘制主要通过修改栅格图上每个格子的值实现。如果不清楚栅格图的具体结构,可以先参考文档 3.3 栅格图。关于使用脚本控制栅格图,可以参考文档 4.4 栅格图形。 -一种使用栅格图绘制热力图的场景就是绘制地价图。在绘制地价图时,我们可以遍历栅格图上的每个格点,计算该格点到每个仓库的距离之和。然后将该格点的值设置为这个值,就可以得到一张热力图。这种方法可以帮助我们可视化地价的分布情况,并且可以用来发现地价的趋势和规律。`}]},{path:"/notes/warehouse-simulation.html",title:"自动化仓库仿真思路",pathLocale:"/",contents:[{header:"自动化仓库仿真思路",slug:"自动化仓库仿真思路",content:"本文思路仅供参考,建议做出适当改进。"},{header:"具体问题:基于元胞自动机的仓库仿真",slug:"具体问题-基于元胞自动机的仓库仿真",content:`其中,出入库位置可以更改,叉车为AGV。 -也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。`},{header:"基本假设",slug:"基本假设",content:`所有货架上的货物相同 -一个货架只放一个货物 因此,出库和入库可以看做完全相反的过程,所以此处只需要详细讨论出库的情况。即默认货架上本身就有货物。`},{header:"总体实现思路",slug:"总体实现思路",content:`将整个 3×33\\times33×3 的仓库中每个元胞的位置赋予 (x,y)(x,y)(x,y) 坐标,方便后续的移动操作。 -以AGV为核心,对货架进行操作。AGV处于升起状态移动货架时,只需要将货架的坐标位置同步设为AGV的位置即可达到AGV移动货架的效果。`},{header:"业务流程",slug:"业务流程",content:"先按照需求数量乱序生成订单列表,AGV根据订单顺序依次将货架移动到出库点进行出库操作。"},{header:"业务逻辑",slug:"业务逻辑",content:`当执行出库时,AGV先找到最近的货架并移动到那个货架的位置,抬起货架。为货架(AGV)设定移动的终点,计算曼哈顿距离差值。 每次移动前都通过是否有障碍物判断货架移动的方向(xxx 方向或 yyy 方向)。 -如果两个方向都被堵塞,则优先选择 yyy 方向(人为规定),将这个方向的障碍物递归移走,为货架移动腾出空间。如果 yyy 方向没有空间才选择移动 xxx 方向。`},{header:"过程优化:关于旧方法和新方法",slug:"过程优化-关于旧方法和新方法",content:`这两种方法都是可用的方法,但是 新方法对特定场景进行了优化,通过对障碍进行预判减少了操作步骤。 问题见下图 -旧方法:无障碍预判(进出货点在 x=3,y=3x=3,y=3x=3,y=3 的位置) 👉 AGV完成第一个货架的出库后,向第二个货架移动,但是发现第一个货架挡住了去路,因此又回到第一个货架的位置将其移开,再回到第二个货架进行出库操作。 -新方法:预判障碍(进出货点在 x=3,y=3x=3,y=3x=3,y=3 的位置) 👉 AGV完成第一个货架的出库操作后判断后一个货架是否需要移动其他位置的货架才能到达出入库点。如果需要,则移动障碍货架后才前往后一个货架进行出库。 相关信息 -本着尽量少占用出入库点的原则,当有空位时AGV将把在出入口的货架移走。因此某些看起来冗余的操作并非没有考虑全面。 不同数量货架对应的最优布局方案(动图) -8个货架的情况,上面已经进行了展示。下面仅展示表中货架数为5和7的情况。其他情况详见附件。`},{header:"仿真数据收集分析",slug:"仿真数据收集分析",content:""},{header:"出入库效率最高",slug:"出入库效率最高",content:`仿真结果如下图所示,表示相同货架数量下得到的效率最佳货架的货架布局 最佳货架布局:相同货架数量下,取出所有货物操作次数(ticks)最小 布局图说明 白色:没有放置货架 -浅灰色:货架,但是AGV一开始位于这个货架下方 -灰色:货架。 表格说明 货架数量:存在于布局图中的货架数量 -旧ticks:使用旧方法(无预判障碍)实现取货的操作次数。 -新ticks:使用新方法(预判障碍)实现取货的操作次数。后面将对新方法进行说明。 -黄色高亮:相同布局下操作次数最少(ticks最小)的方案`},{header:"空间利用率最大",slug:"空间利用率最大",content:`如果所有位置都放置货架,则无法访问到所有货架。因此,空间利用率最大的方法是放置8个货架。 -颜色说明 绿色:有货物的货架 -紫色:没有货物的货架 -浅紫色:AGV抬起的货架 -深紫色:AGV在这个货架下面,但是没有抬起货架 -深灰色:进出货点 有时候刷新太快可能看不出AGV抬起 进出货点在x=2,y=3的位置`},{header:"创新点",slug:"创新点",content:`额外考虑货物种类不同的情况。 -每次仿真会根据货架上的货物乱序生成需求。 -面向对象编程。使用面向对象的思想编程有助于将问题抽象化、有助于流程细节的改进;再加上好的命名方式会让整个程序的流程和逻辑清晰很多,不至于睡一觉起来就忘了😂 不同的货物类型用不同的颜色表示。AGV状态颜色、空货架的颜色、进出库点的颜色含义与之前相同。 紫色:没有货物的货架 -浅紫色:AGV抬起的货架 -深紫色:AGV在这个货架下面,但是没有抬起货架 -深灰色:进出货点 5个货架的情况示例 8个货架的情况示例`},{header:"仿真改进:三维化自动仓库仿真",slug:"仿真改进-三维化自动仓库仿真",content:"在这一部分题目也稍微有所变化,要求将元胞自动机仿真仓库案例三维化,进行自动化仓库仿真。具体要求如上图。"},{header:"总体思路",slug:"总体思路",content:""},{header:"三维化",slug:"三维化",content:`以基于元胞自动机的仓库仿真为核心,将其中元胞自动机仿真的部分改写为内部数据表,作为内部数据模型,对整个仿真过程的状态进行监视和控制。 -由于基于元胞自动机的仓库仿真使用了面向对象的方法封装对象,业务逻辑和流程的构建中大面积使用了对象方法,因此此处只需要改写对象方法(如 Agv:Move(dx, dy) 等)即可实现由元胞自动机仿真到三维化自动仓库的仿真。 如果程序整体结构设计优良,应用“面向对象”将会大幅提升程序的可维护性,降低移植难度。 对于AGV、货架直接套用现成模型;对于货物,只需要设置其距离货架的相对高度列表即可实现货物自动存放于指定高度。 提示 -如果需要套用现成模型,或者申请上传模型到本文作者维护的仓库,请参考文档 3D对象-外部模型`},{header:"出入库需求波动极大",slug:"出入库需求波动极大",content:`根据题目要求,基本上只存在有限的2种情况:3个货架、6个货架。 -由于货架数量情况有限,而基于元胞自动机的仓库仿真中得到了性能最佳的仓库布局,因此可以直接套用对应货架数量的最佳布局,本问题中只需要考虑固定货架布局下货物的位置摆放问题。 -对于3个货架的情况,其最佳布局属于高度对称的形态,距离出入库点的距离都为1,因此这种情况下只需要对1种情况进行仿真、收集其数据。 -对于6个货架的情况,选取了3种情况进行多次仿真,得到每种情况出入库耗费Ticks的平均值、最大值、最小值。 当前Ticks是AGV移动的次数,相当于单位操作时间。后文改进空间中提到了可以进行的改进 经过以上分析可以看出情况有限,因此可以通过控制货物需求总数不变,每次随机生成需求货物种类的方式对各种货物摆放位置进行仿真、对得到数据进行分析,最终确定最佳的货物布局方案。`},{header:"改进",slug:"改进",content:`在测试的过程中发现原有移动货架的策略不合理,改进了移动货架的策略。 -旧策略: 找到离AGV最近的装有需求货物的货架,将其移动到出入库点。 可以看到AGV已经将需要出库的同种货物(青色方块)移动到了出入库点,但是由于AGV移动的货架对象是旁边的货架,因此没有对已经在出入库点的货物进行出库。 -新策略: 找到离出入库点最近的装有需求货物的货架,将其移动到出入库点。改变策略后,没有发现以上提到的不合理情况出现。`},{header:"创新",slug:"创新",content:`由于测试的次数较多,因此将主体流程写入函数并进行适应性改进,实现自动对所有情况进行仿真测试并将数据输出。下图为自动仿真测试运行为示例。 自动仿真测试流程代码,仅供参考 --- 批量测试 -local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- 测试需求(上限)序列 local output_string_list = {} -- 测试结果列表字符串 -for k, v in ipairs(cargo_ubs) do local test_result = {} -- 本需求上限测试结果序列 cargo_ub = v -- 设置需求数量上限 for j = 1, test_count do scene.setenv({ grid = 'plane', clear = true }) -- 清空场景内容 print("测试(", j, "/", test_count, "):需求数量为", cargo_ub) local tick = ModelRun() -- 运行仿真模型返回测试结果 table.insert(test_result, tick) -- 将测试结果插入测试结果序列 end local output_string = "" print("需求数量为", cargo_ub, "的测试结果序列:") for i = 1, #test_result do -- 输出测试结果序列到列表字符串 output_string = output_string .. test_result[i] .. "\\t" end print(output_string) table.insert(output_string_list, output_string) -end -- 输出测试测试结果列表 -for i, str in ipairs(output_string_list) do print("需求数量为", cargo_ubs[i], "的测试结果序列:", str) -end -在自动仿真测试的过程中发现了BUG,详见下文说明。`},{header:"货架布局方案",slug:"货架布局方案",content:`颜色说明 浅蓝色:出入库点 -白色:空格 -深蓝、红、黄:3种货物对应的颜色 条件假设 每个货架上都放有2个同类货物 -货物需求随机,没有种类偏好 -每次只取出一个货物`},{header:"仿真结果及分析",slug:"仿真结果及分析",content:"对每个货物布局方案中每种需求数量的情况仿真测试30次,求单方案结果中的最大值、最小值、平均值。最终得到结论为在6个货架的情况中,方案2的布局表现最优。"},{header:"方案3:3个货架",slug:"方案3-3个货架",content:""},{header:"方案6",slug:"方案6",content:"方案6平均Ticks总趋势图 方案6最优布局方案:方案2 还应绘制分方案的“需求量-最短平均服务时间”单位趋势图。以下以方案6-1为例,横坐标为货物需求数量,纵轴为最短平均服务时间(Ticks)。"},{header:"改进空间",slug:"改进空间",content:`由于题目没有给定具体事件的执行时间,也没有指定时间单位,因此此处只计量货架的操作次数作为耗费的时间。也就是说,时间是后计算的,我想大部分同学做到这里可能都是这样的思路。虽然最终得出的结果没有问题,但是思路还可以转变一下,适应于后面的学习。 -当前思路是以任务驱动的。虽然能够得到一个正确的结果,但是没有利用仿真时间,这种做法在只控制一个实体的时候不会出现问题。当要同时处理多个实体的时候,当前思路就无法做到同时操作多个实体完成任务,只能实现多个实体依次完成任务的情况。当前思路的具体流程如下: -由于应用的是时间推进法,因此仿真世界中有属于它自己的时间。对于我们来说,我们可以通过在仿真时间上乘一个倍率实现控制仿真速度,这个倍率就是仿真速度。此外,这种做法更加容易支持考虑多对象的情况。具体流程如下: -这样就改为了以时间为核心的仿真,在刷新任务执行进度的时候就可以直接刷新场景中的所有实体。由于仿真以时间为核心,因此就需要设定各种操作的速率/时间,保证时间计算的准确性。在MicroCityWeb中,有一些技巧可以用于时间推进法的仿真。`},{header:"使用系统时间更新仿真时间",slug:"使用系统时间更新仿真时间",content:`os.clock()函数可以获取系统当前的时间(以秒为单位,但是是小数)。有了这个函数就可以做到仿真与现实时间的同步。用法示例可以参考时间推进法 -由于整个仿真的核心为时间,因此需要对之前没有规定的操作规定其需要花费的时间长度。在改进的部分中,又额外考虑了以下操作所要花费的时间: 货物出入库所要花费的时间 -AGV举起和降落货架所要花费的时间`}]},{path:"/notes/web-ui-en.html",title:"Introduction to the User Interface",pathLocale:"/",contents:[{header:"Introduction to the User Interface",slug:"introduction-to-the-user-interface",content:"The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb."},{header:"Overview of Interface Zones",slug:"overview-of-interface-zones",content:`Overall, the interface of MicroCityWeb can be roughly divided into four areas: Top - Blue Area: performs various operations on code and files -Left - Green Area: code editor -Right - Red Area: view area -Bottom - Yellow Area: output information, recognize program running status Next, we will provide a detailed description of the usage and functions of these areas.`},{header:"Blue: Command Area",slug:"blue-command-area",content:"The content of this area is shown in the following figure, with nine available buttons."},{header:"Program Control",slug:"program-control",content:"The first three buttons are mainly used to control program execution. Their specific functions are as follows: Run/Debug: Clicking the left mouse button will run the code in the code editor on the left-hand side of the webpage, while right-clicking will debug the code. Pause: If the program is running, clicking this button will pause its execution (if supported). Stop/Force Stop: If the program is running, clicking the left mouse button will stop its execution. If left-clicking does not stop the script, right-clicking can forcibly terminate its execution."},{header:"Code Editing",slug:"code-editing",content:`Buttons 4-7 are mainly related to code editing. Show/Hide Editor: If the left code editor is open, clicking this button will close it. If it's closed, clicking it will reopen it. If you right-click, the editor can be expanded to full screen. Open Built-In Code: You can directly load built-in code (import built-in models), such as cubes, trucks, earth, world maps, etc. The specific models will be introduced in detail when the red canvas area is introduced. Built-in code list Open Local Code: -Left-click: A dialog box will pop up when you left-click, and you can choose a code file (.lua) on your local machine. After confirming the selection to open the file, the text of the code file will be automatically imported into the code editor on the left. -Right-click: You can select one or more files to upload to MicroCityWeb by right-clicking. The "Save" button (⑦) on the right can be clicked to view the list of uploaded files. Save Code: -Left-click: When you save a file for the first time, a save file dialog box will pop up after you click the save button. You can choose the save location and fill in the file name. If you have previously saved the file locally and you have made modifications to the file and want to save the changes, you can simply click the save button to save the changes directly to the previously saved file. -Right-click: You can view the list of uploaded files, and you can click on a file in the list and download it to your local machine.`},{header:"Others",slug:"others",content:`Share. After clicking the button, a dialog box for entering a password will pop up. Afterwards, you will receive a link that anyone can use to access your share. -If you enter a password in the dialog box, others who open the link can only run your program code and observe the running result, but cannot view your code (unless you tell them the password); if you do not enter a password, others can not only run your code to view the running result but also view the code you have written. View help documentation.`},{header:"Green: Code Editor",slug:"green-code-editor",content:"The integrated code editor on the left side of MicroCityWeb is based on AceEditor and therefore has some of its features."},{header:"Keyboard Shortcuts",slug:"keyboard-shortcuts",content:`Below are some commonly used keyboard shortcuts to help you edit code more efficiently. -Most Common -Ctrl+Z: Undo -Line Operations -Ctrl+D: Delete a line -Ctrl+Shift+D: Duplicate a line -Alt+↑: Move line of code up -Alt+↓: Move line of code down -Find Content -Ctrl+K: Find the next occurrence of selected content in the code -Indentation -Ctrl+[: Increase code indentation -Ctrl+]: Decrease code indentation -Modify Values -Ctrl+Shift+↑: Increase the numeric value before the cursor by 1 -Ctrl+Shift+↓: Decrease the numeric value before the cursor by 1`},{header:"Red: Canvas area",slug:"red-canvas-area",content:`Built-in code can be imported into the scene, see Command Area - Code Editing for details. -After importing the scene code, click the "Run" button to load the scene. Built-in car model Built-in Earth model`},{header:"Scene Operations",slug:"scene-operations",content:`Scene operations, including viewpoint movement and rotation, need to be performed in the canvas area. Therefore, the following will introduce the basic operations of the canvas area. Zooming in and out of the scene: Scroll the mouse wheel up to zoom in and down to zoom out. -Translation: Hold down the right mouse button and drag. -Rotation Scene rotation: Hold down the left mouse button and drag to rotate from your viewpoint. -Object rotation: Click on the object, the color of the object changes, and then hold down the left mouse button on the object to rotate around the object's center. These operation rules apply to both two-dimensional and three-dimensional objects.`},{header:"Yellow: Code Output Area",slug:"yellow-code-output-area",content:`After opening MicroCityWeb, the code output area is shown below. Clicking on the code output area will cause the entire area to move up, allowing you to see more historical output information. Regarding the information output in this area, the code output area will output the following information: Script output: The left side is the output of the script, including the output time and content. -Script running status: The first line on the right side shows the script running status. "state: ready" indicates that the script is ready to start running (not yet running), and "state: running" indicates that the script is running. -MicroCityWeb version number: Indicates the current version number of MicroCityWeb being used. If there is a difference from the known version, you can force a refresh to load the latest version.`},{header:"Notes",slug:"notes",content:"Turn off automatic translation: If your operating system language is not English and the browser has automatic translation enabled, it needs to be manually disabled, otherwise there will be errors when running the code."}]},{path:"/notes/web-ui.html",title:"用户界面简介",pathLocale:"/",contents:[{header:"用户界面简介",slug:"用户界面简介",content:"MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。"},{header:"界面分区概览",slug:"界面分区概览",content:`整体来看,MicroCity Web的界面大致可以划分为4个区域。 顶部-蓝色区域:对代码、文件执行各种操作 -左侧-绿色区域:代码编辑器 -右侧-红色区域:视图区域 -底部-黄色区域:输出信息、识别程序运行状态 下面将详细介绍这几个区域的用法和功能。`},{header:"蓝色:命令区域",slug:"蓝色-命令区域",content:"此区域的的内容如下图所示,共有9个可用按钮。"},{header:"程序控制",slug:"程序控制",content:"前3个按钮的功能大致都用于控制程序运行。详细作用分别如下: 开始运行/debug: 左键点击后将运行网页左侧代码编辑器内的代码;右键点击后进行代码调试(debug) 暂停运行: 如果程序正在运行,点击后程序将暂停运行(如果程序支持)。 停止运行/强行停止: 如果程序正在运行,左键点击后程序将停止运行。有时存在左键点击无法停止运行脚本的情况,右键点击可以强行终止其运行。"},{header:"代码编辑",slug:"代码编辑",content:`编号4~7的按钮主要与代码编辑有关。 显示/隐藏编辑器。 如果左侧的代码编辑器为开启状态,点击这个按钮后将关闭。如果为关闭状态,点击后会重新打开。如果使用右键点击,编辑器可以展开到全屏状态。 打开内置的代码 可以直接载入内置的代码(导入内置模型),如立方体、卡车、地球、世界地图等。具体的模型将在介绍画布区域时详细介绍。 内置代码列表 打开本地代码/上传文件 -左键点击:弹出打开文件的对话框,您可以选择本机上的某个代码文件(.lua)。确定打开文件后,代码文件文本将自动导入到左侧代码编辑器中。 -右键点击:可以选择一个或多个文件上传到MicroCity Web中。右键“保存”按钮(⑦)可以查看已上传的文件列表。 保存代码/下载 -左键点击:当您第一次保存文件时,点击保存按钮后会弹出保存文件对话框,您可以选择保存位置并填写文件名。如果您之前已经将该文件保存到本地,而此时您又对该文件进行了修改并想要保存更改,直接点击保存按钮即可直接将更改保存到之前保存的文件中。 -右键点击:可以查看已上传的文件列表,您可以点击列表中的文件并下载到本地。`},{header:"其他",slug:"其他",content:`共享。 点击按钮后,将会弹出一个输入密码的对话框。随后,您将会得到一个链接,任何人都可以通过这个链接打开您的共享。 -如果您在弹出的对话框中输入了密码,那么在其他人打开链接后,他们只能运行您的程序代码并观察运行结果,而无法查看您的代码(除非您告知他们密码);如果您没有输入密码,则其他人不仅可以运行您的代码查看运行结果,还可以查看您编写的代码。 查看帮助文档。`},{header:"绿色:代码编辑器",slug:"绿色-代码编辑器",content:"MicroCity Web左侧整合的代码编辑器源于AceEditor,因此也具有AceEditor的一些特性。"},{header:"快捷键",slug:"快捷键",content:`下面将介绍一些常用的快捷键,帮助你更好地编辑代码。 -最常用 Ctrl+Z:撤销 行操作 Ctrl+D:删除一行 -Ctrl+Shift+D:复制一行 -Alt+↑:行代码上移 -Alt+↓:行代码下移 查找内容 Ctrl+K:在代码中查找下一个与选中内容 代码缩进 Ctrl+[:增加代码缩进 -Ctrl+]:减少代码缩进 修改数值 Ctrl+Shift+↑:光标前的数字数值+1 -Ctrl+Shift+↓:光标前的数字数值-1`},{header:"红色:画布区域",slug:"红色-画布区域",content:"可以从内置代码导入场景,详见 命令区域 - 代码编辑 导入场景代码后要点击“运行”按钮才会载入场景 内置汽车模型 内置地球模型"},{header:"场景操作",slug:"场景操作",content:`对场景的操作包括视角移动、旋转都需要在画布区域进行。因此,下面将介绍画布区域的基本操作。 场景的放大缩小:鼠标滚轮向上滚动为放大,向下滚动为缩小。 -平移:按住鼠标右键拖动。 -旋转 场景旋转:按住鼠标左键拖动,以你的视角进行旋转 -对象旋转:点击对象,对象颜色改变后从对象上按住鼠标左键拖动,以对象为中心旋转。 无论是二维对象还是三维对象都遵循上述操作逻辑。`},{header:"黄色:代码输出区域",slug:"黄色-代码输出区域",content:`打开MicroCity Web后,代码输出区域如下。点击代码输出区域后整个区域会上移,能够看到更多的历史输出信息。 说到这个区域输出的信息,代码输出区域会输出以下信息: 脚本输出: 左侧是脚本的输出,包含输出时间、脚本输出内容。 -脚本运行状态: 右边第一行为脚本运行状态。state:ready表示脚本已经准备好开始运行(未运行),state:running表示脚本正在运行。 -MicroCityWeb版本号: 表示当前使用的MicroCityWeb版本号。如果与已知版本有差异,可以通过强制刷新加载最新版本。`},{header:"注意事项",slug:"注意事项",content:"关闭自动翻译: 如果你的操作系统语言不是英语且浏览器开启了自动翻译,需要手动关闭,否则代码运行将出现错误。"}]},{path:"/docs/imgs/",title:"",pathLocale:"/",contents:[{header:"",slug:"",content:"This folder contains images used by documentation pages."}]},{path:"/404.html",title:"",pathLocale:"/",contents:[]}],F="update-vuepress-plugin-full-text-search2-search-index";var C=f(V),W=w(()=>{const e=new Map;for(const t of C.value)e.set(t.path,t);return e});import.meta.webpackHot&&(__VUE_HMR_RUNTIME__[F]=e=>{C.value=e});function B(e){const t=f([]);let s=null;return A(e,()=>{s&&clearTimeout(s),s=setTimeout(i,100)}),t;function i(){const c=e.value.toLowerCase().trim();if(!c){t.value=[];return}const a=new Map,n=new Set;for(const o of C.value)for(const r of q(o,c)){n.add(r.parentPageTitle);let l=a.get(r.parentPageTitle);l||(l=[],a.set(r.parentPageTitle,l)),l.push(r)}const d=[...n].sort((o,r)=>{const l=a.get(o);return a.get(r).length-l.length});t.value=[...a].flatMap(([,o])=>o).sort((o,r)=>o.parentPagePriority-r.parentPagePriority||d.indexOf(o.parentPageTitle)-d.indexOf(r.parentPageTitle)||o.priority-r.priority)}}function*q(e,t){const s=v(e.title,t);if(s){yield{path:e.path,parentPageTitle:j(e),title:e.title,display:s,page:e,content:null,parentPagePriority:1,priority:1};return}for(const i of e.contents){const c=v(i.header,t);if(c){yield{path:e.path+(i.slug?`#${i.slug}`:""),parentPageTitle:j(e),title:e.title,display:c,page:e,content:null,parentPagePriority:10,priority:2};continue}const a=v(i.content,t);a&&(yield{path:e.path+(i.slug?`#${i.slug}`:""),parentPageTitle:j(e),title:e.title,display:[{type:"header",str:`${i.header} -`},...a],page:e,content:null,parentPagePriority:10,priority:10})}}function j(e){const t=e.path.split("/");let s="/";return t[1]&&(s=`/${t[1]}/`),(W.value.get(s)||e).title}function v(e,t){const s=[];let i=0;const c=e.toLowerCase().replace(/\s/gu," ");let a=0,n=c.indexOf(t,a);if(n<0)return null;for(;n>=0;){const o=n+t.length;if(d(e.slice(a,n),"normal"),d(e.slice(n,o),"highlight"),a=o,n=c.indexOf(t,a),i>100)break}return d(e.slice(a),"normal"),s.filter(o=>o.str);function d(o,r){let l=o;r==="normal"&&l.length>100&&i===0&&(l=`… ${l.slice(-10)}`);let g=!1;if(i+l.length>100){if(s.some(b=>b.type==="ellipsis"))return;l=l.slice(0,Math.max(100-i,1)),g=!0}s.push({type:r,str:l}),i+=l.length,g&&(s.push({type:"ellipsis",str:" …"}),i+=2)}}var U={"/":{placeholder:"搜索"}};const Y=U,H=L({name:"SearchBox",props:{locales:{type:Object,required:!1,default:()=>Y}},setup(e){const{locales:t}=D(e),s=f(""),i=f(!1),c=f(-1),a=B(s),n=w(()=>s.value&&i.value&&a.value.length),d=I(),o=z(),r=w(()=>t.value[o.value]??{});function l(){if(!n.value)return;let h=c.value-1;h<0&&(h=a.value.length-1),b(h)}function g(){if(!n.value)return;let h=c.value+1;h>=a.value.length&&(h=0),b(h)}function b(h){c.value=h}function _(){c.value=-1}function G(h){if(!n.value)return;const M=a.value[h];M&&d.push(M.path)}return{query:s,focused:i,focusIndex:c,suggestions:a,activeSuggestion:n,onUp:l,onDown:g,focus:b,unfocus:_,go:G,locale:r}}}),X={class:"search-box",role:"search"},Z=["placeholder"],$=["onMousedown","onMouseenter"],K=["href"],Q={key:0,class:"parent-page-title"},J={class:"suggestion-row"},ee={class:"page-title"},te={class:"suggestion-content"};function ne(e,t,s,i,c,a){return u(),p("div",X,[N(m("input",{ref:"input","onUpdate:modelValue":t[0]||(t[0]=n=>e.query=n),"aria-label":"Search",class:x({focused:e.focused}),placeholder:e.locale.placeholder??"Search",autocomplete:"off",spellcheck:"false",onFocus:t[1]||(t[1]=()=>e.focused=!0),onBlur:t[2]||(t[2]=()=>e.focused=!1),onKeyup:[t[3]||(t[3]=y(n=>e.go(e.focusIndex),["enter"])),t[4]||(t[4]=y((...n)=>e.onUp&&e.onUp(...n),["up"])),t[5]||(t[5]=y((...n)=>e.onDown&&e.onDown(...n),["down"]))]},null,42,Z),[[O,e.query]]),e.activeSuggestion?(u(),p("ul",{key:0,class:"suggestions",onMouseleave:t[7]||(t[7]=(...n)=>e.unfocus&&e.unfocus(...n))},[(u(!0),p(k,null,T(e.suggestions,(n,d)=>(u(),p("li",{key:d,class:x(["suggestion",{focused:d===e.focusIndex}]),onMousedown:o=>e.go(d),onMouseenter:o=>e.focus(d)},[m("a",{href:n.path,onClick:t[6]||(t[6]=E(()=>{},["prevent"]))},[n.parentPageTitle&&(!e.suggestions[d-1]||e.suggestions[d-1].parentPageTitle!==n.parentPageTitle)?(u(),p("div",Q,S(n.parentPageTitle),1)):P("v-if",!0),m("div",J,[m("div",ee,S(n.title||n.path),1),m("div",te,[(u(!0),p(k,null,T(n.display,(o,r)=>(u(),p("span",{key:r,class:x(o.type)},S(o.str),3))),128))])])],8,K)],42,$))),128))],32)):P("v-if",!0)])}const ie=R(H,[["render",ne],["__scopeId","data-v-fd6cd4d5"],["__file","SearchBox.vue"]]);export{ie as default}; diff --git a/assets/SearchBox-dgLZwYTI.js b/assets/SearchBox-dgLZwYTI.js new file mode 100644 index 00000000..756ba256 --- /dev/null +++ b/assets/SearchBox-dgLZwYTI.js @@ -0,0 +1,2621 @@ +import{g as b,h as j,i as L,j as D,t as I,u as _,k as z,_ as O,o as u,c as p,l as N,v as R,a as f,n as y,m as x,F as T,p as M,q as v,f as G,s as E}from"./app-LOf__QKq.js";const V=[{path:"/",title:"首页",pathLocale:"/",contents:[{header:"开始使用MicroCity Web",slug:"开始使用microcity-web",content:"打开MicroCity Web,默认加载方块旋转的示例代码。 点击运行按钮运行代码 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用技巧,可以参阅本站提供的 学习笔记"},{header:"开始使用MicroCity Desktop",slug:"开始使用microcity-desktop",content:'转到MicroCity的文档仓库下载 MicroCity的最新版本 打开 ScriptEditor 并输入: Print("hello, world!") 将脚本另存为 test.mcs 并将其拖入 MicroCity 在程序主界面左侧转到 Modules 标签页,打开 test ,双击其中的 main ,执行刚刚编写的脚本。 程序界面下方的 Messages 栏中会输出执行脚本的信息。 更多MicroCity的使用方法可以参考本站搬运自GitHub的文档:MicroCity文档,也可以参考 MicroCtiy 在GitHub上的文档。'},{header:"MicroCityNotes 仓库",slug:"microcitynotes-仓库",content:`国内用户如果不方便访问 GitHub 也可以访问本站在 Netlify 上搭建的 同步站点 +如果发现文档或笔记有问题,欢迎 Pull Request 或者提供 Issues 让它变得更完善😋`}]},{path:"/en/",title:"Home Page",pathLocale:"/en/",contents:[{header:"Getting Started with MicroCity Web",slug:"getting-started-with-microcity-web",content:"Open MicroCity Web, and the example code for rotating blocks will load by default. Click the button to run the code. The program will run, and you will see the blocks rotating in the right-hand view. If you want to learn more about how to use MicroCity Web and its advanced features, you can refer to the Learning Notes provided on this site."},{header:"Getting Started with MicroCity Desktop",slug:"getting-started-with-microcity-desktop",content:'Go to the MicroCity documentation repository to download the Latest Version of MicroCity. Open the ScriptEditor and type: Print("hello, world!") Save the script as test.mcs and drag it into MicroCity. In the main interface of the program, go to the Modules tab on the left side, open test, and double-click on main to execute the script you just wrote. The information about the execution of the script will be displayed in the Messages panel at the bottom of the program interface. For more information on how to use MicroCity, you can refer to the documentation found on this site, which is a mirror of the documentation provided on GitHub: MicroCity Documentation. You can also refer to the documentation of MicroCtiy on GitHub at MicroCity.'},{header:"MicroCityNotes Repository",slug:"microcitynotes-repository",content:`If users in China have difficulty accessing GitHub, they can also visit the Synchronized Site hosted on Netlify. +If you find any issues with the documentation or notes, please feel free to submit a Pull Request or provide Issues to help make it better😋. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/docs/1.1_what_microcity_can_do.html",title:"1.1 MicroCity的功能",pathLocale:"/",contents:[{header:"1.1 MicroCity的功能",slug:"_1-1-microcity的功能",content:"MicroCity被设计为一款方便的空间规划工具,具有便携、紧凑和快速的特点。"},{header:"一个建模框架",slug:"一个建模框架",content:"基于GIS、网络和混合整数规划库,MicroCity可以作为一个建模框架来解决交通运输问题,例如城市物流和航运规划:"},{header:"一个仿真平台",slug:"一个仿真平台",content:"基于3D计算机图形和离散事件仿真引擎,MicroCity可以作为一个仿真平台来评估物流场景,例如自动化仓库和集装箱码头:"},{header:"通过脚本模块定制",slug:"通过脚本模块定制",content:"MicroCity可以通过模块来扩展其功能,这些模块可以从SAGA继承或在脚本编辑器中进行脚本编写和调试: 目前,MicroCity主要用于教学和研究,可以自由分发。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/2.1_showing_a_world_map.html",title:"2.1 显示世界地图",pathLocale:"/",contents:[{header:"2.1 显示世界地图",slug:"_2-1-显示世界地图",content:"本教程将指导您在 MicroCity 中操作和可视化地理信息系统(GIS)数据。"},{header:"加载数据和创建地图",slug:"加载数据和创建地图",content:"下载 countries.shp(ArcGIS shapefile)和 countries.dbf(dBase 文件)到同一个文件夹中。打开 MicroCity,点击 或将 countries.shp 拖入 MicroCity,然后在工作区面板中选择 Data Tab。双击工作区面板中的 Data->Shapes->Polygon->01. countries。"},{header:"可视化国家属性",slug:"可视化国家属性",content:"右键点击 01. countries 在工作区面板中。在弹出菜单中选择 Attributes->Table->Show。在 Settings 面板中,找到 Colors->Type 选项并选择 Graduated Color。在其子选项 Attribute 中,选择国家的人口属性 POP_EST。在 Settings 面板中,找到 Chart 选项并点击 ... 按钮。在弹出对话框中,选择饼图(pie)作为图表类型,选择 GDP_MD_EST 作为属性(大小),并在 Fields 选项中选择 EXPORT 和 IMPORT 复选框,然后点击 Okay 按钮。"},{header:"编辑形状",slug:"编辑形状",content:"在工具栏上选择 Action 按钮。左键点击某个国家,右键点击它并在弹出菜单中选择 Edit Selected Shape,然后该形状将进入编辑模式。您可以更改其多边形的点,并在右键点击并再次选择 Edit Selected Shape 来完成编辑。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/2.2_searching_for_countries.html",title:"2.2 寻找国家",pathLocale:"/",contents:[{header:"2.2 寻找国家",slug:"_2-2-寻找国家",content:"本教程将指导您使用 MicroCity Script 对GIS数据进行编码操作。您需要完成 2.1 内容以继续。"},{header:"GIS 数据结构",slug:"gis-数据结构",content:"在 MicroCity 中,GIS 数据由三种类型的形状组成:点、折线和多边形,每种类型都可以视为地图图层。在图层中,形状对象由一个或多个部分组成,而每个部分又由一个或多个点组成。形状对象还与属性表中的记录相关联。您还可以编辑形状或其属性(请参阅 3.2)。 如果您想要执行复杂的编辑或处理一批形状,可以使用 MicroCity Script,其中包含许多内置函数可供使用。"},{header:"进行查询",slug:"进行查询",content:`假设我们想要找出人口超过1亿且完全位于北半球的国家。因此,我们需要检查每个形状中每个点的坐标以及形状的人口属性。打开 ScriptEditor ,然后输入以下代码: +local Countries = Open("countries.shp") --尝试打开形状图层 +for i = 1, GetRecCount(Countries) do --循环遍历图层中的所有形状对象 local country = GetShape(Countries, i) --获取一个国家的形状对象 local north = true --假设该国家位于北半球 for j = 1, GetPartCount(country) do --循环遍历所有形状中的部分 for k = 1, GetPointCount(country, j) do --循环遍历该部分中的所有点 local x, y = GetPointXY(country, k, j) --获取点的坐标 if y < 0 then --如果纬度小于0 north = false --北半球的假设为假 end end end local pop = GetValue(country, "POP_EST") --获取人口属性 local name = GetValue(country, "NAME") --获取国家名称 if pop > 100000000 and north then --检查两个条件 Print(name, ": ", pop/100000000) --打印结果 end +end`},{header:"运行脚本",slug:"运行脚本",content:"将脚本保存为 query.mcs,并使用 MicroCity 打开它,或将其拖到 MicroCity。然后您将在 Workspace 面板的模块选项卡中找到一个名为query的项目。双击子项main。如果弹出对话框,请选择01. countries,然后点击确定。结果将显示在消息面板中。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/3.1_ui_overview.html",title:"3.1 用户界面概览",pathLocale:"/",contents:[{header:"3.1 用户界面概览",slug:"_3-1-用户界面概览",content:"MicroCity提供了一个简洁的图形窗口界面,以便于对数据和模块进行操作。"},{header:"主窗口及其组件",slug:"主窗口及其组件",content:""},{header:"支持的文件类型",slug:"支持的文件类型",content:"MicroCity可以打开ArcGIS shapefile文件(*.shp),Grids文件(*.sgrd),dBase文件(*.dbf),Tabular文本文件(*.csv, *.txt),Point clouds点云文件(*.spc),影像文件(*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx)以及MicroCity 3D场景文件(*.m3d)。这些数据文件可以在工作区面板的数据选项卡中进行管理。模块库文件(*.dll, *.mcs)可以在工作区面板的模块选项卡中进行管理和执行。"},{header:"项目管理",slug:"项目管理",content:"已打开的数据文件、模块库文件、设置和子窗口信息可以通过文件->项目菜单保存或打开一个MicroCity项目(*.mprj)。mprj文件不包含任何文件数据。为方便维护,项目中的文件应放置在同一文件夹或mprj文件的子文件夹中。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/3.2_vector_shapes.html",title:"3.2 矢量图",pathLocale:"/",contents:[{header:"3.2 矢量图",slug:"_3-2-矢量图",content:"MicroCity可以打开、创建和编辑ArcGIS shapefiles(*.shp),即所谓的Shapes,并在Workspace面板的Data选项卡中进行维护。通过使用模块(参见3.7),还可以导入或导出其他矢量文件格式,例如可伸缩矢量图形(*.svg)和AutoCAD绘图交换格式(*.dxf)。"},{header:"打开、创建、保存和关闭Shapes",slug:"打开、创建、保存和关闭shapes",content:"用户可以单击加载按钮或文件->Shapes->加载菜单项来打开ArcGIS shapefile(*.shp)作为Shapes。从菜单中选择文件->Shapes->新建,弹出对话框如下所示,可以创建新的Shapes。用户可以从点,线和面中选择其中一种形状类型。还显示了ArcGIS shapefile(*.shp)与同名dBase文件(*.dbf)之间的关系。 保存Shapes可以通过右键单击上下文菜单中的保存或另存为来完成。也可以从菜单中关闭Shapes并弹出提示对话框以保存它。"},{header:"显示和编辑形状",slug:"显示和编辑形状",content:"在数据选项卡中双击一个形状将为您提供地图视图(有关地图和图层,请参见3.6)。切换到操作按钮,然后右键单击形状图层中的一个形状,选择编辑所选形状,然后进入编辑模式。在这个模式下,用户可以添加/删除部分以及添加/删除形状中的点(关于形状的数据结构,请参见2.2)。通过右键单击上下文菜单属性->表格->显示可以访问形状的相关属性表格(*.dbf)(请参见教程2.1)。"},{header:"显示设置和数据可视化",slug:"显示设置和数据可视化",content:"用户可以从设置面板中更改形状的轮廓、填充、标签和其他显示设置。一些选项可以连接属性数据并提供可视化功能(例如2.1)。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/3.3_raster_grids.html",title:"3.3 栅格图",pathLocale:"/",contents:[{header:"3.3 栅格图",slug:"_3-3-栅格图",content:"MicroCity可以打开、创建和编辑SAGA Grid(*.sgrd),在工作空间面板的数据选项卡中被称为Grid并进行维护。图像文件(*.bmp、*.gif、*.jpg、*.png、*.tif、*.pcx)也可以被作为Grid打开。通过使用模块(参见[3.7](3.7_modules.md)),其他栅格文件格式,例如ESRI Arc/Info Grid(*.adf)和Surfer Grid(*.grd),也可以被导入或导出。"},{header:"打开、创建、保存和关闭Grid",slug:"打开、创建、保存和关闭grid",content:`用户可以点击Load按钮或File->Grid->Load菜单项来打开一个Grid。从菜单File->Grid->New中可以创建一个新的Grid,然后弹出对话框: 上图是一个Grid的数据结构和定义。Grid从其左下角开始,具有坐标**(xMin, yMin),包含NX*NY个方形单元格**。每个单元格有自己的整数坐标(X, Y),范围从(0, 0)到(XMax, YMax)。 +保存Grid可通过右键上下文菜单Save or Save As来完成。也可以通过菜单关闭Grid,并获得一个提示对话框来保存它。`},{header:"显示和编辑Grids",slug:"显示和编辑grids",content:"双击数据选项卡中的一个Grid将为您提供一个地图视图(有关地图和图层,请参见3.6)。切换Action按钮 ,然后在Grid中选择一系列单元格。然后可以在设置面板的属性选项卡中编辑这些单元格的值。"},{header:"显示设置和3D视图",slug:"显示设置和3d视图",content:"用户可以使用设置面板来显示单元格的值,更改颜色并设置网格的透明度。使用按钮可以创建一个网格的3D表面,其中单元格的值被转换为高程(见3.6)。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/3.4_3d_scenes.html",title:"3.4 3D场景",pathLocale:"/",contents:[{header:"3.4 3D场景",slug:"_3-4-3d场景",content:"MicroCity 3D场景(*.m3d)是一种存储3D场景信息的数据文件格式。流行的3D文件格式包括3D Studio Max(*.3ds),Wavefront OBJ(*.obj)和立体光刻(*.stl)可以作为场景中的对象进行加载(详见下文中的显示和编辑3D场景),但不能存储在.m3d文件中。"},{header:"打开、创建、保存和关闭3D场景",slug:"打开、创建、保存和关闭3d场景",content:"用户可以点击加载按钮 ,或选择文件->场景->加载菜单项来打开一个场景。从菜单项文件->场景->新建可以创建新的场景并填写弹出对话框中的信息,如下所示。点击确定按钮之后,工作区面板的数据选项卡中会出现一个项目。然后可以通过右键单击菜单来保存或关闭场景:"},{header:"显示和编辑3D场景",slug:"显示和编辑3d场景",content:"从数据选项卡双击一个场景会显示一个场景视图。在场景视图中,用鼠标左键拖拽可以旋转相机,用鼠标右键拖拽可以平移相机。在场景视图上用双击左键可以选择对象,在场景视图上用双击右键可以弹出上下文菜单(如下图所示)。可以添加对象、加载对象和设置对象等等。请注意,坐标系中的旋转应该遵循左手规则。下图展示了坐标系的示例和沿y轴旋转的示例: 在对象的位置和旋转中使用的坐标是相对于其父对象的。默认情况下,新对象的父对象为空。"},{header:"显示设置",slug:"显示设置",content:"用户可以通过使用设置面板更改场景的背景色、参考网格或其他显示选项。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。"}]},{path:"/docs/3.5_tables.html",title:"3.5 表格",pathLocale:"/",contents:[{header:"3.5 表格",slug:"_3-5-表格",content:"包括 dBase 文件 (*.dbf)、文本文件 (*.txt) 和逗号分隔值 (*.csv) 在内的表格文件可以在 MicroCity 中打开并保存为表格。"},{header:"打开、创建、保存和关闭表格",slug:"打开、创建、保存和关闭表格",content:"用户可以单击加载按钮 ,或选择文件->表格->加载菜单项来打开一个表格文件。可以从文件->表格->新建菜单项中创建一个新的表格,如下图所示的弹出对话框。要保存一个表格,可以右键单击上下文菜单中的保存或另存为选项。"},{header:"显示和编辑表格",slug:"显示和编辑表格",content:'双击数据选项卡中的表格,将显示一个表格视图。通过右键单击表头可以修改表格的结构。如果单击"添加字段",将显示一个引导对话框(如下图所示)。如果要向表格中插入一条记录,可以右键单击表格左侧的数字,并选择一个上下文菜单项。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。'}]},{path:"/docs/3.6_maps_and_layers.html",title:"3.6 地图和图层",pathLocale:"/",contents:[{header:"3.6 地图和图层",slug:"_3-6-地图和图层",content:"在MicroCity中,形状和网格可以显示在地图中。每个地图可以包含多个图层,每个图层对应一个形状或一个网格。"},{header:"打开、创建、保存、打印和关闭地图",slug:"打开、创建、保存、打印和关闭地图",content:"由于地图是基于形状和网格的,它们不能独立保存或打开,但可以与一个MicroCity项目(*.mprj)一同保存或打开。创建一个地图是通过在工作区面板的数据选项卡中双击一个形状或网格来实现的。地图窗口包含四个坐标栏,可用于定位对象(见下文)。地图也可以通过工作区面板的地图选项卡的上下文菜单进行打印或关闭。"},{header:"在地图中添加、移动、隐藏和关闭图层",slug:"在地图中添加、移动、隐藏和关闭图层",content:"一个地图可以有多个图层,每个图层表示一个数据项。可以通过在数据选项卡中双击一个形状或网格来将一个图层添加到一个地图中。较低的图层可以被上面的图层遮挡。可以通过拖动来移动一个图层,通过双击来隐藏一个图层,通过菜单来关闭一个图层(如下所示)。"},{header:"控制地图视图",slug:"控制地图视图",content:`当选择一个数据项或图层时,该图层被称为活动图层。可以切换操作按钮来选择和编辑活动图层中的对象。通过切换缩放按钮或平移按钮,可以对地图进行缩放和平移操作。如果在地图中迷失了方向,可以使用缩放至全图范围按钮来查看整个地图。其他的缩放控制按钮可用于方便地浏览地图。 +如果要比较两个或多个地图之间的差异,可以使用同步按钮。可以使用尺子按钮测量距离。需要注意的是,默认情况下,在地球坐标系下测得的距离单位是公里。可以在地图的设置面板中将坐标系更改为非地球,从而获取没有单位的笛卡尔距离。 +点击3D按钮可以创建一个3D表面地图,需要一个适当大小的网格(参见3.3)来实现。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/3.7_modules.html",title:"3.7 拓展模块",pathLocale:"/",contents:[{header:"3.7 拓展模块",slug:"_3-7-拓展模块",content:"MicroCity的功能可以通过模块进行拓展,其中之一是SAGA模块(*.dll)。SAGA模块包含许多有用的形状(Shapes)和网格(Grids)库。另一种类型的模块是MicroCity脚本(*.mcs),可以使用进行编辑和调试(请参阅4.1)。"},{header:"加载、关闭和执行模块",slug:"加载、关闭和执行模块",content:"可以通过点击加载按钮或模块->加载模块库菜单项将模块加载到MicroCity中。工作区面板的模块选项卡将显示已加载的库文件(每个对应一个文件)及其包含的模块。可以通过上下文菜单关闭或重新加载模块库。执行模块有多种方式:双击模块,点击设置面板的执行按钮,或点击执行上下文菜单项。还可以通过点击调试上下文菜单项来调试MicroCity脚本模块,这需要后台运行ScriptEditor。MicroCity还可以捕获运行时错误并暂停模块的执行。"},{header:"加速、停止模块的执行",slug:"加速、停止模块的执行",content:`MicroCity Script 模块是使用非常快速的 Lua 语言创建的。在某些情况下,如果您想要更快的执行速度,可以在 工作区 面板的 模块 标签中点击 模块库,然后在 设置 面板中将 脚本运行模式 从 安全模式 切换到 快速模式。然后 MicroCity 将使用 LuaJIT 来执行模块。 +如果一个模块正在被执行,可以通过点击相应的 设置 中的 执行 按钮来停止它。在 安全模式 下,执行可以立即停止,但在 快速模式 下,停止操作取决于脚本中调用的 GetReady() 函数(参见 4.2)。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.1_si_overview.html",title:"4.1 脚本概览",pathLocale:"/",contents:[{header:"4.1 脚本概览",slug:"_4-1-脚本概览",content:"MicroCity使用模块(详见3.7)来扩展其功能。模块的一种类型是MicroCity脚本(*.mcs),可以在ScriptEditor中进行编辑和调试。"},{header:"脚本编辑器",slug:"脚本编辑器",content:""},{header:"编码和调试MicroCity脚本",slug:"编码和调试microcity脚本",content:"ScriptEditor基于ZeroBrane。可以在那里找到详细的信息。要进行调试,您应该保持Script Editor打开。然后从MicroCity中右键点击模块,选择上下文菜单中的调试项(详见3.7)。执行过程可以在ScriptEditor的Code View中显示。您可以使用调试按钮控制执行并查看变量。"},{header:"Lua语言和嵌入函数",slug:"lua语言和嵌入函数",content:`MicroCity使用Lua 5.1作为其脚本语言。可以在那里找到参考手册。MicroCity在Lua中嵌入了许多有用的函数,不仅可以控制用户界面、操作数据,还可以解决数学模型和太阳模拟等问题。请阅读以下章节以获取更多信息。 +本参考资料中的约定: +Lua中有四种主要的数据类型可以作为参数通过嵌入函数传递,分别是数字(Number)、布尔值(Boolean)、字符串(String)和对象(Object)。对象类型包括内置的Lua对象,如表(Table)、函数(Function)和线程(Thread),以及MicroCity对象,如形状(Shapes)、网格(Grid)、表(Table)和场景(Scene)。为了明确嵌入函数中的参数类型,在函数描述中我们使用大写、引号和语义信息来避免歧义。参数的小写单词表示数字。有时候为了表示整数参数,会在单词后面加上字母'i',如iField。以字母'b'开头并跟随一个单词表示布尔值,如bShow。用引号括起来的单词表示字符串。大写的单词表示对象或关键字。以下是一个嵌入函数描述的示例。 +AddParameter(Module, ParentNode, "Value", "id" [, default = 0]) +在这个例子中,Module参数应该是一个Module对象。ParentNode参数应该是一个Node对象,但它作为一个父节点。"Value"参数是一个字符串,但它代表MicroCity中的内置类型Value,因此这个字符串是不能改变的。*"id"*参数应该是一个用户指定的字符串。default参数是一个数字。方括号中的内容是可选的。参数之间的竖线表示"或"的关系。 +编码格式: +MicroCity使用ANSI编码格式读写数据,比如shp、txt、csv和dbf等。ScriptEditor和嵌入函数使用UTF-8编码格式读写数据,比如txt或csv等。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.2_ui_control.html",title:"4.2 控制用户界面",pathLocale:"/",contents:[{header:"4.2 控制用户界面",slug:"_4-2-控制用户界面",content:'Microcity Script 可用于控制用户界面上的一些功能,包括模块、数据对象、消息等等。在 ScriptEditor 的项目标签的"user_interface"文件夹中可以找到一些示例代码。'},{header:"基本用户界面",slug:"基本用户界面",content:`Print ("hello" [,...]) +在消息面板中打印数值。 +Note ("hello" [,...]) +通知用户并暂停执行。 +SetProcessText ("processing") +在MicroCity的左下角设置一个文本。 +SetProgress (position, range) +设置位于MicroCity右下角的进度条的 position/range 值。 +Sleep (milliseconds) +暂停执行 milliseconds 毫秒。 +GetReady () +MicroCity与Lua引擎共享同一线程。Lua中的计算量较大会阻塞MicroCity界面。在内部使用该函数可以使MicroCity界面响应用户操作。如果用户取消当前执行,则返回false。 +GetClickXY () +返回用户在地图视图中点击的 x,y 坐标。 +GetDragExtent () +返回用户使用鼠标在地图视图中拖动矩形时的底部左侧和顶部右侧坐标:Lx,By,Rx,Ty。`},{header:"数据对象",slug:"数据对象",content:`PATH +内部全局变量,保存当前工作目录的字符串,例如"c:\\microcity"。 +Open (".\\\\shapes.shp" [, ".\\\\grid.sgrd" [, ".\\\\table.dbf" [, ".\\\\scene.m3d" , ...]]]) +从当前工作目录或打开的数据中打开并返回Shapes、Table、Grid和Scene对象。 +Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel) +关闭已打开或创建的Shapes、Table、Grid、Scene、Network、RndEngine或LPModel对象。 +Update (Shapes|Grid|Table [, bShow = true]) +在MicroCity中更新Shapes、Grid或Table对象的当前更改。bShow表示是否创建对象的视图。如果用户取消当前执行,返回false。 +CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...]) +创建一个地图视图,以显示按参数中的顺序分层排列的对象。`},{header:"模块和参数",slug:"模块和参数",content:`AddModule ("Function" [, "name"]) 此函数可以将Lua函数作为模块添加到当前模块库。模块的默认名称是函数的名称。返回一个Module对象。 +function AddParameter(Module, ParentNode, "Node", "id") +function AddParameter(Module, ParentNode, "Value", "id" [, default = 0]) +function AddParameter(Module, ParentNode, "Range", "id" [, low = 0 [, high = 1]]) +function AddParameter(Module, ParentNode, "Check", "id" [, default = 0]) +function AddParameter(Module, ParentNode, "String", "id" [, "string" = "") +function AddParameter(Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]]) +function AddParameter(Module, ParentNode, "File", "id" [, "c:\\\\default.txt" = ""]) +function AddParameter(Module, ParentNode, "Color", "id" [, "color" = "255 255 255") +function AddParameter(Module, ParentNode, "Shapes", "id") +function AddParameter(Module, ParentNode, "Grid", "id") +function AddParameter(Module, ParentNode, "Scene", "id") +function AddParameter(Module, ParentNode, "Table", "id") +function AddParameter(Module, ParentNode, "Field", "id") +这些函数可以在模块的设置面板中添加参数。返回相应的值或对象。ParentNode 可以设置为 AddParameter 函数的第一个返回值。如果 "Field" 在第三个位置,则 parent_node 可以设置为 Table 或 Shapes 对象,以获取其属性表的头部。 +GetParameter(Shapes|Table|Grid|Scene|Module, "id") +从对象的设置面板中返回指定的参数。 +SetParameter(Shapes|Table|Grid|Scene|Module, "id", Number | "String" | Object) +在对象的设置面板中设置指定的参数。如果成功,则返回 true。请注意,选择参数应从1开始。可以在下图中的参数帮助文本中找到参数的 "id"。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.3_shapes_and_tables.html",title:"4.3 矢量图形和表格",pathLocale:"/",contents:[{header:"4.3 矢量图形和表格",slug:"_4-3-矢量图形和表格",content:'用户可以使用 MicroCity 脚本操作 形状(Shapes) 和 表格(Tables)。有关形状(Shapes)的详细数据结构,您可以参考上一章节 2.2 和 3.2。由于形状(Shapes)可以被视为带有地理数据的表格(Tables),因此一些用于表格数据操作的嵌入函数可以在**形状(Shapes)和表格(Tables)中同时使用。本章节的示例代码可以在项目(Project)**选项卡的"shapes_samples"文件夹中找到,该文件夹位于 ScriptEditor。'},{header:"表格数据操作",slug:"表格数据操作",content:`CreateShapes ("name", "Point|Line|Polygon") +返回一个 Shapes 对象。 +CreateTable ("Name") +返回一个 Table 对象。 +GetFieldCount (Shapes|Table) +返回 Shapes 或 Table 中字段的数量。 +GetField (Shapes|Table, iField) +输入字段的索引(从 1 开始)并返回字段名和类型("Int"、"Float"、"Double" 或 "String")。 +AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...]) +向 *Table 或 Shapes 添加字段,并按照顺序返回布尔值(true 或 false)。 +DelField (Shapes|Table, iField) +成功删除字段时返回 true。 +GetRecCount (Shapes|Table) +返回 Shapes 或 Table 中的记录总数。 +AddRecord (Shapes|Table) +向 Shapes 或 Table 添加一条记录,并返回该记录的索引。 +GetValue (Shapes|Table, "field_name", index1 [, index2, ...]) +从指定字段和 Shapes 或 Table 的索引中检索值。按照索引的顺序返回多个值。 +SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...]) +为指定字段和 Shapes 或 Table 的索引设置值。`},{header:"地理数据操作",slug:"地理数据操作",content:`GetSelections (Shapes) +从Shapes中返回所选的形状对象。 +GetShape (Shapes, index1 [, index2, ...]) +按索引顺序从Shapes中返回Shape对象。 +AddShape (Shapes, Shape) +将Shape对象添加到Shapes中并返回其索引。 +AddShape (Shapes [, x1, y1, x2, y2, ...]) +将定义为点的Shape对象添加到Shapes中。返回Shape对象和索引。 +DelShape (Shape|Shapes) +删除一个Shape或Shapes对象,如果成功则返回true。 +AddPoint (Shape, x, y [, iPart = 1]) +在Shape中添加一个点,如果成功则返回true。 +InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]]) +在Shape中插入一个点,如果成功则返回true。 +SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]]) +设置Shape中的点坐标,如果成功则返回true。 +DelPoint (Shape, iPoint [, iPart=1]) +从Shape中删除位置为iPoint的一个点,如果成功则返回true。 +DelPart (Shape, iPart) +从Shape中删除一个部分,如果成功则返回true。 +GetPartCount (Shape) +返回Shape中部分的数量。 +GetPointCount (Shape [, iPart]) +返回Shape中点的数量。 +GetPointXY (Shape [, iPoint [, iPart = 1]]) +从Shape或指定点的坐标中返回所有点的坐标:x1,y1,x2,y2,...。 +CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...]) +将Shape对象复制到目标Shapes,并进行相对平移(dx,dy),返回新的Shape对象。 +MoveShapeTo (dx, dy, Shape1 [, Shape2, ...]) +将Shape对象平移到其相对位置(dx,dy)。 +GetCenterXY (Shapes) +返回Shapes的中心坐标(x,y)。 +GetCenterXY (Shapes, index1 [, index2, ...]) +返回在Shapes中由索引指定的Shape对象的中心坐标(x1,y1,x2,y2,...)。 +GetCenterXY (Shape1 [, Shape2, ...]) +返回Shape对象的中心坐标(x1,y1,x2,y2,...)。 +GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) +返回每两个坐标(x,y)对之间的总距离。 +GetShapeLen (Shape1 [, Shape2, ...]) +返回Shape对象的长度。 +GetShapeArea (Shape1 [, Shape2, ...]) +返回Shape对象的面积。 +GetShapeType (Shape|Shapes) +返回Shapes或Shape对象的类型("Point","Line"或"Polygon")。 +GetExtent (Shapes) +返回Shapes的范围坐标(Lx,By,Rx,Ty)。 +GetExtent (Shapes, index) +返回Shapes中索引为index的Shape的范围坐标(Lx,By,Rx,Ty)。 +GetExtent (Shape) +返回Shape的范围坐标(Lx,By,Rx,Ty)。 +GetIntersection (ShapeA, ShapeB) +返回两个Shapes的交集的Shape(Point,Line或Polygon)对象。 +GetValue (Shape, "field_name") +返回Shape的指定字段的值。 +SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...]) +为Shape的不同字段设置值。 +SetCoorSys ("Earth"|"Non-Earth") +设置坐标系统。如果使用"Earth",距离、长度和面积将根据地球椭球坐标系统计算。默认情况下使用"Non-Earth",即笛卡尔坐标系统。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.4_grids.html",title:"4.4 栅格图形",pathLocale:"/",contents:[{header:"4.4 栅格图形",slug:"_4-4-栅格图形",content:'在MicroCity中,栅格图形具有简单的结构(3.3),但是如果在其上应用算法,可以高效利用时间和空间。本章的示例代码可以在项目选项卡的"grid_samples"文件夹中找到,该选项卡位于ScriptEditor中。'},{header:"栅格数据操作",slug:"栅格数据操作",content:`CreateGrid("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]]) +返回一个Grid对象。 +GetCellSize(Grid) +返回Grid的Cellsize值。 +GetGridMaxXY(Grid) +返回Grid的XMax和YMax值。 +ConvertToGridXY(Grid, x1, y1 [, x2, y2, ...]) +将实际坐标转换为Grid中的坐标。返回X1,Y1,X2,Y2,...。 +ShapeToGrid(Grid, Shape, value) +在Grid中将Shape栅格化。栅格单元值将根据覆盖面积和输入的值设置。 +ShapeToGrid(Grid, Shapes, "field_name") +在Shapes中栅格化所有的Shape对象。栅格单元值将根据覆盖面积和Shapes字段的值设置。 +GetValue(Grid, X1, Y1 [, X2, Y2, ...]) +返回指定Grid坐标的单元格值:value1,value2,...。 +SetValue(Grid, value, X1, Y1 [, X2, Y2, ...]) +设置指定Grid坐标单元的值。 +GetCenterXY(Grid) +返回Grid的中心实际坐标(x,y)。 +GetCenterXY(Grid, X1, Y1 [, X2, Y2, ...]) +返回单元格中心的实际坐标:x1,y1,x2,y2,...。 +GetExtent(Grid) +返回Grid范围的左下角和右上角坐标:Lx,By,Rx,Ty。 +GetExtent(Grid, X, Y) +返回单元格范围的左下角和右上角坐标:Lx,By,Rx,Ty。 +GetFractalDim(Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0]) +计算Grid中指定区域的分形维度。返回维度,线性回归的RSQ值以及每个折叠中的盒子数。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.5_3d_scenes.html",title:"4.5 3D场景",pathLocale:"/",contents:[{header:"4.5 3D场景",slug:"_4-5-3d场景",content:'场景和3D物体(3.4)可以进行脚本编写。本章节的示例代码可以在项目标签中的"3d_samples"文件夹中的ScriptEditor中找到。'},{header:"3D场景和物体操作",slug:"_3d场景和物体操作",content:`CreateScene ("标题" [, RotSpeed=1] [, TransSpeed=1]) +创建一个新的3D场景并返回物体。 +AddZipTo3DPath (Scene, "文件名.zip") +将一个zip文件添加到搜索目录中,并在成功时返回true。这对于收集大量文件很有用。 +LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg") +将六个图像文件加载为3D场景的天空盒。 +LoadObject (Scene, "文件名.3ds" [,shadow = false [, AnimationSpeed]]) +从文件中加载一个3D物体,并返回该物体。 +AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255]) +添加一个光源物体,并返回该物体。 +Add3DLabel(Scene, "标签" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]]) +在坐标(0,0,0)处添加一个3D标签,并返回该物体。 +Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0]) +从点(x1, y1, z1)到点(x2, y2, z2)添加一个3D线物体,并返回该物体。 +Add3DRect (Scene, 长度, 宽度 [, r = 180, g = 180, b = 180]) +从(-长度/2,0,-宽度/2)到(长度/2,0,宽度/2)添加一个3D矩形物体,并返回该物体。 +Add3DBox (Scene, 长度, 宽度, 高度 [, r = 180, g = 180, b = 180 [, bShowEdge = true]]) +从(-长度/2,-高度/2,-宽度/2)到(长度/2,高度/2,宽度/2)添加一个3D盒子物体,并返回该物体。 +AddSphere (Scene, 半径 [, polycount = 16 [, r = 180, g = 180, b = 180]]) +在坐标(0,0,0)处添加一个球体,并返回该物体。如果半径参数小于0,则返回一个不可见的物体。 +GetTexture (Object) +返回一个物体的纹理文件:"文件名1","文件名2"等等。 +LoadTexture (Scene, Object, "文件名1" [, "文件名2", ...]) +加载纹理文件到一个物体中。 +SetPosition (Object, x, y, z [, absolute = false]) +设置一个物体相对于其父物体的位置(或者绝对位置到场景)。 +GetPosition (Object [, absolute = false]) +获取一个物体相对于其父物体的位置(或者该物体在场景中的绝对位置)。 +SetRotation (Object, rx, ry, rz [, absolute = false]) +设置一个物体相对于其父物体的旋转角度(左手坐标系),以度为单位(或者该物体在场景中的绝对旋转角度)。 +GetRotation (Object [, absolute = false]) +获取一个物体相对于其父物体的旋转角度(左手坐标系),以度为单位(或者该物体在场景中的绝对旋转角度)。 +SetScale (Object, sx, sy, sz) +设置一个物体的缩放比例。 +GetScale (Object) +获取一个物体的缩放比例。 +SetParent (Object, Parent) +将一个物体作为子物体附加到另一个物体上。 +GetParent (Object) +获取一个物体的父物体。 +SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]]) +设置一个物体的id、位置、旋转和缩放。 +DelObject (Object) +删除一个物体。 +SetCamera (Scene, x, y, z [,Tx, Ty, Tz]) +设置场景相机的位置和目标。 +GetCamera (Scene) +获取一个3D场景的相机物体以及其位置和目标。 +GetSelections (Scene) +从一个3D场景中返回选中的物体。 +GetObjectID (Object1 [, Object2, ...]) +返回物体的"id"。 +SetObjectID (Object, "id") +设置一个物体的id。 +GetObject (Scene, "id") +根据id查找一个物体。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.6_networks.html",title:"4.6 网络",pathLocale:"/",contents:[{header:"4.6 网络",slug:"_4-6-网络",content:'在MicroCity中,GIS矢量数据(参见3.2)可以进行拓扑操作,并应用最短路径算法和用户均衡交通分配算法。本章的示例代码可以在项目选项卡的"network_samples"文件夹中找到,具体请参考ScriptEditor。'},{header:"网络操作",slug:"网络操作",content:`CreateNetwork () +创建一个空网络对象并返回。 +CreateNetwork (UnTopoLines) +从未进行拓扑操作的“线”形状创建网络,并返回三个对象:网络、节点(形状)和链接(形状)。 +CreateNetwork (Nodes, Links) +从进行了拓扑操作的节点和链接形状创建网络对象。返回网络对象。 +InitNetwork (Network, Nodes, Links) +从节点和链接形状初始化网络。如果成功返回true。 +AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]]) +向网络中添加新的链接或更新现有链接。返回linkID、oID、dID、添加结果(true/false)和更新结果(true/false)。 +AddLink (Network, Shapes|Table, index1 [, index2, ...]) +从形状记录集或表中添加或更新链接。返回布尔值。 +DelLink (Network, linkID) +从网络中删除链接。返回布尔值。 +GetNearNodeID (Network, x, y [, radius=nil]) +获取坐标最近的网络节点。返回节点ID。 +GetNodeXY (Network, nodeID1 [, nodeID2, ...]) +返回网络中节点的坐标:x1、y1、x2、y2,等等。`},{header:"算法",slug:"算法",content:`GenSTPTree (Network, startID [, endID]) +从一个节点生成最短路径生成树。返回布尔值。 +GetSTPPath (Network, endID, "NodeID"|"LinkID") +在调用GenSTPTree之后调用该函数。返回由节点ID或链接ID序列表示的最短路径:id1、id2,等等。 +GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp") +在调用GenSTPTree之后调用该函数。返回由节点或链接形状索引序列表示的最短路径。 +GetSTPPath (Network, endID, "NodeShp"|"LinkShp") +在调用GenSTPTree之后调用该函数。返回由节点或链接形状对象序列表示的最短路径。 +GetSTPLen (Network, endID) +在调用GenSTPTree之后调用该函数。返回到达目标节点的最短路径距离。 +GetSTPLen (Network, startID, endID) +在网络中从起点节点到终点节点获取最短路径。返回距离。 +GetSTPLen (Network, x1, y1, x2, y2) +在网络中从起点坐标到终点坐标获取最短路径。返回距离。 +SetTrip (Network, oID, dID, amount) +设置从出发地到目的地的旅行量。 +SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]]) +在调用SetTrip之后调用该函数。执行用户均衡交通分配,并返回布尔值。 +GetFlow (Network, linkID) +返回指定链接的交通流量。 +SetFlow (Network, linkID, flow) +设置指定链接的交通流量,并返回布尔值。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.7_des_simulations.html",title:"4.7 离散事件仿真",pathLocale:"/",contents:[{header:"4.7 离散事件仿真",slug:"_4-7-离散事件仿真",content:"MicroCity有一个内置的模拟时间计数和事件调度机制。它提供了几个嵌入的Lua函数来方便创建离散事件仿真,这对于动态系统分析非常有用。本章的示例代码可以在项目选项卡的“simulation_samples”文件夹中的ScriptEditor找到。"},{header:"随机数生成",slug:"随机数生成",content:`CreateRandEng (seed, "uniform_01") +使用种子创建一个二进制分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "uniform_real" [, min = 0, max = 1]) +使用种子创建一个服从均匀分布的实数随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "uniform_int" [, min = 0, max = 1]) +使用种子创建一个服从均匀分布的整数随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2]) +使用种子创建一个服从三角分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "bernoulli" [, p = 0]) +使用种子创建一个服从伯努利分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1]) +使用种子创建一个服从柯西分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "exponential" [, lambda = 1]) +使用种子创建一个服从指数分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "geometric" [, p = 0]) +使用种子创建一个服从几何分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "normal" [, mean = 0, sigma = 1]) +使用种子创建一个服从正态分布的随机数生成引擎,并返回该对象。 +CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1]) +使用种子创建一个服从对数正态分布的随机数生成引擎,并返回该对象。 +GetNextRandom (Engine) +从随机数生成引擎中获取一个随机数。`},{header:"模拟控制",slug:"模拟控制",content:`CreateEvent (time, Funcion [, arg1, arg2, ...]) +从Lua Function或Lua Coroutine创建一个将来的事件,并返回一个Coroutine对象。 +ExecAllEvents () +最后调用这个函数。它会将所有事件作为Lua Coroutines执行。 +Delay ([relativeTime = 0]) +在Lua Coroutine中调用这个函数,让它先暂停一段指定的相对时间,然后再恢复执行。如果没有设置参数relativeTime,当前的Coroutine将暂停而不会自动恢复。 +Resume ([time, ] Coroutine [, arg1, arg2, ...]) +立即或在指定的时间恢复一个已暂停的协程。 +GetSimTime () +返回当前的模拟时间。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/4.8_mixed_integer_programming.html",title:"4.8 混合整数线性规划",pathLocale:"/",contents:[{header:"4.8 混合整数线性规划",slug:"_4-8-混合整数线性规划",content:'MicroCity使用lpsolve来解决混合整数线性规划问题。开发人员可以使用嵌入的Lua函数来构建和求解模型。本章的示例代码可以在项目选项卡中的"optimization_samples"文件夹中找到,图标为ScriptEditor.'},{header:"模型创建和执行",slug:"模型创建和执行",content:`CreateLP ([rows = 0 , columns = 0]) +创建一个混合整数线性规划模型并返回LPModel对象。 +SetObjFunction (LPModel, rowTable, "MAX"|"MIN") +使用存储决策变量系数的Lua Table设置LPModel的目标函数。 +AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue) +使用存储决策变量系数的Lua Table向LPModel添加约束。 +SetInteger (LPModel, index) +将由索引index指定的决策变量设置为整数变量。 +SetBinary (LPModel, index) +将由索引index指定的LPModel的决策变量设置为二进制变量。 +SetUnbounded (LPModel, index) +将由索引index指定的LPModel的决策变量设置为无界(正/负无穷大)。 +SolveLP (LPModel [, timeoutSec = 60]) +求解LPModel并返回0表示成功,-1表示无效LP模型,-2表示内存不足,1表示次优,2表示不可行,3表示无界,4表示退化,5表示遇到数值错误,6表示用户中止,7表示超时错误,9表示模型可由预处理解决,10表示B&B例程失败,11表示B&B因中断而停止,12表示找到可行的B&B解决方案,13表示没有可行的B&B解决方案。 +GetObjective (LPModel) +返回LPModel的目标函数值。 +GetVariable (LPModel, index) +返回由索引index指定的决策变量的值。 +GetVariables (LPModel) +返回LPModel的所有决策变量的值。 +GetDual (LPModel, index) +返回由索引index指定的决策变量的对偶值。 +GetDuals (LPModel) +返回LPModel的所有决策变量的对偶值。 +ReadLP("fileName.mps") +从文件(*.lp, *.mps)中读取LPModel,并在成功时返回LPModel。 +WriteLP (LPModel, "fileName.mps") +将LPModel写入文件(*.lp, *.mps),并在成功时返回true。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/docs/",title:"MicroCity Desktop 文档",pathLocale:"/",contents:[{header:"MicroCity Desktop 文档",slug:"microcity-desktop-文档",content:""},{header:"目录",slug:"目录",content:`1 Introduction 1.1 MicroCity的功能 2 入门指南 2.1 显示世界地图 +2.2 搜索国家 3 用户界面 3.1 UI概览 +3.2 矢量形状 +3.3 栅格图层 +3.4 3D场景 +3.5 表格 +3.6 地图和图层 +3.7 模块 4 脚本接口 4.1 接口概览 +4.2 UI控制 +4.3 形状和表格 +4.4 栅格图层 +4.5 3D场景 +4.6 网络 +4.7 离散事件仿真 +4.8 混合整数规划 声明:本网站文档中的部分内容来源于MicroCity Desktop,版权归原作者所有。 这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈页面提交反馈。`}]},{path:"/notes/3d-objects.html",title:"3D 对象",pathLocale:"/",contents:[{header:"3D 对象",slug:"_3d-对象",content:"本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。"},{header:"添加对象",slug:"添加对象",content:`向场景中添加对象,函数形式如下 +local obj = scene.addobj([类型], {key1 = value1, key2 = value2, ...})`},{header:"对象可选属性列表",slug:"对象可选属性列表",content:`添加到场景中的对象通常支持设置以下属性中的某些属性 对象属性 +含义 color +对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 的设置相同 opacity +透明度 hcolor +选中时的颜色 size +对象的大小,默认值为1 length +对象的长度,常用于 box(立方体) width +对象的宽度,常用于 box(立方体) height +对象的高度,常用于 box(立方体) radius +对象圆角大小 segments +份数,通常用于设置 sphere(球体) 绘制的精度 selectable +是否可被选中 name +对象名称 text +对象文本值 font +文本字体 vertices +构成对应对象的点集合 支持添加到场景中的类型如下`},{header:"对象类型",slug:"对象类型",content:""},{header:"对象类型列表",slug:"对象类型列表",content:`label:文本标签 +points:点集合 +polyline:线段集合 +box:立方体 +sphere:球体 +polygon:多边形 +light:光源 +mesh:点构成的面 注释 +为了简洁起见,下方示例的对象可选属性中只展示对应对象的关键属性。其他通用的属性可以参考 对象可选属性列表 自行添加。`},{header:"label",slug:"label",content:`label 是文本标签。可以在 text 属性中设置label的文本。 +local obj = scene.addobj('label', {text = "Hello World!"})`},{header:"points",slug:"points",content:`points 是点集合。可以只创建单个点,也可以创建多个点。每个点都有三个维度的坐标以确定其在三维空间中的位置。点的个数通过 vertices 属性确定。 +下面是一个创建 points 点集对象的示例 +-- 在坐标为(5,5,5)的位置创建一个点 +scene.addobj("points", {vertices = {5,5,5}, size = 5}) -- 第一个点的坐标为(0,0,0),第二个点的坐标为(5,5,5) +scene.addobj("points", {vertices = {0,0,0, 5,5,5}, size = 5})`},{header:"polyline",slug:"polyline",content:`polyline 是线段集合。当在vertices属性中输入多个点的坐标时,将会依次根据点坐标连线,得到线段集合。 +因此,虽然下面两个例子中使用了相同的点坐标,但是由于点坐标输入顺序不同,得到的结果也不同。 +scene.addobj("polyline", {vertices = {0,0,0, 4,6,7, -2,3,5}}) +scene.addobj("polyline", {vertices = {0,0,0, -2,3,5, 4,6,7}}) polyline点顺序对比图 polyline 没有 size 属性`},{header:"box",slug:"box",content:`box 是长方体。主要通过 length、width 和 height 属性修改其形状。 +local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) +box 对象的重要可选属性 属性 +含义 length +立方体的长度 width +立方体的宽度 height +立方体的高度 基于以上三个属性,我们可以修改默认示例代码中旋转的box的形状。 +--添加了length, width, height三个属性(不添加默认都为1) +local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) local x = 1 +local y = 1 +local z = 0 +while scene.render() do x = x + 0.1 y = y + 0.1 obj:setrot(x, y, z) +end 不同长宽高设置的box`},{header:"sphere",slug:"sphere",content:`sphere 是球体。可以通过 radius 属性修改其大小,还可以通过设置 segment 属性设置其模型质量。具体可以参考内置示例中地球的例子。 +local obj = scene.addobj('sphere', {radius=15, segments=360}) +sphere 对象的可选属性 属性 +含义 radius +球体的圆角大小。可以用于控制球体的大小。 segments +球体的渲染面数。设置值越高球体的模型越精细。 不同segment对于相同sphere的影响`},{header:"polygon",slug:"polygon",content:`polygon 是多边形。主要通过 vertices 属性对其进行设置。 +local obj = scene.addobj("polygon", {vertices = {-1,-1,0, -1,1,-0, 1,1,0, 1,-1,0}}) 由于此处举例的多边形为正方形,因此看上去与上面介绍的 box 没什么差别。但是当形状设置为其他类型的多边形时(如三角形、五边形等),多边形的意义就能被体现出来了。 属性 +含义 +说明 vertices +多边形的顶点 +可以在 vertices 属性中依次设置每个点的三维坐标。第三维的坐标不会产生影响,但是起到占位作用。 size +体积 +由于第三维的坐标不影响,且多边形的顶点确定后面积就已经确定,因此 size 属性通过控制每个点的第三维坐标值来控制体积。 不同size对于相同polygon体积的影响`},{header:"外部模型",slug:"外部模型",content:`引用外部文件。但是目前对于MicroCityWeb来说,暂时只能引用网站中内置的文件。 +例如内置示例中引用网站内部文件在视图中生成一辆厢式货车: +local obj = scene.addobj('/res/2axle.glb') +还可以通过引用文件的网址引用外部模型: +local obj = scene.addobj('https://huuhghhgyg.github.io/ModelResource/models/F16-lite.glb') 提示 +如果需要外部模型,可以到 ModelResource仓库 中找有没有合适的模型。如果其中没有合适的模型,但是你手上又有特别想用的模型,可以按照 ModelResource仓库提供的指引 进行Pull Request请求上传模型。一旦你的Pull Request被同意,Github工作流会立即将你上传的模型部署到仓库网页中供使用并以邮件形式通知。 相关信息 +如果手中有三维模型资源,可以在3D Viewer中查看,也可以通过这个网站导出为 .glb 模型`},{header:"light",slug:"light",content:"设置光源的方向,可选参数 vertices 为一个三维向量,表示光的照射方向。由于MicroCity Web的场景中已经设置了很强的光源,因此此处不过多做介绍。"},{header:"mesh",slug:"mesh",content:"多个点构成的面,多见于引用的外部模型中。由于应用较少此处不做介绍。"},{header:"对象控制函数",slug:"对象控制函数",content:"下面假定要操作的三维对象为 obj"},{header:"getpos()",slug:"getpos",content:`获取 obj 对象的位置坐标 (x, y, z) +local x, y, z = obj:getpos()`},{header:"setpos()",slug:"setpos",content:`设置 obj 对象的位置坐标为 (x, y, z) +obj:setpos(x, y, z)`},{header:"getrot()",slug:"getrot",content:`获取 obj 对象在 x, y, z 方向上的旋转弧度值 (rx, ry, rz) +local rx, ry, rz = obj:getrot()`},{header:"setrot()",slug:"setrot",content:`设置 obj 对象在 x, y, z 方向上的旋转弧度值为 (rx, ry, rz) +obj:setrot(rx, ry, rz)`},{header:"getscale()",slug:"getscale",content:`获取 obj 对象在 x, y, z 方向上的缩放比例 sx, sy, sz +local rx, ry, rz = obj:getrot()`},{header:"setscale()",slug:"setscale",content:`设置 obj 对象在 x, y, z 方向上的缩放比例 sx, sy, sz +local rx, ry, rz = obj:getrot()`},{header:"getchildren()",slug:"getchildren",content:`获取 obj 对象的子对象表 +local children = obj:getchildren()`},{header:"getchildren()",slug:"getchildren-1",content:`设置 obj 对象的子对象表 +obj:setchildren(children_table)`},{header:"getparent()",slug:"getparent",content:`获取 obj 对象的父对象 +local num = obj:getparent() 此处只返回一个数值`},{header:"setparent()",slug:"setparent",content:`设置 obj 对象的父对象为 obj0 +obj:setparent(obj0)`},{header:"delete()",slug:"delete",content:`删除 obj 对象 +obj:delete()`}]},{path:"/notes/3d-scene.html",title:"3D 场景",pathLocale:"/",contents:[{header:"3D 场景",slug:"_3d-场景",content:"本节将介绍 MicroCity Web 中的三维场景及其设置。"},{header:"MicroCityWeb三维场景坐标系",slug:"microcityweb三维场景坐标系",content:`MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。 MicroCity Web中的坐标系 手动绘制上图坐标轴的代码 +scene.setenv({grid="plane"}) -- x +scene.addobj("polyline", {vertices = {0,0,0, 10,0,0}, color = "blue"}) +scene.addobj("points", {vertices = {10,0,0}, color = "blue", size = 5}) +local labelx = scene.addobj("label",{text="x"}) +labelx:setpos(10,1,0) +-- y +scene.addobj("polyline", {vertices = {0,0,0, 0,10,0}, color = "green"}) +scene.addobj("points", {vertices = {0,10,0}, color = "green", size = 5}) +local labelx = scene.addobj("label",{text="y"}) +labelx:setpos(0,11,0) +-- z +scene.addobj("polyline", {vertices = {0,0,0, 0,0,10}, color = "red"}) +scene.addobj("points", {vertices = {0,0,10}, color = "red", size = 5}) +local labelx = scene.addobj("label",{text="z"}) +labelx:setpos(0,1,10) scene.render()`},{header:"设置场景",slug:"设置场景",content:`设置场景需要用到 setenv 函数,具体用法如下 +local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true}) +可以简单地表示为如下形式 +local s = scene.setenv({key1 = value1, key2 = value2, ...}) +其中变量 s 存放返回的环境对象。下面将详细介绍函数的可选参数。`},{header:"场景可选参数",slug:"场景可选参数",content:""},{header:"参数列表",slug:"参数列表",content:`grid:场景的背景网格 +bgcolor:场景背景颜色 +camtype:摄像机视角 +clear:是否清除场景 +rotspeed & transpeed*:鼠标操作速度调整`},{header:"grid:场景的背景网格",slug:"grid-场景的背景网格",content:`可选值 值 +含义 "none" +默认值,无网格 "plane" +平地网格 "sphere" +球形网格`},{header:"bgcolor:场景背景颜色",slug:"bgcolor-场景背景颜色",content:`可选值类型 值类型 +示例 内置颜色 +"black", "white", "gray" 等 十六进制颜色 +"#ffffff", "#fff", "#000000", "#000"等 RGB表示的颜色 +"rgb(255, 255, 255)", "rgb(0, 0, 0)" 等 实例 +scene.setenv({bgcolor='gray'}) --设置背景颜色为内置的gray +scene.setenv({bgcolor='#eee'}) --设置背景颜色为#eee +scene.setenv({bgcolor='rgb(255, 255, 255)'}) --设置背景颜色为白色`},{header:"camtype:摄像机视角",slug:"camtype-摄像机视角",content:`可选值 值 +含义 "ortho" +正视。相当于向x和y构成的平面投影,用户视角在二维空间中。 "persp" +透视(默认值)。用户视角在三维空间中。`},{header:"clear:是否清除场景",slug:"clear-是否清除场景",content:"值设置为 true 时,清除场景 setenv 函数默认不清除原来的场景,除非手动设置参数 clear 的值为 true"},{header:"rotspeed & transpeed",slug:"rotspeed-transpeed",content:`值 +含义 rotspeed +设置鼠标的旋转三维对象的速度 transpeed +设置鼠标平移三位对象的速度 提示 +这两个参数通常不需要特别设置,使用默认值即可。`},{header:"其他",slug:"其他",content:""},{header:"有关高频率设置场景",slug:"有关高频率设置场景",content:`2023/03/21:目前发现过高频次设置场景会导致内存占用过高,进而导致浏览器崩溃的问题。因此建议尽量不要循环调用 scene.setenv() 函数。 +如果必须这么做,请确保调用频率相对较低,这样允许浏览器有一定的时间进行GC(垃圾清理),否则可能导致浏览器崩溃。`}]},{path:"/notes/",title:"笔记",pathLocale:"/",contents:[{header:"笔记",slug:"笔记",content:""},{header:"通用知识",slug:"通用知识",content:`Lua语言快速上手 +MicroCity的版本 +时间推进法 +面向对象编程 +有关工具`},{header:"MicroCity(桌面版)",slug:"microcity-桌面版",content:`结果可视化 +操作网络 +模型求解`},{header:"MicroCityWeb",slug:"microcityweb",content:`用户界面简介 +3D 场景 +3D 对象 +离散事件模拟和程序控制 +混合整数规划 +调试相关`},{header:"思路",slug:"思路",content:`仓库仿真 +通用绘图代码 +港口AGV服务流程三维仿真思路 本页目录所指的笔记内容适用于相应版本的MicroCity。特别感谢在编写和整理的过程中 孙卓老师(MicroCity作者) 给予的指导和帮助。`}]},{path:"/notes/cy-simulation.html",title:"港口AGV服务流程三维仿真思路",pathLocale:"/",contents:[{header:"港口AGV服务流程三维仿真思路",slug:"港口agv服务流程三维仿真思路",content:"本文思路仅供参考。 集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。"},{header:"实现场桥对集装箱的抓取",slug:"实现场桥对集装箱的抓取",content:""},{header:"总体思路",slug:"总体思路",content:"实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽象为对象。"},{header:"总体结构",slug:"总体结构",content:`具体的想法是将堆场对象作为数据模型(DataModel),主要存放各种数据,如存放集装箱实体、对应位置(行、列、高度)的集装箱坐标等数据;将场桥对象作为操作器(Operator),主要实现场桥的三维动画、实现对堆场对象中数据的管理。 +这样做的好处是可以将场桥和堆场解耦合,方便后续的扩展。此外,如果对象属性考虑得比较周全,可以方便地在同一个场景中创建多个对象,实现多个场桥对堆场的操作。`},{header:"事件和任务",slug:"事件和任务",content:"我打算为整体流程中涉及到需要移动的主要实体对象创建任务序列。这样可以做到在同一个场景中实现多个场桥的并行操作,各个场桥执行各自的任务,互不干扰。此外,还需要一个总控制程序控制每个时间节点的任务执行情况,并控制场桥的三维动画。"},{header:"业务流程",slug:"业务流程",content:"在这部分的仿真中主要业务流程聚焦于集装箱的移动。因此,最重要的就是集装箱所有权的流转。集装箱的所有权流转流程如下图所示: 集装箱对象流转过程"},{header:"对象结构",slug:"对象结构",content:"以下是这个仿真中主要涉及到的对象的结构"},{header:"实现方法",slug:"实现方法",content:""},{header:"堆场规模",slug:"堆场规模",content:`对于堆场对象,由于它的功能主要是存放集装箱对象及其相关数据(比如对应位置的坐标),那么就还会出现一个问题,堆场的规模有多大?因此确定堆场的规模是一个必要的步骤。在创建堆场对象时需要确定所创建的堆场的规模,即行数、列数、高度。这样可以在创建堆场对象时就确定堆场的规模,方便后续的操作。 +我的做法是首先确定堆场对象的占地大小和集装箱层数,然后由相关数据去计算最多能摆放几行几列的集装箱。 堆场占地大小方面,通过在创建对象时输入两点坐标来确定,根据两点连成的对角线构成一个矩形,从而确定堆场的占地面积。 +集装箱层数方面,通过在创建对象时输入一个数字来确定。根据这两个输入就就可以确定堆场的规模。`},{header:"事件和任务",slug:"事件和任务-1",content:`由于在这个仿真中需要移动的对象主要是场桥,因此每次循环执行任务的时候只需要操作场桥即可。 +因此,我打算将场桥的任务序列作为一个队列,每次循环执行任务的时候,从对象的任务序列中取出第一个任务执行,执行完毕后判断是否满足任务执行完毕的条件,如果满足则删除这个任务,执行下一个任务。这样可以保证每次循环执行任务的时候,场桥对象能够按照次序执行任务。 +执行任务的方法为 executeTask(dt) ,对象根据推进时间的长短 dt 执行任务。在 executeTask(dt) 中存放了处理任务的逻辑,包括判断任务类型、执行任务、删除任务等。 +如果场景中存在多个场桥,只需要将这些对象添加到执行任务对象的列表中即可。主控程序每次循环执行任务时,会遍历这个对象列表,依次执行每个对象的任务。 提示 +注意此处任务执行虽然在时间点上看是同时执行的,但是其实和对象所处的序列位置有关。 +一个例子就是:假设两个对象同时需要抢占位置A,那么按照任务序列的顺序,先执行的对象会抢占到位置A,后执行的对象会抢占失败,尽管它们在同一时刻都在抢占位置A。因此,此处不是严格的同时执行,而是同一时刻按照任务序列的顺序执行。`},{header:"业务流程",slug:"业务流程-1",content:`场桥首先从堆场中获取对应位置(行、列、高度)集装箱的坐标,并将吊具移动到堆场指定集装箱位置,抓取集装箱。集装箱所有权从堆场(cy.containers)转移到场桥吊具(rmg.attached)(通过解除表引用实现,将值设为 nil)。 +场桥将集装箱移动到过道并放下集装箱。以同样的方式将集装箱所有权从场桥吊具(rmg.attached)移动到过道(rmg.stash),表明集装箱可以被提取。 +如果有车辆将集装箱接走,则可以进一步将集装箱所有权从场桥过道(rmg.stash)移动到车辆上。`},{header:"运行结果",slug:"运行结果",content:""},{header:"实现AGV到达至服务的全流程",slug:"实现agv到达至服务的全流程",content:""},{header:"问题描述",slug:"问题描述",content:"使用事件调度法实现以上流程的三维化形式"},{header:"What's New",slug:"what-s-new",content:`上一个仿真的实现是实现这个仿真的基础。相比于上一个仿真,这个仿真最为显著的改进体现在: 使用面向对象编程模式,创建场桥、堆场(数据模型)、AGV、岸桥、船(数据模型)共4个类型的对象,并实现对象本体和其各部件的移动方法。 如果不了解面向对象编程,可以参考通用知识-面向对象编程 延续面向事件的仿真的思路,实现了总控制流程,实现同一时刻对多个对象同时进行控制(主要通过对象的 executeTask(dt) 和 maxStep() 及相关函数实现)。在面向对象的编程模式中,可以将 executeTask(dt) 和 maxStep() 视为接口,主程序通过实现这两个接口,实现对对象的控制。(尽管lua中似乎没有这部分的概念) +使用任务序列实现各个对象的流程,实现场桥和AGV之间、AGV和岸桥之间的相互等待,实现不同对象之间的任务协同。 +尝试将流程从堆场至AGV延伸至岸桥、船,实现两级排队等待。`},{header:"对象设计",slug:"对象设计",content:`由于属性和函数实在太多,因此使用思维导图的形式展示对象的设计。 提示 +此处占用篇幅较大,您也可以直接跳转到下一部分总体布局`},{header:"堆场",slug:"堆场",content:"堆场仍然作为数据模型。"},{header:"场桥",slug:"场桥",content:""},{header:"AGV",slug:"agv",content:""},{header:"岸桥",slug:"岸桥",content:"岸桥的代码和涉及结构主要衍生自堆场,因此后面不详细叙述。"},{header:"船",slug:"船",content:"船对象的主要作用也是作为数据模型,设计思路同堆场。"},{header:"总体布局",slug:"总体布局",content:""},{header:"总体流程",slug:"总体流程",content:"集装箱流转流程 相比于之前的仿真,这个仿真在流程上更进了一步,添加了AGV到达、排队的流程,还添加了岸桥服务、集装箱装船的流程。"},{header:"流程分析",slug:"流程分析",content:`AGV出现后,场桥、岸桥和AGV之间的流程也变得更加复杂。首先,AGV的到达是随机的,因此可能造成排队现象。其次,AGV的到达会触发场桥和AGV的流程,而场桥和AGV的流程又会触发岸桥的流程。因此,这个仿真的流程是一个多级流程,需要考虑多个对象之间的流程协同。 +特别是AGV和场桥之间的流程,其中存在AGV和场桥的相互等待。AGV到达的时候需要通知场桥提取货物。在场桥提取的过程中: 场桥需要等待AGV到达指定位置后,才能将货物移动到AGV上 +AGV需要等待场桥的抓取并将集装箱放在AGV上以后,才能将集装箱的所有权从场桥转移到AGV上 因此,AGV和场桥之间的流程是一个相互等待的流程。具体流程可以参考下图。 而岸桥的流程和场桥的流程类似,也是一个相互等待的流程。主要体现在: 当AGV到达指定位置时,岸桥可能在服务别的AGV,此时AGV要进行等待 +当AGV刚进入岸桥的服务区域时,通知岸桥到达指定位置,如果岸桥先到达指定位置,则此时岸桥要进行等待`},{header:"实现方法",slug:"实现方法-1",content:""},{header:"排队流程的实现",slug:"排队流程的实现",content:`AGV排队的情况我选择使用元胞自动机作为停车位的数据模型。其中,停车位的长度为: +停车位长度=对应数据模型中1个集装箱的长度+集装箱间隔长度 +\\text{停车位长度}=\\text{对应数据模型中1个集装箱的长度}+\\text{集装箱间隔长度} +停车位长度=对应数据模型中1个集装箱的长度+集装箱间隔长度 +由于AGV的长度比1个集装箱略长,因此需要占用2个停车位的长度。每次执行任务时,AGV会判断前方空间是否被阻塞,如果没被阻塞则向前移动。如果前方位置为目标bay,则前进后等待场桥作业,获取集装箱后继续以元胞为单位向前移动直到离开。场桥部分排队和岸桥部分排队原理也相同。 AGV元胞自动机排队模型示意图`},{header:"事件调度法的实现",slug:"事件调度法的实现",content:`在之前的仿真中,我使用了非固定步长的时间推进法来实现仿真。在这个仿真中,我使用了事件调度法来实现仿真。相比于时间推进法,事件调度法的特点是可以准确地将事件推进到发生的时刻,从而执行对应事件。 +你可能注意到了对象设计部分我将 executeTask() 和 maxstep() 标记为(interface),这是由于为了计算准确的推进时间,我需要在每个对象中实现 executeTask() 和 maxstep() 方法。其中,executeTask() 方法用于执行任务,maxstep() 方法用于计算距离到达下一个事件的发生时间(当前任务还剩多久能执行完),然后得到最大能够推进的时间,再去跟系统运行得到的间隔时间dt进行比较得到最大的推进时间。 +我认为课件中的下面这张图能够很好地表示如何使用事件调度法来进行仿真并刷新场景。其中,第一行指的是仿真的业务流程,第二行Refresh部分指的是刷新场景。`},{header:"运行结果",slug:"运行结果-1",content:`注意 +由于以下部分内容均为动图且图片体积较大。由于本站托管于GitHubPage,因此如果您没有的特殊网络环境可能会造成动图加载缓慢甚至加载失败。 提示 +如果您直接观看动图的时候动图区域出现了摩尔纹,可以尝试将动图点开放大看,再看看是否有改善。 场桥运行过程 岸桥运行过程 总体运行过程`}]},{path:"/notes/debug.html",title:"调试相关",pathLocale:"/",contents:[{header:"调试相关",slug:"调试相关",content:"本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。"},{header:"清除输出",slug:"清除输出",content:"右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。"},{header:"调试器快捷键",slug:"调试器快捷键",content:`在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。 F9 Step Over:跳过当前行,执行下一行 +F10 Step Into:进入当前行,如果当前行是函数调用,则进入函数内部 +F11 Step Out:跳出当前函数,执行函数调用的下一行`},{header:"Debug命令",slug:"debug命令",content:""},{header:"监视变量",slug:"监视变量",content:`在控制台使用 debug.watch() 命令监视变量。 +例如,在调试的过程中想要监视 a 变量的值,可以使用 debug.watch('a') 命令。 右键输出区域可以输入命令`},{header:"堆栈跟踪",slug:"堆栈跟踪",content:`使用 debug.traceback() 函数可以打印出当前的堆栈跟踪信息 +function myFunction() -- 某些代码逻辑 print(debug.traceback("Stack trace")) -- 其他代码逻辑 +end function anotherFunction() myFunction() +end anotherFunction() +输出结果 +Stack trace +stack traceback: +[string "function myFunction() ..."]:3: in function 'myFunction' +[string "function myFunction() ..."]:8: in function 'anotherFunction' +[string "function myFunction() ..."]:11: in main chunk`},{header:"运行状态",slug:"运行状态",content:`debug.debug() 进入Debug模式。常用于在程序运行过程中进入Debug模式。如果想要启动时就进入Debug模式,可以右键顶部▶️按钮。详见 用户界面简介 - 运行状态。 +debug.pause() 暂停程序运行。顶部运行按钮▶️会亮起,暂停按钮⏸️熄灭。`},{header:"其他调试命令",slug:"其他调试命令",content:`Lua 的 Debug 函数大多都适用于 MicroCity Web,可以参考: The Debug Library | Lua 5.4 Reference Manual +Lua 调试(Debug) | 菜鸟教程`}]},{path:"/notes/event-scheduling.html",title:"离散事件模拟和程序控制",pathLocale:"/",contents:[{header:"离散事件模拟和程序控制",slug:"离散事件模拟和程序控制",content:"本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。"},{header:"协程",slug:"协程",content:"MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 部分了解相关概念。"},{header:"coroutine.queue",slug:"coroutine-queue",content:`将函数或协程添加到协程队列中等待 +coroutine.queue(rt, f|co [, 参数列表...]) +参数 参数 +含义 rt +相对当前队列的时间,要求大于等于0。换句话说,也就是再过rt执行输入的函数或协程 f/co +函数或协程。如果是函数,只需要输入函数名`},{header:"coroutine.qtime",slug:"coroutine-qtime",content:`获取当前队列的时间 +local time = coroutine.qtime()`},{header:"示例",slug:"示例",content:`此处提供两个示例 协程添加任务:使用协程添加任务,并在函数中显示当前队列时间 +车辆移动:使用协程实现以真实世界的时间刷新场景`},{header:"协程添加任务",slug:"协程添加任务",content:`这个示例中展示了如何使用协程添加任务,并在函数中显示当前队列时间 +function Show() print("当前时间:",coroutine.qtime()) +end +function ShowShort() print("当前时间short:",coroutine.qtime()) +end coroutine.queue(10, Show) +coroutine.queue(20, Show) +coroutine.queue(15, ShowShort) +coroutine.queue(5, Show) -- 结果: +-- 当前时间: 5.0 +-- 当前时间: 10.0 +-- 当前时间short: 15.0 +-- 当前时间: 20.0`},{header:"车辆移动",slug:"车辆移动",content:`这个示例中展示了如何使用协程实现以真实世界的时间刷新场景 +scene.setenv({grid='plane'}) -- 设置场景网格背景 -- 车辆 +local car = scene.addobj('/res/2axle.glb') +car.speed = 1 --车速度 -- 初始时间 +local t = os.clock() +local dt = 0 -- 刷新时间状态t和dt(按照CPU间隔步进,达到和真实时间同步) +function refreshtime() dt = os.clock() - t t = os.clock() +end -- 协程更新场景 +function update() if not scene.render() then return end --渲染场景并检查程序是否中止 coroutine.queue(dt, update) --根据CPU步进时间添加下一次更新 carmove() --移动车辆 refreshtime() --计算本次dt +end -- 车辆移动 +function carmove() print("car move at ",t) local x, y, z = car:getpos() car:setpos(x,y,z+dt*car.speed) +end -- 初始更新(添加第一次更新) +-- 由于函数中涉及到添加后续更新,因此更新会自动循环 +coroutine.queue(dt,update) +在MicroCityWeb中打开`},{header:"随机数",slug:"随机数",content:""},{header:"创建随机数种子",slug:"创建随机数种子",content:`local seed = math.randomseed(x [, dist]) +参数 参数 +含义 x +随机数种子,会根据输入的不同数值返回不同的随机数。如果需要每次的值都不一样,可以考虑将随机数种子x设置为当前时间 dist +随机数分布(可选参数)。如果不设置,默认为均匀分布。如果设置这个参数,还可以设置 mu 和 sigma 作为对应分布的参数 dist参数可以设置键值为三种分布: 'normal':正态分布 +'exponential':指数分布 +'poisson':泊松分布 此外,还可以设置这几种分布的参数,其中 mu 键为均值,sigma 键为方差。`},{header:"示例",slug:"示例-1",content:`-- 创建泊松分布的随机数种子 +local seed = math.randomseed(os.time(), {distribution = "poisson", mu = "3"}) -- 泊松分布,均值为3 -- 输出随机数 +print(seed:random())`},{header:"程序控制",slug:"程序控制",content:`本文中的程序控制主要是指如何使用用户界面中的按钮控制程序的运行,包括暂停、恢复、停止等。 命令栏 主要是指命令栏的前3个按钮 MicroCity Web中的程序控制主要是指3D界面渲染中通过 scene 对象实现的3D界面运动的暂停、恢复、停止,具体的函数如下: +local state = scene.render() +此处将 scene.render() 的返回值存放于 state 变量中,state 变量的值为 true 或者 false,分别代表程序的运行状态为运行或者被终止(命令栏中按下按钮3)。 +3D对象的暂停渲染也是通过调用 scene.render() 来实现的。如果刷新3D对象是通过不断调用 scene.render() 函数实现,并且刷新间隔时间不是通过 os.sleep() 来控制,那么可以实现在3D界面上将渲染暂停在某个状态。这是因为如果使用 os.sleep() 来控制3D对象的运动速度,那么当点击暂停按钮时,很可能正好处于 os.sleep() 的过程中,导致程序无法立即响应,从而导致暂停按钮无效。因此,建议在控制3D对象的运动速度时避免使用 os.sleep(),而是通过添加其他参数的方式来控制推进时长,以达到控制3D对象运动速度的目的。`}]},{path:"/notes/lp.html",title:"模型求解",pathLocale:"/",contents:[{header:"模型求解",slug:"模型求解",content:`在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。 +规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划 提示 +本页内容基于 MicroCity 桌面版。如果你在寻找 MicroCity Web 版的混合整数规划求解方法,请参考 MicroCity Web 笔记中对应的 混合整数规划 部分。`},{header:"创建模型对象",slug:"创建模型对象",content:`创建规划模型对象,存入变量lp中。 +local lp = CreateLP() 官方文档中将创建的数学模型对象存入变量LPModel中,作用同本文的lp`},{header:"写入数学模型",slug:"写入数学模型",content:`此时,数学模型的对象已经创建并存入了变量lp中,可以对其进行更进一步的操作。数学模型一般分为两个部分: 目标函数 +约束方程 接下来,先介绍创建目标函数的具体做法。`},{header:"创建目标函数",slug:"创建目标函数",content:`MicroCity中,使用SetObjectFunction()设置模型对象的目标函数。允许选择目标函数求最大值或最小值。具体用法如下: 最大值 +最小值 SetObjFunction(lp, coeff, "max") --求最大值 SetObjFunction(lp, coeff, "min") --求最小值 "min"和"max"不区分大小写,写"MIN"和"MAX"也可以`},{header:"参数说明及示例",slug:"参数说明及示例",content:`参数 +作用 lp +数学模型对象。将数学模型输入函数中,为模型设置目标函数 coeff +目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。 "min"或"max" +确定目标函数求最大还是求最小。 coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​的最小值,则添加目标函数的做法如下: +-- 假设你已经创建了模型对象,并存入变量lp中 -- 4*x1 + 12*x2 + 18*x3 +local coeff = {4, 12, 18} -- 设置目标函数:求最小 +SetObjFunction(lp, coeff, "min")`},{header:"添加约束方程",slug:"添加约束方程",content:`在MicroCity中,添加模型约束的函数为AddConstraint(),用法如下: ≤ +≥ += -- 使用符号表达 +AddConstraint(lp, cons, "<=", b) -- 或者可以使用缩写表达 +AddConstraint(lp, cons, "le", b) -- 使用符号表达 +AddConstraint(lp, cons, ">=", b) -- 或者可以使用缩写表达 +AddConstraint(lp, cons, "ge", b) -- 使用符号表达 +AddConstraint(lp, cons, "==", b) -- 或者可以使用缩写表达 +AddConstraint(lp, cons, "eq", b)`},{header:"参数说明",slug:"参数说明",content:`参数 +作用 lp +数学模型对象。将数学模型输入函数中,为模型添加约束 cons +约束方程系数。和设置目标函数中的cons一样,也是一个table类型的变量。用于确定约束方程中各个变量的系数。 "<=" 或 ">=" 或 "==",或其对应的字母表达 +确定约束方程与右端项的关系 b +一个数字,表示约束方程的右端项。可以是变量也可以是常量`},{header:"示例",slug:"示例",content:`上面已经设置了目标函数为4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​,假设你要为这个函数添加两个约束方程: +{x1+3x3≥32x2+2x3≥5 +\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ +添加对应约束方程: +-- 添加约束:x1+3*x3≥3 +cons = { 1, 0, 3 } +AddConstraint(lp, cons, ">=", 3) -- 添加约束:2*x2+2*x3≥5 +cons = { 0, 2, 2 } +AddConstraint(lp, cons, ">=", 5) +不难注意到,系数的个数和目标函数中变量的个数一致。因此,在编程求解之前首先要搞清楚变量的总数,并安排好各个变量的位置。`},{header:"设置变量类型",slug:"设置变量类型",content:`MicroCity中的数学规划支持整数规划。如果没有对变量设置SetUnbounded(),默认变量的取值范围是非负实数(≥0)。下面介绍变量类型设置的详细做法。 +你可以将模型中第i个变量设置为整数变量或0-1变量。如果不将变量设置为这些类型,则默认变量为非负实数。 整数变量 +0-1变量 SetInteger(lp, i) --整数变量 SetBinary(lp, i) --0-1变量 让第i个变量的值可以是负数(默认取不到负数): +SetUnbounded(lp, i)`},{header:"模型求解和输出",slug:"模型求解和输出",content:""},{header:"模型求解",slug:"模型求解-1",content:`由于目标函数和约束方程都已经添加完毕,因此模型的求解就很简单了,只需要一步: +SolveLP(lp) +执行完这条语句后,存放于变量lp内的数学模型就求解完毕了🎉`},{header:"输出",slug:"输出",content:`求解完还需要输出,否则就不知道求解的结果如何。以下是常用的输出求解结果的函数。 +获取目标函数值: +GetObjective(lp) +获取第i个变量的值: +GetVariable(lp, i)`},{header:"SolveLP",slug:"solvelp",content:`SolveLP()函数在求解完毕后也有输出,输出代码的含义如下: 输出代码 +含义 0 +成功 -1 +无效的LP模型 -2 +无内存 1 +次优 2 +无可行解 3 +无界解 4 +退化 5 +遇到数值错误 6 +用户终止了求解 7 +超时错误 其他返回值表示的含义请参阅文档 4.8混合整数线性规划 中的SolveLP()函数。`},{header:"模型求解示例",slug:"模型求解示例",content:`这里提供一个简单的从建模至求解的示例供参考。(其实就是将前面的拼起来) +算例: +minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N +minf=4x_1+12x_2+18x_3\\\\ +s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N +\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N表示自然数(非负整数集合) 脚本 +-- 创建线性规划对象 +local lp = CreateLP() local n = 3 --设置目标函数个数 -- 目标函数:4*x1 + 12*x2 + 18*x3 +-- 设置目标函数系数,目标函数求最小 +local coeff = { 4, 12, 18 } +SetObjFunction(lp, coeff, "min") -- 添加约束1:x1 + 3*x3 ≥ 3 +cons = { 1, 0, 3 } +AddConstraint(lp, cons, ">=", 3) -- 添加约束2:2*x2 + 2*x3 ≥ 5 +cons = { 0, 2, 2 } +AddConstraint(lp, cons, ">=", 5) -- 由于没有设置SetUnbounded(), +-- 默认所有变量取值非负, +-- 因此不用针对变量非负添加约束。 -- 设置所有变量为整数 +for i = 1, n do SetInteger(lp, i) +end -- 求解模型 +SolveLP(lp) -- 输出目标函数值 +print("目标函数值:",GetObjective(lp)) -- 输出各个变量的值 +for i = 1, n do print("x",i,"=",GetVariable(lp, i)) +end +输出结果 +目标函数值:42 +x1=0 +x2=2 +x3=1`},{header:"建模的一些技巧",slug:"建模的一些技巧",content:""},{header:"线性化",slug:"线性化",content:`有时候我们会遇到多下标的建模问题,如决策变量为xijx_{ij}xij​,这个时候就要将其进行线性化编码。 +假设决策变量本身的形状共有3行4列,即: 列1 +列2 +列3 +列4 x11x_{11}x11​ +x12x_{12}x12​ +x13x_{13}x13​ +x14x_{14}x14​ x21x_{21}x21​ +x22x_{22}x22​ +x23x_{23}x23​ +x24x_{24}x24​ x31x_{31}x31​ +x32x_{32}x32​ +x33x_{33}x33​ +x34x_{34}x34​ 假设目标函数要将这些决策变量求和,即 F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​ 如果要将其输入目标函数,此时可以将其线性化为 x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​ +由于只有两个维度,因此可以使用两个for实现: +local cons = {} +for i = 1, 3 do -- 第一维 for j = 1, 4 do -- 第二维 cons[4 * (i - 1) + j] = 1 -- 填入系数 -- 其中 4 * (i - 1) + j 的思想类似于进位 end +end --结果: +-- cons长度为12,值都为1`},{header:"例题:指派模型",slug:"例题-指派模型",content:`下面以一个实际的例题来看看多维线性化的具体使用方法及其方便之处。 +甲、乙、丙、丁四人配送A,B,C,D四种货物,所需时间如表所示。若一种货物只交一人送货,则应指派何人配送何种货物,能使总的时间最少? 人\\工件 +A +B +C +D 甲 +14 +9 +4 +15 乙 +11 +7 +9 +10 丙 +13 +2 +10 +5 丁 +17 +9 +15 +13 假设货物A、B、C、D对应的编号依次为1、2、3、4,设 xij=1x_{ij}=1xij​=1 时表示第i个人送j货,xij=0x_{ij}=0xij​=0 时表示第i个人不送j货。 +则上述问题的数学模型可以表示为 +minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 +minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ +s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 +\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ +求解代码 +-- 效率矩阵 +local cost = { { 14, 9, 4, 15 }, { 11, 7, 9, 10 }, { 13, 2, 10, 5 }, { 17, 9, 15, 13 } +} local lp = CreateLP() -- 创建目标函数 +local coeff = {} +for i = 1, 4 do for j = 1, 4 do -- 此处可以轻松将二维数组转换为一维数组 coeff[4 * (i - 1) + j] = cost[i][j] end +end SetObjFunction(lp, coeff, "min") --添加约束 +for k = 1, 4 do -- 第i维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- j求和,判断i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) +end for k = 1, 4 do -- 第j维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then --i求和,判断j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) +end -- 求解模型 +SolveLP(lp) -- 输出目标函数值 +print("目标函数值:",GetObjective(lp)) -- 输出决策变量 +for i = 1, 4 do -- 第一维 for j = 1, 4 do -- 第二维 local x = GetVariable(lp, 4 * (i - 1) + j) if x~=0 then print("x[", i, "][", j, "]=", x) end end +end +输出 +目标函数值:29 +x[1][3]=1 +x[2][1]=1 +x[3][4]=1 +x[4][2]=1 结果 +人 +配送工件 x13=1x_{13}=1x13​=1 +甲 +C x21=1x_{21}=1x21​=1 +乙 +A x34=1x_{34}=1x34​=1 +丙 +D x42=1x_{42}=1x42​=1 +丁 +B`},{header:"中间变量的处理",slug:"中间变量的处理",content:`有时候模型中会存在一些中间变量,这些变量必须要在矩阵中有对应的位置才能对其进行求解,而这些中间变量不参与目标函数值的运算。可以将中间变量对应位置的系数设为0。 +假设x1,x2,x3,x4x_1,x_2,x_3,x_4x1​,x2​,x3​,x4​为决策变量,y1,y2y_1,y_2y1​,y2​为中间变量。目标函数为: +z=∑i=14xi +z=\\sum_{i=1}^4x_i +z=i=1∑4​xi​ +则目标函数系数可以设为: +local fcons = {1, 1, 1, 1, 0, 0} +接下来按照一般流程做就可以啦😎`}]},{path:"/notes/lua.html",title:"Lua语言快速上手",pathLocale:"/",contents:[{header:"Lua语言快速上手",slug:"lua语言快速上手",content:"由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。"},{header:"变量和函数定义",slug:"变量和函数定义",content:`lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。 +a = 1.5 +b = "string" +c = {} -- c为表,见下文介绍 +函数的定义 +function add(a, b) return a + b +end +上方简单定义了一个add()函数,目的是把输入的两个变量相加返回结果。 +变量分为全局变量和局部变量,函数也是如此。局部变量和函数的定义如下。 +-- 定义局部函数 +local function show(msg) print(msg) +end -- 定义局部变量 +local a = 1 +如果局部定义的内容(函数或变量)和全局定义的内容有冲突,以局部的内容优先。存在这种冲突时,你操作的内容是局部的内容。 +如果没有明确需要操作全局变量,建议尽量将变量定义为局部变量。这种做法可能会减少bug的出现,也是更加安全的做法。`},{header:"条件",slug:"条件",content:`就是if,具体实现形式有如下几种: 普通形式 if condition then print("condition==true") +end 带else的形式 if condition then print("condition==true") +else print("condition==false") +end 以及使用elseif的形式 if number > 0 then print("number>0") +elseif number < 0 then print("number<0") +else print("number==0") +end +Lua中相等判断的运算符为==,不等判断的运算符为~=。您可以将运算符运用于条件表达式。下面是一个简单的举例: +print(1==1) -- true +print(1~=1) -- false`},{header:"循环",slug:"循环",content:"记录一下最常用的两种循环: for&while"},{header:"for",slug:"for",content:`最普通的形式 +-- 输出1到10共10个数 +for i = 1:10 do print(i) +end +如果你比较熟悉C语言或C类语言,以上代码对应的形式如下 +for(int i=1; i<=10; i++){ printf("%d\\n",i); +} +考虑步长 +-- 输出10到1共10个数,步长为-1 +for i = 10:1:-1 do print(i) +end 步长为负数时,需要注意开始和结束的数字也应该为倒序 泛型循环 +可以直接遍历一个表中的所有元素。 +i为表元素的下标,从1开始;v为表元素的值。 +a = {4,7,9} +for i,v in ipairs(a) do print("index=",i,"\\tvalue=",v) +end ipairs适用于数组(i估计是integer的意思),pairs适用于对象,因为数组也是对象,所以pairs用于数组也没问题。`},{header:"while",slug:"while",content:`while的常用方法就一个 +local condition = true +while condition do print("while==true") condition = false +end +和C类语言一样。只要condition为true的时候while就会一直执行。当condition被设置为false的时候,while就会结束运行。`},{header:"循环操作符",slug:"循环操作符",content:`同其他语言的规定一样,break关键字用于跳出循环。 +LUA中没有continue,只有break。但是可以可以通过使用if+break的形式实现continue的功能。`},{header:"Lua的小特性:表",slug:"lua的小特性-表",content:`虽然Lua里面把它自己的数组称作table,但是我认为这个数据结构更类似于Python的集合或者json,里面可以存储任何东西,不受结构约束。 +collection = {{"a", 1, 2}, "abc", {2, 3}} +如果需要查询数组的长度,只需要在数组名前面添加#即可得到 +list = {1, 2, 3, 4, 5} +for i=1,#list do print(list[i]) +end +Lua的数组(表)下标从1开始,不同于C类语言的0。此处以前面定义的collection为例: +-- collection = {{"a", 1, 2}, "abc", {2, 3}} +print(collection[1][1]) --a +print(collection[2]) --abc +print(collection[3][2]) --3`},{header:"索引",slug:"索引",content:`Lua的表的索引非常灵活,可以是数字,也可以是字符串,甚至是其他类型的数据。 +下面是一些简单的例子: +local list = {} -- 以数字为索引 +list[1] = "a" -- 以字符串为索引 +list["b"] = 2 +list.message = "hello world" -- 等价于list["message"] = "hello world" print(list[1]) -- a +print(list["b"]) -- 2 +print(list.message) -- hello world`},{header:"添加元素",slug:"添加元素",content:`向指定位置添加 +table.insert(table, pos, value) --在指定位置(pos)添加元素 +或者 +table.insert(table, value) --向最后添加元素 +示例 +list = {1, 2, 3, 4, 5} +table.insert(list, 6) +-- {1, 2, 3, 4, 5, 6}`},{header:"删除元素",slug:"删除元素",content:`table.remove(table, pos) +示例 +list = {1, 2, 3, 4, 5} +table.remove(list, 2) +-- {1, 3, 4, 5}`},{header:"table的排序",slug:"table的排序",content:""},{header:"默认排序方法",slug:"默认排序方法",content:`可以使用函数对列表进行排序,最简单的用法如下 +table.sort(list) -- 默认升序排序 +此处提供一个实验案例 +-- 函数:打印列表 +function PrintList(list) -- 输出列表 local listStr = "" for i = 1, #list do listStr = listStr .. list[i] .. " " end print(listStr) +end local list = { 3, 7, 2, 5, 4 } -- 原始列表 PrintList(list) -- 输出原始列表 +table.sort(list) -- 对列表进行排序 +PrintList(list) -- 输出排序后的列表 -- 结果: +-- 3 7 2 5 4 (原始列表) +-- 2 3 4 5 7 (排序后的列表)`},{header:"自定义排序方法",slug:"自定义排序方法",content:`table.sort函数也可以使用自定义排序规则,但是这个规则你需要写在函数里。 +table.sort(list, function(a, b)) +function(a, b)是自定义的排序规则,要求最终返回一个bool值(true或false)。a和b分别为列表中的任意两项,如果函数返回true,则a在b的前面,否则b在a的前面。 +下面提供了2个示例供参考。`},{header:"示例1:上面代码改为降序输出",slug:"示例1-上面代码改为降序输出",content:`-- 此处省略PrintList()函数,函数代码与上方相同 local list = { 3, 7, 2, 5, 4 } -- 原始列表 PrintList(list) -- 输出原始列表 +table.sort(list, function(a, b) -- 对列表进行排序 return a > b -- 降序排序,如果a>b,则a在b前面 +end) +PrintList(list) -- 输出排序后的列表 -- 结果: +-- 3 7 2 5 4 (原始列表) +-- 7 5 4 3 2 (排序后的列表)`},{header:"示例2:二维数组中的排序",slug:"示例2-二维数组中的排序",content:`-- 函数:打印列表 +function PrintList(list) -- 输出列表 local listStr = "" for i = 1, #list do listStr = listStr .. "\\n" .. list[i][1] .. ", " .. list[i][2] end print(listStr) +end -- 原始列表 +local list = { { 3, 5 }, { 7, 6 }, { 2, 2 }, { 5, 1 }, { 4, 3 } } PrintList(list) -- 输出原始列表 -- 以列表中每项的第1维降序排序 +table.sort(list, function(a, b) return a[1] > b[1] +end) +PrintList(list) -- 输出排序后的列表 -- 以列表中每项的第2维降序排序 +table.sort(list, function(a, b) return a[2] > b[2] end) +PrintList(list) -- 输出排序后的列表 -- 结果: +-- 原始列表: +-- 3, 5 +-- 7, 6 +-- 2, 2 +-- 5, 1 +-- 4, 3 -- 以第1维降序排序: +-- 7, 6 +-- 5, 1 +-- 4, 3 +-- 3, 5 +-- 2, 2 -- 以第2维降序排序: +-- 7, 6 +-- 3, 5 +-- 4, 3 +-- 2, 2 +-- 5, 1`},{header:"table的引用",slug:"table的引用",content:`当没有对table进行对拷,而直接复制的时候,刚刚新得到的list2相当于原list1的引用,称为浅拷贝。当你修改浅拷贝得到的list2中的元素时,由于两个table是引用的关系,list1中的元素也会随之改变。 +上面的示例代码也遵循了这一原理。下面将用一个新的例子突出这一特点。`},{header:"示例:浅拷贝",slug:"示例-浅拷贝",content:`function PrintList(list) -- 输出列表 local listStr = "" for i = 1, #list do listStr = listStr .. list[i] .. " " end print(listStr) +end list1 = { 1, 2, 3, 4, 5 } +PrintList(list1) +-- 1 2 3 4 5 list2 = list1 +PrintList(list2) +-- 1 2 3 4 5 -- 修改list2的第2个元素 +list2[2] = 10 +PrintList(list2) +-- 1 10 3 4 5 PrintList(list1) +-- 1 10 3 4 5`},{header:"示例:深拷贝",slug:"示例-深拷贝",content:`而如果想要复制一个全新的列表list2怎么办呢?那么你就需要对table中的元素进行逐个复制,也称深拷贝。 +-- PrintList函数代码与上方相同 list1 = { 1, 2, 3, 4, 5 } +PrintList(list1) +-- 1 2 3 4 5 list2 = {} -- 新建一个空列表 -- 将list1的元素复制到list2 +for index, value in pairs(list1) do table.insert(list2, value) +end +PrintList(list2) +-- 1 2 3 4 5 -- 修改list2的第2个元素 +list2[2] = 10 +PrintList(list2) +-- 1 10 3 4 5 PrintList(list1) +-- 1 2 3 4 5 (没有发生变化) +在这个例子中,修改深拷贝得到的list2中的元素并不会对原来的list1产生影响。`}]},{path:"/notes/mip.html",title:"混合整数规划",pathLocale:"/",contents:[{header:"混合整数规划",slug:"混合整数规划",content:"本文档介绍MicroCity Web中混合整数规划的建模方法。"},{header:"创建混合整数规划模型",slug:"创建混合整数规划模型",content:`创建整数规划模型对象 +local mip = math.newmip() -- 将创建的模型对象赋值给 mip`},{header:"设置目标函数",slug:"设置目标函数",content:`MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。 +允许选择目标函数求最大值或最小值。具体用法如下: 最大值 +最小值 mip:addrow(coeff, 'max') --求最大值 mip:addrow(coeff, 'min') --求最小值`},{header:"参数说明及示例",slug:"参数说明及示例",content:`参数 +作用 mip +数学模型对象。将数学模型输入函数中,为模型设置目标函数 coeff +目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。 "min"或"max" +确定目标函数求最大还是求最小。 coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数 +4x1+12x2+18x3 +4x_1+12x_2+18x_3 +4x1​+12x2​+18x3​ +的最小值,则添加目标函数的做法如下: +-- 假设你已经创建了模型对象,并存入变量mip中 +-- 设定目标函数为 4*x1 + 12*x2 + 18*x3,求最小 +mip:addrow({4, 12, 18}, "min")`},{header:"添加约束",slug:"添加约束",content:""},{header:"添加约束方程",slug:"添加约束方程",content:`在MicroCity Web中,使用mip:addrow()添加剩下的约束方程,用法如下: ≤ +≥ += mip:addrow(cons, "<=", b) mip:addrow(cons, ">=", b) mip:addrow(cons, "==", b)`},{header:"参数说明",slug:"参数说明",content:`参数 +作用 mip +一开始创建的整数规划模型对象 cons +约束方程系数。和设置目标函数中的cons一样,也是一个table类型的变量。用于确定约束方程中各个变量的系数。 "<=" 或 ">=" 或 "==" +确定约束方程与右端项的关系 b +约束方程的右端项。`},{header:"示例",slug:"示例",content:`上面已经设置了目标函数为4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​,假设你要为这个函数添加两个约束方程: +{x1+3x3≥32x2+2x3≥5 +\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ +添加对应约束方程: +-- 添加约束:x1+3*x3≥3 +mip:addrow({ 1, 0, 3 }, ">=", 3) -- 添加约束:2*x2+2*x3≥5 +mip:addrow({ 0, 2, 2 }, ">=", 5) +不难注意到,系数的个数和目标函数中变量的个数一致。因此,在编程求解之前首先要搞清楚变量的总数,并安排好各个变量的位置。`},{header:"设置变量类型",slug:"设置变量类型",content:`MicroCity Web 中的数学规划支持整数规划。默认变量的取值范围是非负实数(≥0)。下面介绍变量类型设置的详细做法。 +你可以将模型中第i个变量设置为整数变量或0-1变量。如果不将变量设置为这些类型,则默认变量为非负实数。 整数变量 +0-1变量 mip:addrow('c1', 'int') --将第1个变量(第一列,col 1)设置为整数变量(Integer) mip:addrow('c2', 'bin') --将第2个变量(第二列,col 2)设置为0-1变量(Binary)`},{header:"模型求解和输出",slug:"模型求解和输出",content:""},{header:"模型求解",slug:"模型求解",content:`由于目标函数和约束方程都已经添加完毕,因此模型的求解就很简单了,只需要一步: +mip:solve() +执行完这条语句后,存放于变量mip内的数学模型就求解完毕了🎉`},{header:"输出",slug:"输出",content:`求解完还需要输出,否则就不知道求解的结果如何。以下是常用的输出求解结果的函数。 +获取目标函数值: +mip['obj'] +获取第i个变量的值: +mip['c'..i] +这里提供一个简单的从建模至求解的示例供参考。(其实就是将前面的拼起来) +算例: +minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N +minf=4x_1+12x_2+18x_3\\\\ +s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N +\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N表示自然数(非负整数集合) 脚本 +local mip = math.newmip() -- 设置目标函数 +mip:addrow({4, 12, 18}, "min") -- 添加约束 +mip:addrow({ 1, 0, 3 }, ">=", 3) -- x1+3*x3≥3 +mip:addrow({ 0, 2, 2 }, ">=", 5) -- 2*x2+2*x3≥5 -- 设置所有变量为整数 +for i = 1, 3 do mip:addrow('c'..i, 'int') +end -- 求解模型 +mip:solve() -- 输出目标函数值 +print("目标函数值:", mip['obj']) -- 输出各个变量的值 +for i = 1, 3 do print("x"..i.."=",mip['c'..i]) +end +输出结果 +目标函数值: 42.0 +x1= 0.0 +x2= 2.0 +x3= 1.0 在线运行 +在MicroCity Web中查看这个示例`},{header:"建模的一些技巧",slug:"建模的一些技巧",content:""},{header:"线性化",slug:"线性化",content:`有时候我们会遇到多下标的建模问题,如决策变量为xijx_{ij}xij​,这个时候就要将其进行线性化编码。 +假设决策变量本身的形状共有3行4列,即: 列1 +列2 +列3 +列4 x11x_{11}x11​ +x12x_{12}x12​ +x13x_{13}x13​ +x14x_{14}x14​ x21x_{21}x21​ +x22x_{22}x22​ +x23x_{23}x23​ +x24x_{24}x24​ x31x_{31}x31​ +x32x_{32}x32​ +x33x_{33}x33​ +x34x_{34}x34​ 假设目标函数要将这些决策变量求和,即 F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​ 如果要将其输入目标函数,此时可以将其线性化为 x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​ +由于只有两个维度,因此可以使用两个for实现: +local cons = {} +for i = 1, 3 do -- 第一维 for j = 1, 4 do -- 第二维 cons[4 * (i - 1) + j] = 1 -- 填入系数 -- 其中 4 * (i - 1) + j 的思想类似于进位 end +end --结果: +-- cons长度为12,值都为1`},{header:"例题:指派模型",slug:"例题-指派模型",content:`下面以一个实际的例题来看看多维线性化的具体使用方法及其方便之处。 +甲、乙、丙、丁四人配送A,B,C,D四种货物,所需时间如表所示。若一种货物只交一人送货,则应指派何人配送何种货物,能使总的时间最少? 人\\工件 +A +B +C +D 甲 +14 +9 +4 +15 乙 +11 +7 +9 +10 丙 +13 +2 +10 +5 丁 +17 +9 +15 +13 假设货物A、B、C、D对应的编号依次为1、2、3、4,设 xij=1x_{ij}=1xij​=1 时表示第i个人送j货,xij=0x_{ij}=0xij​=0 时表示第i个人不送j货。 +则上述问题的数学模型可以表示为 +minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 +minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ +s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 +\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ +求解代码 +-- 效率矩阵 +local cost = {{14, 9, 4, 15}, {11, 7, 9, 10}, {13, 2, 10, 5}, {17, 9, 15, 13}} local mip = math.newmip() -- 创建目标函数 +local coeff = {} +for i = 1, 4 do for j = 1, 4 do -- 此处可以轻松将二维数组转换为一维数组 coeff[4 * (i - 1) + j] = cost[i][j] end +end mip:addrow(coeff, "min") -- 添加约束 +for k = 1, 4 do -- 第i维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- j求和,判断i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) +end for k = 1, 4 do -- 第j维的值控制 local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then -- i求和,判断j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) +end -- 求解模型 +mip:solve() -- 输出目标函数值 +print("目标函数值:", mip['obj']) -- 输出决策变量 +for i = 1, 4 do -- 第一维 for j = 1, 4 do -- 第二维 local x = mip['c' .. 4 * (i - 1) + j] if x ~= 0 then print("x[" .. i .. "][" .. j .. "]=", x) end end +end +输出 +目标函数值: 29.0 +x[1][3]= 1.0 +x[2][1]= 1.0 +x[3][4]= 1.0 +x[4][2]= 1.0 在线运行 +在MicroCity Web中查看这个示例 结果 +人 +配送工件 x13=1x_{13}=1x13​=1 +甲 +C x21=1x_{21}=1x21​=1 +乙 +A x34=1x_{34}=1x34​=1 +丙 +D x42=1x_{42}=1x42​=1 +丁 +B`},{header:"中间变量的处理",slug:"中间变量的处理",content:`有时候模型中会存在一些中间变量,这些变量必须要在矩阵中有对应的位置才能对其进行求解,而这些中间变量不参与目标函数值的运算。可以将中间变量对应位置的系数设为0。 +假设x1,x2,x3,x4x_1,x_2,x_3,x_4x1​,x2​,x3​,x4​为决策变量,y1,y2y_1,y_2y1​,y2​为中间变量。目标函数为: +z=∑i=14xi +z=\\sum_{i=1}^4x_i +z=i=1∑4​xi​ +则目标函数系数可以设为: +local fcons = {1, 1, 1, 1, 0, 0} -- 前面4位为决策变量,后面2位为中间变量 +接下来按照一般流程做就可以啦😎`}]},{path:"/notes/network.html",title:"操作网络",pathLocale:"/",contents:[{header:"操作网络",slug:"操作网络",content:""},{header:"网络拓补化",slug:"网络拓补化",content:`网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题: 这条路是单向通行的还是双向通行? +这条路的起点是哪?终点是哪? 一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 这样,每条路就有了通行方向。一般规定出发点的符号为O,目的点的符号为D,这样,使用O和D就能清晰地描述每条路的方向。 +对于上图的示例,上方的道路O=1,D=2,所以方向描述为从1到2;下方的道路O=2,D=1,方向描述为从2到1。`},{header:"使用函数对网络进行拓补",slug:"使用函数对网络进行拓补",content:`MicroCity可以处理网络,所有函数的具体用法见参考文档:4.6 网络 +此处简单列举几种创建MicroCity中网络对象的方法: +local network = CreateNetwork() 创建一个空网络对象并返回此对象。network就是返回得到的空网络对象。 +创建对象后,可以使用AddLink和DelLink等函数在网络对象中创建连接。具体用法见参考文档。 +local network, nodes, links = CreateNetwork(Lines) +此处的Lines为一个矢量图形对象,类型为Line。MicroCity中的CreateNetwork()函数在这种用法中可以直接帮你在道路连线上添加起点和终点,并自动在返回的links对象中标上O点和D点的编号。 +也就是说,你只需要提供网络连线即可,剩下的拓补化工作可以由函数自动完成。我认为这可能是最常用的创建网络图并进行拓补化的方法。`},{header:"网络拓补的简单示例",slug:"网络拓补的简单示例",content:`-- 打开连线图层 +Shapes = Open("Shapes.shp") -- 拓补化网络 +network, network_nodes, network_links = CreateNetwork(Shapes) -- 创建图层,用于存放拓补后的网络节点 +Nodes = CreateShapes("Nodes", "point") +-- 将拓补化网络得到的网络节点复制到图层中 +AddField(Nodes, "ID", "int") +for i = 1, GetRecCount(network_nodes) do CopyShapeTo(Nodes, 0, 0, GetShape(network_nodes, i)) +end -- 创建图层,用于存放拓补后的网络连线 +Links = CreateShapes("Links", "line") +-- 将网络连线中原有的属性字段复制到图层中 +for i = 1, GetFieldCount(Shapes) do AddField(Links, GetField(Shapes, i)) +end +-- 为连线添加属性字段,稍后会通过函数将对应的数据添加到其中 +AddField(Links, "ID", "int") +AddField(Links, "O", "int") +AddField(Links, "D", "int") +AddField(Links, "IMPEDANCE", "double") --阻抗 +AddField(Links, "DIRECTION", "int") --方向 +AddField(Links, "CAPACITY", "double") --容量 +-- 将拓补化网络得到的网络线路复制到图层中(包括对应数据) +for i = 1, GetRecCount(network_links) do CopyShapeTo(Links, 0, 0, GetShape(network_links, i)) +end -- 更新图层 +Update(Nodes) +Update(Links) 示例改自MicroCity自带的编辑器 虽然一开始就输入了网络连线,但是在拓补化的过程中可能由于连线上的节点重合,在拓补化的过程中会把连续的连线拆成多段,因此得到的Links图层可能与输入的图层存在不同。而拓补化得到的节点Nodes和得到的连线Links是对应的,因此推荐使用拓补化处理完的Links图层作为网络节点之间的连线。`},{header:"踩坑经验:创建网络对象",slug:"踩坑经验-创建网络对象",content:`如果需要使用CreateNetwork(Nodes, Links)函数再次建立网络,需要保留以下在拓补化过程中添加的属性,否则将会出现网络初始化错误的问题: +AddField(Links, "ID", "int") +AddField(Links, "O", "int") +AddField(Links, "D", "int") +AddField(Links, "IMPEDANCE", "double") --阻抗 +AddField(Links, "DIRECTION", "int") --方向 +AddField(Links, "CAPACITY", "double") --容量 +如果只是一次性地进行网络拓补,不会再用拓补化过的网络重新创建网络对象,也需要先创建以上属性。拓补化后数据并不会根据属性名称填入,而是根据位置填入。 +如果只创建了O和D两个属性,则O的属性中会被填入ID数据,而D的属性中会被填入O的数据。而如果只根据上面的顺序创建了ID、O、D三个属性,由于数据顺序根据位置填入,则最终的填入的数据是正确的。`},{header:"CopyShapeTo函数",slug:"copyshapeto函数",content:`拓补的操作中使用了CopyShapeTo()函数,其作用是将一个Shape对象复制到Shapes图层中的对应位置,并根据输入的dx和dy在Shapes图层中进行位置变换。其中,dx和dy分别为在x和y方向上的位移量(理解为deltax和deltay)。 +CopyShapeTo(TargetShapes, dx, dy, Shape1 [, Shape2, ...]) +根据函数的用法可以看到,还支持复制到多个图层上的对应位置后再进行变换。 +如果只想将图形复制到对应图层的对应位置,而不进行变换,可以将dx和dy设为0,像这样: +CopyShapeTo(TargetShapes, 0, 0, Shape1 [, Shape2, ...]) +CopyShapeTo()函数的具体用法见 4.3 矢量图形和表格`},{header:"网络拓补化后算法的使用",slug:"网络拓补化后算法的使用",content:"对网络进行拓补化后,可以使用自带的函数求解很多问题,如:最短路径生成树、最短路径、最短距离等。本文以计算最短路径和最短路长为例介绍一下计算最短路径的流程及踩过的坑"},{header:"计算最短路径和最短路长",slug:"计算最短路径和最短路长",content:"要计算最短路径,首先必须要清楚计算网络中哪两个点之间的最短路径。这里以startID和endID分别表示起点和终点。本文假设你已经创建了网络对象,并存入名为Network的变量中。如果你不知道该如何创建一个网络图,可以参考上方介绍的 网络拓补化 流程。"},{header:"创建最小生成树",slug:"创建最小生成树",content:`第一步,先要以startID为开始点创建最短路径生成树。理论上以始点创建最短路径生成树后,就可以获取始点到网络上任意一点的最短距离。创建最短路径生成树可以调用GenSTPTree()函数实现。 +GenSTPTree(Network, startID [, endID]) +此处的endID不是必须的,如果有可以提供给函数。也就是说,您共有两种做法实现这一步: +GenSTPTree(Network, startID) --方法1 +GenSTPTree(Network, startID , endID) --方法2(建议) +一般认为提供的信息越完备,执行的效果越好。由于在计算最短路径之前就知道endID,因此建议将其提供给函数。 此处已经对函数的这种中括号写法进行了解释,后文中将会直接使用这种写法。 第二步,获取最短路径对应的信息。前面提到,确定起点和终点后才能确定两点之间的最短线路。由于前面使用始点startID创建了最小生成树,因此现在只需要提供终点endID就能获取到最短路径和最短路长。下面介绍了使用网络对象Network获取最短路长和最短路径的方法。`},{header:"获取最短路长",slug:"获取最短路长",content:`MicroCity的文档中提供了3种获取最短路径的方式。 +第一种,由于前面计算了最短路径生成树,已经输入了起始点的信息。因此现在只需要提供终点信息即可。(即使刚刚可能已经提供了终点信息)函数需要网络对象Network和终点endID用法如下。 +local len = GetSTPLen(Network, endID) +第二种,通过提供始点startID和终点endID计算两个点在网络上的最短路长。这种用法不要求在计算最短路径前先生成最短路径生成树,可以直接使用。Network为网络对象,用法如下: +local len = GetSTPLen(Network, startID, endID) +第三种,通过提供始点和终点的xy坐标计算两个点在网络上的最短路长。这种用法也不需要在计算最短路径前先生成最短路径生成树,可以直接使用。起点的坐标设为x1,y1;终点的坐标设为x2,y2,Network为网络对象,用法如下: +local len = GetSTPLen(Network, x1, y1, x2, y2)`},{header:"获取最短路径",slug:"获取最短路径",content:`MicroCity的文档中提供了3种信息可供获取,分别为: 点或线的ID序列 +点或线的索引(index)序列 +点或线的形状(Shape)序列。 函数的详细用法请参阅 4.6 网络 - 算法,此处仅以第2种:点或线的索引序列作为示例。 +返回点的序列: +GetSTPPath (Network, endID, "iNodeShp") +返回线的序列: +GetSTPPath (Network, endID, "iLinkShp") +这样就能返回所有点或线的索引序列了。`},{header:"踩坑经验:序列",slug:"踩坑经验-序列",content:`在Lua语言快速上手中介绍过Lua中的集合,它提供了丰富的特性帮助编写代码。但是没有听说过序列。序列是下面这个东西: +local x, y = GetCenterXY(Shapes) --借用一下这个函数 +里面的x,y就是一个序列。还有这种情况: +GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) --再次借用一个函数 +在这种情况下,输入的点越多,返回值也越多。如果输入4个点,可以这样处理: +-- 正常情况 +d1, d2, d3, d4 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -- 也可以仅取前两个返回值 +d1, d2 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -- 当然,只取一个返回值也可以 +d1 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) +上面的函数输入参数数量和输出参数数量是有关系的。如果输入了n个点的参数,就会返回n个点的距离。但是对于网络拓补来说,在返回最短路径的时候返回的都是参数序列,而我并不知道函数会给我传出多少个参数;而且当输出参数的个数太多的时候,也不太可能手动创建很多个变量存放这些参数。 +-- 错误做法: +local indexList = GetSTPPath(Network, endID, "iLinkShp") +-- GetSTPPath()函数不会返回一个table +-- 这里获取到的indexList只是第一个Link的index,是一个数值。 +既然等号左边没有办法改变,就从等号右边做出改变。还记得怎么定义一个最简单的table吗? +local list = {1, 2, 3, 4, 5} +右边的1, 2, 3, 4, 5其实可以看做一个序列。所以,只要给函数的返回值加上括号就能把他们全部捞起来 ( •̀ ω •́ )✧ +local indexList = { GetSTPPath(Network, endID, "iLinkShp") } +上面的这种做法得到的indexList就是一个table类型的变量了。然后就可以开始执行集合的各种操作了捏😋`}]},{path:"/notes/oop.html",title:"面向对象编程",pathLocale:"/",contents:[{header:"面向对象编程",slug:"面向对象编程",content:`面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。 网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实现过对象的消息传递,如果实现了会继续更新本文。因此下面主要介绍一下如何在适用于MicroCity的lua代码中使用封装。 提示 +本文中的代码示例适用于MicroCityWeb,对于桌面版的MicroCity不一定适用。此外,本文均为个人感悟,不保证概念绝对的正确性。`},{header:"面向对象编程的基本概念",slug:"面向对象编程的基本概念",content:""},{header:"类和对象",slug:"类和对象",content:`通俗来说,类是对象的模板,对象是类的实例(实体)。 +类是面向对象编程的基本概念,它是对一类事物的抽象。类的概念可以理解为一类对象,比如AGV、货架、场桥等。你可以把类理解为一类事物的模板,而对象则是根据这个模板创建出来的具体的事物。 +一个比较好的例子是上面提到的货架。货架是一个类,那么具体的货架就是一个对象。货架类中包含了货架的各种属性,比如货架的位置,装载的货物等。通过货架类创建出来的不同的货架对象都属于货架类,比如货架1、货架2等,尽管它们的属性可能不同,但是它们都是货架类的对象。`},{header:"类的属性和方法",slug:"类的属性和方法",content:"在MicroCity的仿真中,就我个人遇到的情况而言,类一般会有属性,但是不一定会有方法。延续上面举的货架的例子来说,属性是类的特征,比如货架的位置、货架上的货物等。方法是类的行为,通常使用函数体现,比如AGV将货架抬起、放下、AGV移动或者带动货架移动。"},{header:"仿真中使用面向对象的优点和缺点",slug:"仿真中使用面向对象的优点和缺点",content:""},{header:"优点",slug:"优点",content:`在MicroCity中,就涉及到多个同类物体移动、播放物体移动动画等场景而言(如AGV、货架、场桥移动等),需要进行比较大量的坐标计算和位置设置。如果对每个对象都实现一次,那么修改各个对象坐标的代码将会非常冗长,而且不易于维护。如果使用面向对象的编程思想,可以将数据处理的代码封装成一个个的对象,也能使代码更加更具有可读性和可维护性。 +此外,如果在场景中创建多个同类对象,各个对象的参数也可能各不相同。如果使用面向对象的方法封装,可以将各个对象的参数封装在各个对象自身中。当仿真流程或者规模变得复杂时,能够增加代码的复用性。 +对于仿真来说,最重要的是搞清楚仿真的业务流程和业务逻辑。使用面向对象编程可以使仿真的业务流程和业务逻辑体现得更清晰,使代码的可读性提高,更具有可维护性。 此外,当需要修改一类对象的业务逻辑时,只需要进入类中修改即可。比如修改一个港口中所有场桥的调度算法,由于所有场桥共用一套调度算法,因此只需要修改一次即可。 +就我个人的情况而言,采用面向对象的方法封装对象时大多是希望创建一个通用的对象,然后在后续的仿真中通过自动或手动的方式创建多个同类对象,而各个对象的参数各不相同。这么做会使得代码通用性增加,而且也能够使得代码更加易懂,为后续的维护和修改提供便利,为大规模的仿真打下基础。`},{header:"缺点",slug:"缺点",content:"如果仿真规模很小,代码量不大的简单的操作,不建议使用面向对象的方法封装代码。 使用面向对象的方法会增加代码行数,甚至会使代码看起来显得比原问题更加复杂。(当然你要用也不会有什么后果,只是看起来会比较奇怪而已)具体可以参考下文提供的代码示例,不难发现,代码主要篇幅用在描述类及其业务逻辑上,而业务流程的代码很简单,且占比很小。"},{header:"面向对象在Lua中的实现",slug:"面向对象在lua中的实现",content:"在Lua中,面向对象的概念通常使用table实现。table是Lua中的一种数据结构,它可以用来表示数组、字典、对象等。在面向对象的编程中,table也可以用来表示对象。"},{header:"示例",slug:"示例",content:`由于MicroCity中创建的对象都是table,因此我们可以在创建对象时,将对象的属性直接封装在table中,然后返回这个table。 +下面是一个例子: +-- 函数将返回一个AGV对象 +function AGV() -- 在MicroCity中创建一个AGV的3d对象 local agv = scene.addobj('/res/agv.glb') -- 设置对象的属性 agv.position = {0, 0, 0} -- 设置对象的位置 agv.speed = 1 -- 设置对象的速度 function agv:move(dx, dy, dz) agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- 修改对象坐标 agv:setpos(agv.position[1], agv.position[2], agv.position[3]) -- 设置对象位置 scene.render() -- 渲染场景,不建议在这里调用,这里只是为了演示 end return agv -- 返回对象 +end -- 对象的使用 +local obj = AGV() --创建对象 +obj:move(1, 0, 0) --对象向x方向移动1个单位 +或者你也可以选择在创建对象后,将对象的封装在一个table中,然后返回这个table。 +-- 函数将返回一个AGV对象 +function AGV() -- 直接在要返回的table中设置对象属性 local agv = { object = scene.addobj('/res/agv.glb'), position = {0, 0, 0}, speed = 1 } function agv:move(dx, dy, dz) agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- 修改对象坐标 agv.object:setpos(agv.position[1], agv.position[2], agv.position[3]) -- 设置对象位置 scene.render() -- 渲染场景,不建议在这里调用,这里只是为了演示 end return agv -- 返回对象 +end -- 对象的使用 +local agv = AGV() --创建对象 +agv:move(1, 0, 0) --对象向x方向移动1个单位 +还有一种创建对象的方法是使用setmetatable,这属于高级用法,但是感觉用到的场景不多后来我也用得比较少了。但是使用这种方法好像可以实现类的继承,如果你感兴趣可以自行搜索。这里提供我早期作业中创建货架类的代码实现供参考。(现在感觉这个类写得不算很好😂,比如 x,y 可以用 pos = {x, y} 代替,x_origin 和 y_origin 可以使用 origin = {x, y} 代替) +-- 货架 +Shelf = { x = 1, y = 1, cargo = {"box"}, -- 货物 x_origin = 1, -- 货架原始x坐标 y_origin = 1 -- 货架原始y坐标 +} function Shelf:New(x, y) local self = {} setmetatable(self, { __index = Shelf }) self.__index = self self.x = x self.y = y -- 设置原始坐标 self.x_origin = x self.y_origin = y return self +end`},{header:"类的类型",slug:"类的类型",content:`我在这里还想总结一下我创建过的类主要有什么类型。 3D实体类。 主要控制3D实体的运动,如AGV、场桥等,它们大多具有实体且需要移动。有的甚至还包含子对象,比如场桥对象具有吊具、绳索、吊车等子对象。 +数据模型。 比如堆场,货架、货物。具体来说比如堆场类中包含堆场的长宽、堆场中的货物、堆场中的集装箱等数据。 需要注意的是,我认为这些类型也不是严格区分的,某些类甚至共同具有这些类的特性,严格区分这个类属于哪种类型也没有太大意义。比如AGV类中也包含了AGV的位置、速度等数据,而货架类只是存储了货架模型,货架模型的移动还是交由AGV控制,而其更重要的功能是记录货架上货物的信息。因此,我认为这些类型只是一种大致的划分,具体的实现还是要根据实际业务流程和需求情况来。`}]},{path:"/notes/plots.html",title:"通用绘图代码",pathLocale:"/",contents:[{header:"通用绘图代码",slug:"通用绘图代码",content:`本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。 相关信息 +本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。`},{header:"直方图",slug:"直方图",content:`直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的分布情况。 +以下是用我包装的直方图对象绘制的直方图的示例`},{header:"导入直方图",slug:"导入直方图",content:'首先导入直方图的代码。目前有两种选择: 下载代码文件并导入(推荐):下载直方图代码文件 Histogram.lua,在MicroCityWeb中导入该文件,再引用该文件后即可使用。引用的代码如下: require("Histogram") --引用直方图 复制代码:直接将Histogram.lua文件中的代码复制到你的代码中,代码见下方。'},{header:"创建直方图对象",slug:"创建直方图对象",content:`创建一个直方图对象 +local plot = Histogram(list) -- list为数据集 +还可以在创建对象时对图的属性进行设置。 +local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end}) +属性的设置不是必须的,可以仅根据需要设置。此处就只设置了range、scale、fdisp属性。`},{header:"直方图属性设置",slug:"直方图属性设置",content:`上面提供了直方图属性设置的简单例子。根据代码,还可以设置更多的属性。具体见下表: 属性值 +作用 +示例 origin +设置图原点(左下角点) +origin = {-50, -50},将图的原点设置在(-50,-50)的位置 size +设置图横纵轴长度,可以理解为图的大小 +size = {100, 100},将图的x轴和y轴长度分别设置为100、100 scale +设置横纵坐标轴的分度值 +scale = {3, 2},将图的x轴和y轴分度值分别设置为3和2 axislabel +设置横纵轴标题 +axislabel = {"x", "y"},将图的x轴和y轴标题分别设置为"x"和"y" range +设置横纵坐标轴的显示范围 +range = {0, 10, 0, 20},将图的x轴范围设置为[0,10],y轴范围设置为[0,20] filled +设置是否填充柱状图 +filled = false,将柱状图设置为空心。默认样式为填充 fdisp +数据标签的显示函数,默认返回数量。设置数据标签显示函数时也会影响y轴刻度的显示。 +fdisp = function(v) return (v/n*100).."%" end,将数据标签改为按照比例显示(假设n为样本数)`},{header:"直方图高级用法",slug:"直方图高级用法",content:"动态刷新数据图 修改图中的数据。此处以向图中添加数据为例。其中假设rnd为添加的数据。也可以直接修改plot.data的值。 table.insert(plot.data, rnd) 刷新图 plot:refresh()"},{header:"示例",slug:"示例",content:""},{header:"基本用法示例:绘制泊松分布",slug:"基本用法示例-绘制泊松分布",content:`require("Histogram") --引用直方图 local seed = math.randomseed(1, { distribution = "poisson", mu = "3" +}) +local list = {seed:random()} --静态绘制 +for i = #list, 400 do table.insert(list, seed:random()) +end local histplot = Histogram(list, { range = {0, 10, 0, 50}, scale = {1, 5} +}) +scene.render()`},{header:"高级用法示例:动态刷新绘制泊松分布",slug:"高级用法示例-动态刷新绘制泊松分布",content:`这是一个绘制泊松分布并动态刷新数据图的示例。假设已经导入了Histogram对象,并将场景设为二维显示。 +require("Histogram") --引用直方图 local seed = math.randomseed(1, { distribution = "poisson", mu = "3" +}) +local list = {seed:random()} local histplot = Histogram(list, { range = {0, 10, 0, 50}, scale = {1, 8} +}) +scene.render() -- 动态绘制 +local count = 1 +while count < 1000 do local rnd = seed:random() table.insert(histplot.data, rnd) histplot:refresh() count = count + 1 scene.render() +end`},{header:"子图",slug:"子图",content:"子图(Subplot)是为了解决同时在界面中放置多个图的图定位和尺寸问题。名称借鉴自MATLAB。"},{header:"导入子图",slug:"导入子图",content:'首先导入直方图的代码。与直方图一样,导入有两种选择: 下载代码文件并导入(推荐):下载子图代码文件,在MicroCityWeb中导入Subplot.lua文件,再引用该文件后即可使用。引用的代码如下: require("Subplot") --引入子图代码 复制代码:直接将Subplot.lua文件中的代码复制到你的代码中。这样就不需要导入了。代码见下方。'},{header:"创建子图对象",slug:"创建子图对象",content:`创建子图时必须输入子图的行数和列数。子图的行数和列数决定了子图的数量。 +local subplot = Subplot(rows, cols) +还可以设置附加属性,对子图的位置和尺寸进行设置。这是一个在创建时设置子图位置和尺寸的例子。 +local subplot = Subplot(rows, cols, {span=10, diag={-80, -70, 80, 70}})`},{header:"子图属性设置",slug:"子图属性设置",content:`此处将对子图的属性进行详细说明。属性的设置不是必须的,可以仅根据需要设置。 属性 +作用 +示例 span +设置子图之间的间隔 +span=10,设置子图上下左右之间的间隔为10 diag +通过输入对角线两个点的坐标设置子图位置和大小 +diag = {-80, -70, 80, 70},设置子图的对角线范围从坐标 (−80,−70)(-80,-70)(−80,−70) 到坐标 (80,70)(80,70)(80,70)`},{header:"子图值读取",slug:"子图值读取",content:`通过属性创建子图后,或者修改子图属性并刷新后,可以对子图的计算值进行读取,获取Subplot中各个子图的原点位置和尺寸。主要通过以下几个属性值进行读取。 注 +此处假设子图对象创建后存放于 subplot 变量中。 计算属性 +含义 +示例 originpt +Subplot对象中各个子图的原点位置 +通过subplot.originpt[i][j][1]和subplot.originpt[i][j][2]能够获取到第i行j列的子图对应的原点位置 psize +Subplot对象中各个子图的尺寸 +通过subplot.psize[1]和subplot.psize[2]能够获取到subplot中子图对应的宽度和高度。(假设子图中所有图所需尺寸相同)`},{header:"示例",slug:"示例-1",content:`这是一个绘制子图范围的示例。假设已经导入了Subplot对象,并将场景设为二维显示。 +此处将一个2行3列子图中各个子图的显示范围绘制为一个矩形。其中子图范围用四个灰色点表示,子图位置用蓝色矩形表示。 +require("Subplot") --引入子图代码 local subplot = Subplot(2, 3, {span = 10}) -- 绘制Subplot对象边界点 +local lb = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[2],0}}) +local lt = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[4],0}}) +local rb = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[4],0}}) +local rt = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[2],0}}) -- 绘制范围 +for i = 1, subplot.row do for j = 1, subplot.col do scene.addobj("polyline", {size = 8, color = "blue", vertices={ subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0, subplot.originpt[i][j][1], subplot.originpt[i][j][2], 0, subplot.originpt[i][j][1], subplot.originpt[i][j][2]+subplot.psize[2], 0, subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2]+subplot.psize[2], 0, subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0, } }) end +end +scene.render()`},{header:"代码",slug:"代码",content:"可以根据代码的组合情况删去开头的 scene.setenv 代码。代码中的 scene.render() 是为了在动态绘制时刷新图像。"},{header:"代码文件下载",slug:"代码文件下载",content:`代码文件列表见 ModelResource/libs 名称 +链接 直方图 +ModelResource/libs/Histogram.lua 子图 +ModelResource/libs/Subplot.lua`},{header:"直方图代码",slug:"直方图代码",content:`Histogram +-- 初始场景设置 +local s = scene.setenv({camtype = "ortho"}) -- 返回一个直方图对象 +function Histogram(data, ...) local plot = { -- 默认值设置 origin = {-50, -50}, --坐标原点坐标 size = {100, 100}, --坐标轴长度 scale = {3, 2}, --坐标轴刻度分度值 range = {0, 10, 0, 20}, --xy轴范围 axislabel = {"x", "y"}, filled = true, --是否填充 fdisp = function(v) --数据标签显示 return v end, } -- 导入参数和fallback if ... ~= nil then for k, v in pairs(...) do plot[k] = v end end local barShape = "polygon" if plot.filled==false then barShape = "polyline" end -- 初始化 plot.axes = {} -- 坐标轴 plot.originlabel = {} -- 零点可能存在双坐标 plot.bars = {} -- 数据条 plot.xvalue = {} -- x轴刻度值(不包括最小值) plot.data = data function plot:deldata() --删除数据(private) if #plot.bars == 0 then return end for i = #plot.bars, 1, -1 do -- print("plot.bar:",i) plot.bars[i][2]:delete() plot.bars[i][1]:delete() end plot.zero:delete() for i = #plot.originlabel, 1, -1 do plot.originlabel[i]:delete() end for i = #plot.axes, 1, -1 do for j = #plot.axes[i], 1, -1 do plot.axes[i][j][2]:delete() plot.axes[i][j][1]:delete() end end end function plot:refresh() --反复绘图时调用(public) plot:deldata() -- 计算坐标刻度参数 local xmax = math.max(math.max(table.unpack(plot.data)), plot.range[2]) local xmin = math.min(math.min(table.unpack(plot.data)), plot.range[1]) local valueRange = xmax - xmin plot.range[1], plot.range[2] = xmin, xmax -- 绘图值统计 local barData = {} for i = 1, #data do -- 深拷贝 table.insert(barData, data[i]) end plot.barValue = {} -- 绘制零点 plot.zero = scene.addobj("points", { vertices = {plot.origin[1], plot.origin[2], 0}, size = 10 }) if plot.range[1] == plot.range[3] then -- 都是0 plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1] - 4, plot.origin[2] - 4, 0) else plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1], plot.origin[2] - 4, 0) plot.originlabel[2] = scene.addobj("label", { text = plot.range[3], size = 4 }) plot.originlabel[2]:setpos(plot.origin[1] - 4, plot.origin[2], 0) end -- X坐标刻度 local xaxis = {} -- x坐标轴对象,其中元素为{point,label} for j = 1, (plot.range[2] - plot.range[1]) / plot.scale[1] do -- 第几个刻度 local xpt = plot.origin[1] + j * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] -- X刻度位置 local pt = scene.addobj("points", { vertices = {xpt, plot.origin[2], 0}, size = 5 }) -- 刻度点 local label = scene.addobj("label", { text = string.format("%.1f", plot.range[1] + j * plot.scale[1]), size = 4 }) -- 刻度标签 table.insert(plot.xvalue, plot.range[1] + j * plot.scale[1]) -- 当前x刻度值 label:setpos(xpt, plot.origin[2] - 4, 0) xaxis[j] = {pt, label} -- 对象加入x轴集合 end plot.axes[1] = xaxis for i = 1, #plot.axes[1] do -- 根据x轴分值 local ub = plot.xvalue[i] -- 本次循环最大值 -- print("循环", i, "ub=", ub) -- for debug local value = 0 for j = #barData, 1, -1 do if barData[j] <= ub then value = value + 1 table.remove(barData, j) end end plot.barValue[i] = value -- 录入值 end local ymax = math.max(table.unpack(plot.barValue)) plot.range[4] = math.max(ymax, plot.range[4]) -- Y坐标刻度 local yaxis = {} -- y坐标轴对象,其中元素为{point,label} for i = 1, (plot.range[4] - plot.range[3]) / plot.scale[2] do -- 第几个刻度 local ypt = plot.origin[2] + i * plot.size[2] / (plot.range[4] - plot.range[3]) * plot.scale[2] -- Y刻度位置 local pt = scene.addobj("points", { vertices = {plot.origin[1], ypt, 0}, size = 5 }) -- 刻度点 local label = scene.addobj("label", { text = plot.fdisp(plot.range[3] + i * plot.scale[2]), size = 4 }) -- 刻度标签 label:setpos(plot.origin[1] - 4, ypt, 0) yaxis[i] = {pt, label} end plot.axes[2] = yaxis -- 绘制数据 local xunit = plot.size[1] / (plot.range[2] - plot.range[1]) * #plot.axes[1] -- x轴分度值 local yunit = plot.size[2] / (plot.range[4] - plot.range[3]) -- y轴分度值 -- 根据数值绘制直方图 for i = 1, #plot.axes[1] do -- 绘图 local xl = plot.origin[1] + (i - 1) * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] local xr = plot.origin[1] + i * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] local yb, yt = plot.origin[2], plot.origin[2] + plot.barValue[i] * yunit local bar = scene.addobj(barShape, { vertices = {xl, yb, 0, xr, yb, 0, xr, yt, 0, xl, yt, 0, xl, yb, 0} }) local label = scene.addobj("label", { text = plot.fdisp(plot.barValue[i]), size = 4 }) label:setpos((xl + xr) / 2, yt + 2, 0) plot.bars[i] = {bar, label} end end function plot:draw() --初始化绘制 -- 坐标轴对象 plot.coord = scene.addobj("polyline", { vertices = {plot.origin[1] + plot.size[1], plot.origin[2], 0, plot.origin[1], plot.origin[2], 0, plot.origin[1], plot.origin[2] + plot.size[2], 0} }) -- 坐标轴标题 if plot.axislabel~=nil then plot.axislabel[1] = scene.addobj("label", { text = plot.axislabel[1], size = 4 }) plot.axislabel[1]:setpos(plot.origin[1] + plot.size[1], plot.origin[2] - 8, 0) plot.axislabel[2] = scene.addobj("label", { text = plot.axislabel[2], size = 4, }) plot.axislabel[2]:setpos(plot.origin[1]-4, plot.origin[2] + plot.size[2]+6, 0) plot.axislabel[2]:setrot(0,0,1) end end plot:draw() plot:refresh() scene.render() return plot +end`},{header:"子图代码",slug:"子图代码",content:`Subplot +-- 属性参数 +-- local diag = {-80, -70, 80, 70} --lbx,lby,rtx,rty +-- local span = 10 +-- local row, col = 2, 2 +function Subplot(row, col, ...) local subplot = { span = 10, diag = {-80, -70, 80, 70}, originpt = {}, --存放各行列点坐标 psize = {} --子图大小 } subplot.row, subplot.col = row, col -- 导入参数和fallback if ... ~= nil then for k, v in pairs(...) do subplot[k] = v end end function subplot:refresh() -- 计算参数 subplot.psize = { (subplot.diag[3]-subplot.diag[1] - (subplot.col-1)*subplot.span)/subplot.col, (subplot.diag[4]-subplot.diag[2] - (subplot.row-1)*subplot.span)/subplot.row } local gwidth, gheight = subplot.psize[1]+subplot.span, subplot.psize[2]+subplot.span -- 重新计算originpt subplot.originpt = {} for i = 1, subplot.row do subplot.originpt[i]={} for j = 1, subplot.col do subplot.originpt[i][j] = {subplot.diag[1]+(j-1)*gwidth, subplot.diag[2]+(i-1)*gheight} end end end subplot:refresh() return subplot +end`}]},{path:"/notes/timelapse.html",title:"时间推进法",pathLocale:"/",contents:[{header:"时间推进法",slug:"时间推进法",content:"仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。"},{header:"时间推进法的分类",slug:"时间推进法的分类",content:`常见的仿真时间推进方法有三大类: 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。 +固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。 +主导时钟推进法:主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。`},{header:"实例",slug:"实例",content:""},{header:"事件调度法",slug:"事件调度法",content:`事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。在仿真过程中,仿真系统会根据当前仿真时间和各个事件发生的时间来确定下一个要发生的事件,并将仿真时间推进到该事件发生的时间。 +事件调度法主要分为以下3个主要步骤,这3个步骤也是控制事件调度法的主控程序的主要步骤: 时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻 +事件辨识:正确地辨识当前要发生的事件 +事件执行:正确地执行当前发生的事件 事件调度法基本原理流程图如下: +事件调度法在MicroCityWeb中的具体实现参见 离散事件模拟和程序控制 - 协程`},{header:"固定增量推进法",slug:"固定增量推进法",content:"固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。在每个步长内,若无事件发生,则仿真钟再推进一个单位时间T;若在该步内有若干个事件发生,则认为这些事件均发生在该步的结束时刻。 例题"},{header:"代码流程示例",slug:"代码流程示例",content:`while scene.render() do t = t + dt if t % cycle ~= work_time then d = d + v * dt print("出发后", t, "小时") else print("出发后", t, "小时,休息") end car:setpos(CastToLine(d)) --直线轨迹 os.sleep(200) +end 此为代码主要流程,无法直接使用`},{header:"主导时钟推进法",slug:"主导时钟推进法",content:`主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。主导时钟推进法可以分为两类:同步主导时钟和异步主导时钟。同步主导时钟是指所有模块都使用相同的主导时钟进行推进;异步主导时钟是指不同模块使用不同的主导时钟进行推进。 +自动化仓库仿真思路的最后一部分提到了改进空间,最终实现了同步主导时钟的主导时钟推进法。 实现了但是没有放出代码`},{header:"自动化仓库仿真向主导时钟推进法的改变",slug:"自动化仓库仿真向主导时钟推进法的改变",content:`具体来说,只在原来的基础上做了如下改动: 删除大部分与事件调度法有关的 os.sleep()。由于仿真流程比较简单,保留了与装卸货有关的事件调度法,优化资源占用。 +设置全局仿真时钟,将 Agv:Move() 函数的思路从“固定步长执行任务并刷新场景”的改为“监测仿真时钟时长变化,根据时长变化执行任务并刷新场景” +新增仿真速度调整。 从以上的改动可以看出,仿真的核心从事件任务转向了仿真时钟。其中,场景刷新的部分使用了 os.clock() 实现。`},{header:"主导时钟推进法实例",slug:"主导时钟推进法实例",content:`下面是一个有关于主导时钟推进法和 os.clock() 函数的简单的示例,修改自MicroCityWeb中内置的方块旋转案例。 +local obj = scene.addobj('box') -- 初始位置 +local x = 1 +local y = 1 +local z = 0 local rx, ry = 0.1, 0.1 -- x方向和y方向的旋转速度 +local simspeed = 10 -- 仿真速度 local t = 0 -- 全局仿真时钟 +local t0 = os.clock() -- 记录仿真开始的时间 +while scene.render() do local dt = os.clock() - t0 -- 计算自上次记录时间以来的时间差 t = t + dt -- 仿真时钟走过相应时间差长度的时间 -- 设置方块此刻的旋转位置 x = x + rx * dt * simspeed y = y + ry * dt * simspeed obj:setrot(x, y, z) t0 = os.clock() -- 记录仿真时间 +end +相关说明 当仿真速度 simspeed 为1时,表示仿真时钟与真实世界时钟的速度相同。simspeed 可以视作加速倍率。 +dt 表示两次记录时间之间的时间差,仿真中的时间步进根据 dt*simspeed 计算得到。 +相关信息 +需要注意的是,时间增量 dt 的数值在每个循环周期一般都不相同,dt 的具体大小一般取决于电脑的运算能力 提示 +有时两次记录时间之间没有太多耗时的操作,计算得到的 dt 可能为0。一般两次时间记录之间存在一个 scene.render(),这样一般能够保证两次采样的时间之间能够计算得到一个不为0的时间差值。`}]},{path:"/notes/tools.html",title:"有关工具",pathLocale:"/",contents:[{header:"有关工具",slug:"有关工具",content:`可能能够用到的工具 MapShaper 地图编辑器。可以编辑.geojson文件并导出为.shp文件 +Three.js Editor Three.js的在线3D对象编辑器。 🔨 持续更新...`}]},{path:"/notes/versions.html",title:"MicroCity的版本",pathLocale:"/",contents:[{header:"MicroCity的版本",slug:"microcity的版本",content:""},{header:"MicroCity",slug:"microcity",content:"MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwind)意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他操作系统,比如MacOS、Linux等。"},{header:"MicroCityWeb",slug:"microcityweb",content:`🎯访问MicroCity Web 📍(离线版)下载 +为了解决这个问题,开发者决定开发 MicroCity Web,这是一个可以直接在浏览器中运行的版本。 MicroCity Web 不需要任何安装,只需要使用现代浏览器(如Google Chrome、Microsoft Edge)访问它的网站即可。虽然相比于桌面版,运行在浏览器上可能会造成一定的性能损失,但是这使得用户可以在几乎任何操作系统上使用该软件,比如电脑系统Windows、MacOS、Linux和手机/平板系统Android等。 +尽管MicroCity的开发者推出了 MicroCity Web,您仍然可以继续使用以前开发的桌面版MicroCity。然而,桌面版本将不再更新新功能,所有新的功能和改进都将集中在 MicroCity Web 版中。这个决定的目的是确保 MicroCity 能够专注于一种版本,并在这个版本中提供最好的体验。这也使得 MicroCity 更容易管理和维护,避免了版本控制问题。 +值得一提的是,尽管桌面版本不再更新新功能,它仍然可以继续使用。如果用户已经习惯使用桌面版本,他们可以继续使用它。然而,如果用户希望体验最新的功能和改进,则需要改用 MicroCity Web 版。 +MicroCity Web 版也提供使用浏览器打包导出的离线版本(见上方 🔗链接)。 注意 +但是由于 Chromium 浏览器内核的更新,某些老旧的系统版本可能不受支持(如 Windows 8.1 及以下的 Windows 版本、32 位的 Windows 操作系统等)`},{header:"兼容性",slug:"兼容性",content:`MicroCity Web 版使用 Lua 5.4 作为脚本语言编写脚本。您可以在 MicroCity Web 运行环境或编辑器中输入 print(_VERSION) 指令查看使用的 Lua 版本。 +由于使用了实验性的 JavaScript函数,MicroCity Web 可能在以下浏览器内核中运行存在兼容性问题: iOS和iPad OS上的大多数浏览器(由于Apple强制使用Safari的浏览器内核) +FireFox浏览器 2023/9/29测试遇到的兼容性问题及部分技术细节 iOS 和 iPad OS: 无法打开本地文件(由于使用了 showOpenFilePicker() 方法) FireFox: 无法打开本地文件(由于使用了 showOpenFilePicker() 方法) 关于 showOpenFilePicker() 方法的影响参见 MDN Web Docs | showOpenFilePicker()`},{header:"总结",slug:"总结",content:`MicroCity Web 版的推出使得软件更加易用和普及,让更多的用户可以从中受益。同时,MicroCity 桌面版本仍然可用,使得那些已经习惯于使用该版本的用户可以继续使用,并让他们更容易地过渡到 MicroCity Web 版。 +本文作者在写这篇笔记的时候 MicroCity Web 正在被第一次用于教学环境中,已经基本能够正常运行并实现一定的仿真功能。本文作者的学习经历如下: MicroCity(桌面版):物流信息管理 +MicroCity Web :物流系统仿真 本站笔记内容仅供参考。如果本文内容由于时间的因素出现偏差,也欢迎各位在 Github 上通过 Pull Request 的方式对本站内容进行修正🥳`}]},{path:"/notes/visualization.html",title:"结果可视化",pathLocale:"/",contents:[{header:"结果可视化",slug:"结果可视化",content:"本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。"},{header:"改变形状颜色",slug:"改变形状颜色",content:`在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项: Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。 +Lookup Table:通过数值查询表格显示对应的颜色。 +Graduated Color:根据表中数值大小设置渐变色。`},{header:"Lookup Table 通过表中值改变颜色",slug:"lookup-table-通过表中值改变颜色",content:"将Type的属性值改为Lookup Table,根据表格中的数值改变图形的颜色,达到选中指定图形的效果。 此处示例将Lookup Table中的Attribute改为表格中的SELECT,通过表中的SELECT列值控制线的颜色(属性设置见上图)。当值为0时显示黑色,值为1时显示红色。表格中SELECT列的值和Lookup Table中的具体设置如下图。 最终实现的效果"},{header:"Graduated Color 根据值的大小显示渐变色",slug:"graduated-color-根据值的大小显示渐变色",content:"将Type的属性值改为Graduated Color,根据表格中不同数值的大小显示不同的颜色,达到显示渐变色的效果。 此处示例根据每个国家的人口数量显示渐变色。可以看到中国人口数量大,因此显示红色,印度人口数量也较大,因此显示橙色。其他地区人口数量较低,但也能通过颜色看出一些差别。 Graduated Color下的Colors属性中还可以调整其他配色方案。设置界面如下图,此处就不不一一列举了。 如果感兴趣可以参考文档2.1 展示世界地图中的示例手动尝试更改此属性。"},{header:"更改图形和标签的显示大小",slug:"更改图形和标签的显示大小",content:""},{header:"参考系的选择",slug:"参考系的选择",content:`显示内容尺寸的参考系有2个,一个是以地图为参考系,一个是以屏幕为参考系。此处将图形和标签的显示尺寸都设置为相同的参考系。 +内容以地图为参考系时,显示内容的大小会根据地图大小同步缩放,如下图: (以地图为参考系放大) (以地图为参考系缩小) 内容以屏幕为参考系时,无论地图怎么缩放内容的大小都差不多,如下图: (以屏幕为参考系放大) (以屏幕为参考系缩小) 因此,绘图的时候要根据绘图的目的选定参考系。 如果需要在地图上绘制确定尺寸的形状或者标明确定尺寸的标签,如绘制一个半径为10km的圆,此时应选用以地图为参考系。 +如果仅需要在任何尺寸下都能清晰显示标签和图形,此时可以选择以屏幕为参考系。`},{header:"参考系应用实例",slug:"参考系应用实例",content:"在图中绘制圆点,将圆的半径设置为圆的大小,并将圆的中心设置在每个绿点的中心上,灰色圆的大小表示每个绿点的覆盖范围大小。 图中以地图为参考系(Map Units),以16为半径为每个绿点都绘制了一个灰色的圆,表示每个绿点的覆盖范围。这些灰色的圆存放在名为Range.shp的图层内,图层类型为Points。"},{header:"参考系的设定",slug:"参考系的设定",content:`在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。 如图标记的两个位置可以分别调整图形尺寸的参考系和标签尺寸的参考系。 图形尺寸参考系设置:Size栏目下的Size relates to...调整图形尺寸的参考系,Default Size调整图形的相对于坐标系的尺寸。 +标签尺寸参考系设置:Labels栏目下的Size relates to...调整标签尺寸的参考系,Default Size调整的是标签(Labels)相对于坐标系的尺寸。`},{header:"更改显示的标签",slug:"更改显示的标签",content:""},{header:"手动更改显示的标签",slug:"手动更改显示的标签",content:`在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。上图中显示的标签为ID,如果需要改为表格中的其他列,可以更改Lables栏目下的Attribute属性实现。 +需要更改的属性位置如图,图中需要显示表中对应MSG列的值,只需要将Labels栏目下的Attribute属性值改为MSG即可。 但是每次更改图形并执行Update()函数后标签(Label)会取消显示。如果需要执行的脚本中含有此对于此图层的Update()函数,不必在每次执行完脚本后手动重新设置显示的标签,可以通过脚本自动选择显示的标签。`},{header:"自动更改显示的标签",slug:"自动更改显示的标签",content:`通过SetParameter()函数可以更改属性值。以上图Labels栏目下的Attribute属性为例,选中这条属性后可以看到底栏显示其ID为LABEL_ATTRIB,其类型为Choice。 需要注意的是,当类型为Choice时,参数值从1开始编号,编号顺次对应下拉菜单的内容。 点开这条属性以后,可以看到MSG在第二个。 由于Lua中编号一般由1开始,因此此处ID的编号对应1,MSG的编号对应2。需要操作对象为MSG,所以函数中需要填入Choice类型的参数值为2。 +此时已经得到了所有需要的参数,可以使用SetParameter()函数对显示的标签进行更改。 +-- transports为图形图层 +SetParameter(transports, "LABEL_ATTRIB", 2) SetParameter()函数需要在Update()函数执行后再执行,否则效果会被Update()函数覆盖。 现在回过头来再看看SetParameter()函数的具体用法: +SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object) 参数 +含义 参数1 +输入的对象,可以是Shapes、Table、Grid、Scene、Module 参数2 +其中的id为属性对应的ID。如果是上文的情况,就是LABEL_ATTRIB 参数3 +如果需要更改属性值,只接受数值(Number)、字符串(String)、对象(Object)三种类型 SetParameter()函数的介绍出现在文档 4.2 控制用户界面 中,请参阅。`},{header:"借助栅格图",slug:"借助栅格图",content:`栅格图也可以用于可视化,我认为栅格图最常用的场景就是绘制热力图。热力图的绘制主要通过修改栅格图上每个格子的值实现。如果不清楚栅格图的具体结构,可以先参考文档 3.3 栅格图。关于使用脚本控制栅格图,可以参考文档 4.4 栅格图形。 +一种使用栅格图绘制热力图的场景就是绘制地价图。在绘制地价图时,我们可以遍历栅格图上的每个格点,计算该格点到每个仓库的距离之和。然后将该格点的值设置为这个值,就可以得到一张热力图。这种方法可以帮助我们可视化地价的分布情况,并且可以用来发现地价的趋势和规律。`}]},{path:"/notes/warehouse-simulation.html",title:"自动化仓库仿真思路",pathLocale:"/",contents:[{header:"自动化仓库仿真思路",slug:"自动化仓库仿真思路",content:"本文思路仅供参考,建议做出适当改进。"},{header:"具体问题:基于元胞自动机的仓库仿真",slug:"具体问题-基于元胞自动机的仓库仿真",content:`其中,出入库位置可以更改,叉车为AGV。 +也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。`},{header:"基本假设",slug:"基本假设",content:`所有货架上的货物相同 +一个货架只放一个货物 因此,出库和入库可以看做完全相反的过程,所以此处只需要详细讨论出库的情况。即默认货架上本身就有货物。`},{header:"总体实现思路",slug:"总体实现思路",content:`将整个 3×33\\times33×3 的仓库中每个元胞的位置赋予 (x,y)(x,y)(x,y) 坐标,方便后续的移动操作。 +以AGV为核心,对货架进行操作。AGV处于升起状态移动货架时,只需要将货架的坐标位置同步设为AGV的位置即可达到AGV移动货架的效果。`},{header:"业务流程",slug:"业务流程",content:"先按照需求数量乱序生成订单列表,AGV根据订单顺序依次将货架移动到出库点进行出库操作。"},{header:"业务逻辑",slug:"业务逻辑",content:`当执行出库时,AGV先找到最近的货架并移动到那个货架的位置,抬起货架。为货架(AGV)设定移动的终点,计算曼哈顿距离差值。 每次移动前都通过是否有障碍物判断货架移动的方向(xxx 方向或 yyy 方向)。 +如果两个方向都被堵塞,则优先选择 yyy 方向(人为规定),将这个方向的障碍物递归移走,为货架移动腾出空间。如果 yyy 方向没有空间才选择移动 xxx 方向。`},{header:"过程优化:关于旧方法和新方法",slug:"过程优化-关于旧方法和新方法",content:`这两种方法都是可用的方法,但是 新方法对特定场景进行了优化,通过对障碍进行预判减少了操作步骤。 问题见下图 +旧方法:无障碍预判(进出货点在 x=3,y=3x=3,y=3x=3,y=3 的位置) 👉 AGV完成第一个货架的出库后,向第二个货架移动,但是发现第一个货架挡住了去路,因此又回到第一个货架的位置将其移开,再回到第二个货架进行出库操作。 +新方法:预判障碍(进出货点在 x=3,y=3x=3,y=3x=3,y=3 的位置) 👉 AGV完成第一个货架的出库操作后判断后一个货架是否需要移动其他位置的货架才能到达出入库点。如果需要,则移动障碍货架后才前往后一个货架进行出库。 相关信息 +本着尽量少占用出入库点的原则,当有空位时AGV将把在出入口的货架移走。因此某些看起来冗余的操作并非没有考虑全面。 不同数量货架对应的最优布局方案(动图) +8个货架的情况,上面已经进行了展示。下面仅展示表中货架数为5和7的情况。其他情况详见附件。`},{header:"仿真数据收集分析",slug:"仿真数据收集分析",content:""},{header:"出入库效率最高",slug:"出入库效率最高",content:`仿真结果如下图所示,表示相同货架数量下得到的效率最佳货架的货架布局 最佳货架布局:相同货架数量下,取出所有货物操作次数(ticks)最小 布局图说明 白色:没有放置货架 +浅灰色:货架,但是AGV一开始位于这个货架下方 +灰色:货架。 表格说明 货架数量:存在于布局图中的货架数量 +旧ticks:使用旧方法(无预判障碍)实现取货的操作次数。 +新ticks:使用新方法(预判障碍)实现取货的操作次数。后面将对新方法进行说明。 +黄色高亮:相同布局下操作次数最少(ticks最小)的方案`},{header:"空间利用率最大",slug:"空间利用率最大",content:`如果所有位置都放置货架,则无法访问到所有货架。因此,空间利用率最大的方法是放置8个货架。 +颜色说明 绿色:有货物的货架 +紫色:没有货物的货架 +浅紫色:AGV抬起的货架 +深紫色:AGV在这个货架下面,但是没有抬起货架 +深灰色:进出货点 有时候刷新太快可能看不出AGV抬起 进出货点在x=2,y=3的位置`},{header:"创新点",slug:"创新点",content:`额外考虑货物种类不同的情况。 +每次仿真会根据货架上的货物乱序生成需求。 +面向对象编程。使用面向对象的思想编程有助于将问题抽象化、有助于流程细节的改进;再加上好的命名方式会让整个程序的流程和逻辑清晰很多,不至于睡一觉起来就忘了😂 不同的货物类型用不同的颜色表示。AGV状态颜色、空货架的颜色、进出库点的颜色含义与之前相同。 紫色:没有货物的货架 +浅紫色:AGV抬起的货架 +深紫色:AGV在这个货架下面,但是没有抬起货架 +深灰色:进出货点 5个货架的情况示例 8个货架的情况示例`},{header:"仿真改进:三维化自动仓库仿真",slug:"仿真改进-三维化自动仓库仿真",content:"在这一部分题目也稍微有所变化,要求将元胞自动机仿真仓库案例三维化,进行自动化仓库仿真。具体要求如上图。"},{header:"总体思路",slug:"总体思路",content:""},{header:"三维化",slug:"三维化",content:`以基于元胞自动机的仓库仿真为核心,将其中元胞自动机仿真的部分改写为内部数据表,作为内部数据模型,对整个仿真过程的状态进行监视和控制。 +由于基于元胞自动机的仓库仿真使用了面向对象的方法封装对象,业务逻辑和流程的构建中大面积使用了对象方法,因此此处只需要改写对象方法(如 Agv:Move(dx, dy) 等)即可实现由元胞自动机仿真到三维化自动仓库的仿真。 如果程序整体结构设计优良,应用“面向对象”将会大幅提升程序的可维护性,降低移植难度。 对于AGV、货架直接套用现成模型;对于货物,只需要设置其距离货架的相对高度列表即可实现货物自动存放于指定高度。 提示 +如果需要套用现成模型,或者申请上传模型到本文作者维护的仓库,请参考文档 3D对象-外部模型`},{header:"出入库需求波动极大",slug:"出入库需求波动极大",content:`根据题目要求,基本上只存在有限的2种情况:3个货架、6个货架。 +由于货架数量情况有限,而基于元胞自动机的仓库仿真中得到了性能最佳的仓库布局,因此可以直接套用对应货架数量的最佳布局,本问题中只需要考虑固定货架布局下货物的位置摆放问题。 +对于3个货架的情况,其最佳布局属于高度对称的形态,距离出入库点的距离都为1,因此这种情况下只需要对1种情况进行仿真、收集其数据。 +对于6个货架的情况,选取了3种情况进行多次仿真,得到每种情况出入库耗费Ticks的平均值、最大值、最小值。 当前Ticks是AGV移动的次数,相当于单位操作时间。后文改进空间中提到了可以进行的改进 经过以上分析可以看出情况有限,因此可以通过控制货物需求总数不变,每次随机生成需求货物种类的方式对各种货物摆放位置进行仿真、对得到数据进行分析,最终确定最佳的货物布局方案。`},{header:"改进",slug:"改进",content:`在测试的过程中发现原有移动货架的策略不合理,改进了移动货架的策略。 +旧策略: 找到离AGV最近的装有需求货物的货架,将其移动到出入库点。 可以看到AGV已经将需要出库的同种货物(青色方块)移动到了出入库点,但是由于AGV移动的货架对象是旁边的货架,因此没有对已经在出入库点的货物进行出库。 +新策略: 找到离出入库点最近的装有需求货物的货架,将其移动到出入库点。改变策略后,没有发现以上提到的不合理情况出现。`},{header:"创新",slug:"创新",content:`由于测试的次数较多,因此将主体流程写入函数并进行适应性改进,实现自动对所有情况进行仿真测试并将数据输出。下图为自动仿真测试运行为示例。 自动仿真测试流程代码,仅供参考 +-- 批量测试 +local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- 测试需求(上限)序列 local output_string_list = {} -- 测试结果列表字符串 +for k, v in ipairs(cargo_ubs) do local test_result = {} -- 本需求上限测试结果序列 cargo_ub = v -- 设置需求数量上限 for j = 1, test_count do scene.setenv({ grid = 'plane', clear = true }) -- 清空场景内容 print("测试(", j, "/", test_count, "):需求数量为", cargo_ub) local tick = ModelRun() -- 运行仿真模型返回测试结果 table.insert(test_result, tick) -- 将测试结果插入测试结果序列 end local output_string = "" print("需求数量为", cargo_ub, "的测试结果序列:") for i = 1, #test_result do -- 输出测试结果序列到列表字符串 output_string = output_string .. test_result[i] .. "\\t" end print(output_string) table.insert(output_string_list, output_string) +end -- 输出测试测试结果列表 +for i, str in ipairs(output_string_list) do print("需求数量为", cargo_ubs[i], "的测试结果序列:", str) +end +在自动仿真测试的过程中发现了BUG,详见下文说明。`},{header:"货架布局方案",slug:"货架布局方案",content:`颜色说明 浅蓝色:出入库点 +白色:空格 +深蓝、红、黄:3种货物对应的颜色 条件假设 每个货架上都放有2个同类货物 +货物需求随机,没有种类偏好 +每次只取出一个货物`},{header:"仿真结果及分析",slug:"仿真结果及分析",content:"对每个货物布局方案中每种需求数量的情况仿真测试30次,求单方案结果中的最大值、最小值、平均值。最终得到结论为在6个货架的情况中,方案2的布局表现最优。"},{header:"方案3:3个货架",slug:"方案3-3个货架",content:""},{header:"方案6",slug:"方案6",content:"方案6平均Ticks总趋势图 方案6最优布局方案:方案2 还应绘制分方案的“需求量-最短平均服务时间”单位趋势图。以下以方案6-1为例,横坐标为货物需求数量,纵轴为最短平均服务时间(Ticks)。"},{header:"改进空间",slug:"改进空间",content:`由于题目没有给定具体事件的执行时间,也没有指定时间单位,因此此处只计量货架的操作次数作为耗费的时间。也就是说,时间是后计算的,我想大部分同学做到这里可能都是这样的思路。虽然最终得出的结果没有问题,但是思路还可以转变一下,适应于后面的学习。 +当前思路是以任务驱动的。虽然能够得到一个正确的结果,但是没有利用仿真时间,这种做法在只控制一个实体的时候不会出现问题。当要同时处理多个实体的时候,当前思路就无法做到同时操作多个实体完成任务,只能实现多个实体依次完成任务的情况。当前思路的具体流程如下: +由于应用的是时间推进法,因此仿真世界中有属于它自己的时间。对于我们来说,我们可以通过在仿真时间上乘一个倍率实现控制仿真速度,这个倍率就是仿真速度。此外,这种做法更加容易支持考虑多对象的情况。具体流程如下: +这样就改为了以时间为核心的仿真,在刷新任务执行进度的时候就可以直接刷新场景中的所有实体。由于仿真以时间为核心,因此就需要设定各种操作的速率/时间,保证时间计算的准确性。在MicroCityWeb中,有一些技巧可以用于时间推进法的仿真。`},{header:"使用系统时间更新仿真时间",slug:"使用系统时间更新仿真时间",content:`os.clock()函数可以获取系统当前的时间(以秒为单位,但是是小数)。有了这个函数就可以做到仿真与现实时间的同步。用法示例可以参考时间推进法 +由于整个仿真的核心为时间,因此需要对之前没有规定的操作规定其需要花费的时间长度。在改进的部分中,又额外考虑了以下操作所要花费的时间: 货物出入库所要花费的时间 +AGV举起和降落货架所要花费的时间`}]},{path:"/notes/web-ui.html",title:"用户界面简介",pathLocale:"/",contents:[{header:"用户界面简介",slug:"用户界面简介",content:"MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。"},{header:"界面分区概览",slug:"界面分区概览",content:`整体来看,MicroCity Web的界面大致可以划分为4个区域。 顶部-蓝色区域:对代码、文件执行各种操作 +左侧-绿色区域:代码编辑器 +右侧-红色区域:视图区域 +底部-黄色区域:输出信息、识别程序运行状态 下面将详细介绍这几个区域的用法和功能。`},{header:"蓝色:命令区域",slug:"蓝色-命令区域",content:"此区域的的内容如下图所示,共有9个可用按钮。"},{header:"程序控制",slug:"程序控制",content:"前3个按钮的功能大致都用于控制程序运行。详细作用分别如下: 开始运行/debug: 左键点击后将运行网页左侧代码编辑器内的代码;右键点击后进行代码调试(debug) 暂停运行: 如果程序正在运行,点击后程序将暂停运行(如果程序支持)。 停止运行/强行停止: 如果程序正在运行,左键点击后程序将停止运行。有时存在左键点击无法停止运行脚本的情况,右键点击可以强行终止其运行。"},{header:"代码编辑",slug:"代码编辑",content:`编号4~7的按钮主要与代码编辑有关。 显示/隐藏编辑器。 如果左侧的代码编辑器为开启状态,点击这个按钮后将关闭。如果为关闭状态,点击后会重新打开。如果使用右键点击,编辑器可以展开到全屏状态。 打开内置的代码 可以直接载入内置的代码(导入内置模型),如立方体、卡车、地球、世界地图等。具体的模型将在介绍画布区域时详细介绍。 内置代码列表 打开本地代码/上传文件 +左键点击:弹出打开文件的对话框,您可以选择本机上的某个代码文件(.lua)。确定打开文件后,代码文件文本将自动导入到左侧代码编辑器中。 +右键点击:可以选择一个或多个文件上传到MicroCity Web中。右键“保存”按钮(⑦)可以查看已上传的文件列表。 保存代码/下载 +左键点击:当您第一次保存文件时,点击保存按钮后会弹出保存文件对话框,您可以选择保存位置并填写文件名。如果您之前已经将该文件保存到本地,而此时您又对该文件进行了修改并想要保存更改,直接点击保存按钮即可直接将更改保存到之前保存的文件中。 +右键点击:可以查看已上传的文件列表,您可以点击列表中的文件并下载到本地。`},{header:"其他",slug:"其他",content:`共享。 点击按钮后,将会弹出一个输入密码的对话框。随后,您将会得到一个链接,任何人都可以通过这个链接打开您的共享。 +如果您在弹出的对话框中输入了密码,那么在其他人打开链接后,他们只能运行您的程序代码并观察运行结果,而无法查看您的代码(除非您告知他们密码);如果您没有输入密码,则其他人不仅可以运行您的代码查看运行结果,还可以查看您编写的代码。 查看帮助文档。`},{header:"绿色:代码编辑器",slug:"绿色-代码编辑器",content:"MicroCity Web左侧整合的代码编辑器源于AceEditor,因此也具有AceEditor的一些特性。"},{header:"快捷键",slug:"快捷键",content:`下面将介绍一些常用的快捷键,帮助你更好地编辑代码。 +最常用 Ctrl+Z:撤销 行操作 Ctrl+D:删除一行 +Ctrl+Shift+D:复制一行 +Alt+↑:行代码上移 +Alt+↓:行代码下移 查找内容 Ctrl+K:在代码中查找下一个与选中内容 代码缩进 Ctrl+[:增加代码缩进 +Ctrl+]:减少代码缩进 修改数值 Ctrl+Shift+↑:光标前的数字数值+1 +Ctrl+Shift+↓:光标前的数字数值-1`},{header:"红色:画布区域",slug:"红色-画布区域",content:"可以从内置代码导入场景,详见 命令区域 - 代码编辑 导入场景代码后要点击“运行”按钮才会载入场景 内置汽车模型 内置地球模型"},{header:"场景操作",slug:"场景操作",content:`对场景的操作包括视角移动、旋转都需要在画布区域进行。因此,下面将介绍画布区域的基本操作。 场景的放大缩小:鼠标滚轮向上滚动为放大,向下滚动为缩小。 +平移:按住鼠标右键拖动。 +旋转 场景旋转:按住鼠标左键拖动,以你的视角进行旋转 +对象旋转:点击对象,对象颜色改变后从对象上按住鼠标左键拖动,以对象为中心旋转。 无论是二维对象还是三维对象都遵循上述操作逻辑。`},{header:"黄色:代码输出区域",slug:"黄色-代码输出区域",content:`打开MicroCity Web后,代码输出区域如下。点击代码输出区域后整个区域会上移,能够看到更多的历史输出信息。 说到这个区域输出的信息,代码输出区域会输出以下信息: 脚本输出: 左侧是脚本的输出,包含输出时间、脚本输出内容。 +脚本运行状态: 右边第一行为脚本运行状态。state:ready表示脚本已经准备好开始运行(未运行),state:running表示脚本正在运行。 +MicroCityWeb版本号: 表示当前使用的MicroCityWeb版本号。如果与已知版本有差异,可以通过强制刷新加载最新版本。`},{header:"注意事项",slug:"注意事项",content:"关闭自动翻译: 如果你的操作系统语言不是英语且浏览器开启了自动翻译,需要手动关闭,否则代码运行将出现错误。"}]},{path:"/en/docs/1.1_what_microcity_can_do.html",title:"1.1 What MicroCity can Do",pathLocale:"/en/",contents:[{header:"1.1 What MicroCity can Do",slug:"_1-1-what-microcity-can-do",content:"MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast."},{header:"A Modeling Framework",slug:"a-modeling-framework",content:"Based on GIS, Networks and Mixed Integer Programming libraries, MicroCity can be used as a modeling framework to solve transporation problems, such as City Logistics and Shipping Planning:"},{header:"A Simulation Platform",slug:"a-simulation-platform",content:"Based on 3D CGI and Discrete Event Simulation Engine, MicroCity can be used as a simulation platform to evaluate logistic scenarios, such as Automated Warehouses and Container Terminals:"},{header:"Customized by Scriptable Modules",slug:"customized-by-scriptable-modules",content:"MicroCity can extend its functionality with modules which can be inherited from SAGA or scripted and debugged in Script Editor: Currently, MicroCity is mainly used in teaching and research. It can be freely distributed."}]},{path:"/en/docs/2.1_showing_a_world_map.html",title:"2.1 Showing a World Map",pathLocale:"/en/",contents:[{header:"2.1 Showing a World Map",slug:"_2-1-showing-a-world-map",content:"This tutorial will guide you in manipulating and visualizing GIS data in MicroCity."},{header:"Loading Data and Creating a Map",slug:"loading-data-and-creating-a-map",content:"Download the countries.shp (ArcGIS shapefile) and the countries.dbf (dBase file) in a same folder. Open MicroCity and load or drag the countries.shp into MicroCity and select Data Tab in Workspace panel. Double click Data->Shapes->Polygon->01. countries in Workspace panel."},{header:"Visualizing Coutries' Properties",slug:"visualizing-coutries-properties",content:"Right click 01. countries in the Workspace panel. Click Attributes->Table->Show in the popup menu. In the Settings Panel, find the Colors->Type option and select Graduated Color. In its sub-option Attribute, select POP_EST which is population property of countries. In the Setting Panel, find the Chart option and click the ... button. In the popup dialog, select pie in Chart Type option and select GDP_MD_EST in Attribute (Size) option and select EXPORT and IMPORT checkboxs in Fields option and click Okay button."},{header:"Editing Shapes",slug:"editing-shapes",content:"Select Action button at toolbar. Left click some country and right click it and select Edit Selected Shape in the popup menu. Then the shape will be in editing mode. You can change its polygon points and finish your editing by right click and select Edit Selected Shape again."}]},{path:"/en/docs/2.2_searching_for_countries.html",title:"2.2 Searching for Countries",pathLocale:"/en/",contents:[{header:"2.2 Searching for Countries",slug:"_2-2-searching-for-countries",content:"This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed."},{header:"GIS Data Structure",slug:"gis-data-structure",content:"In MicroCity, GIS data consists of three types of Shapes: Point, Polyline and Polygon, each of which can be visualized as a Map Layer. In a layer, a Shape object consists of one or more Parts, and every Part consists of one or more Points. A Shape object is also associated to a record in the Attributes Table. You can also edit the shape or its attributes (see 3.2). If you want perform a complex editing or handle a batch of shapes, you can use MicroCity Script, in which many built-in functions can be used."},{header:"Making a Query",slug:"making-a-query",content:`Suppose we want to find countries, each of which has a population of more than 100 million and is entirely in the northern hemisphere. So we need to check every point's coordinate in each shape and the population attribute of the shape. Open ScriptEditor and type following codes: +local Countries = Open("countries.shp") --Try to open the shapes layer +for i = 1, GetRecCount(Countries) do --Loop all the shape objects in the layer local country = GetShape(Countries, i) --Get the shape object of a country local north = true --Assume the country is in the northern hemisphere for j = 1, GetPartCount(country) do --Loop all of the parts in the shape for k = 1, GetPointCount(country, j) do --Loop all of the points in the shape part local x, y = GetPointXY(country, k, j) --Get coordinate of the point j if y < 0 then --If the latitude is less than 0 north = false --The north assumption is false end end end local pop = GetValue(country, "POP_EST") --Get the population property local name = GetValue(country, "NAME") --Get the country name if pop > 100000000 and north then --Check the two conditions Print(name, ": ", pop/100000000) --Print out the result end +end`},{header:"Running the Script",slug:"running-the-script",content:"Save the script to query.mcs and open it with MicroCity or drag it to MicroCity. Then you will find a query item appears in Modules Tab in Workspace panel. Double click the sub-item main. If a dialog pops up, select 01. countries and click Okay. The results will be shown in Messages panel."}]},{path:"/en/docs/3.1_ui_overview.html",title:"3.1 UI Overview",pathLocale:"/en/",contents:[{header:"3.1 UI Overview",slug:"_3-1-ui-overview",content:"MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules."},{header:"The Main Window and Components",slug:"the-main-window-and-components",content:""},{header:"Supported Files",slug:"supported-files",content:"MicroCity can open ArcGIS shapefile (*.shp), Grids file (*.sgrd), dBase file (*.dbf), Tabular text file (*.csv, *.txt), Point clouds (*.spc), Image file (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) and MicroCity 3D Scene (*.m3d). These data files are maintained in the Data Tab of the Workspace Panel. Module libraries (*.dll, *.mcs) are maintained and executed through the Modules Tab of the Workspace Panel."},{header:"Project Management",slug:"project-management",content:"The information of opened data files, module libraries, settings and sub-windows can be saved or opened in a MicroCity Project (*.mprj) through the menu File->Project. The mprj file does not contain any file's data. For easy maintenance, files in a project should be put into the same folder or sub-folders of the mprj file."}]},{path:"/en/docs/3.2_vector_shapes.html",title:"3.2 Vector Shapes",pathLocale:"/en/",contents:[{header:"3.2 Vector Shapes",slug:"_3-2-vector-shapes",content:"MicroCity can open, create and edit ArcGIS shapefiles (*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7) other vector file formats, such like Scalable Vector Graphics (*.svg) and AutoCAD Drawing Exchange Format (*.dxf), can also be imported or exported."},{header:"Opening, Creating, Saving and Closing Shapes",slug:"opening-creating-saving-and-closing-shapes",content:"Users can click Load button or File->Shapes->Load menu item to open an ArcGIS shapefile (*.shp) as a Shapes. Creating a new Shapes can be done from menu File->Shapes->New and the pop-up dialog as shown below. Users can choose one shapes type from Point, Line and Polygon. The relationship between a ArcGIS shapefile (*.shp) and a same named dBase file (*.dbf) is also shown. Saving a Shapes can be done from the right click context menu Save or Save As. You can also close a Shapes from the menu and get a prompt dialog to save it."},{header:"Showing and Editing Shapes",slug:"showing-and-editing-shapes",content:"Double click a Shapes from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle Action botton and right click a Shape in a Shapes layer and choose Edit Selected Shape then go to the Editing Mode. In this mode users can add/delete parts and add/delete points in a shape (for data structure of a shape see 2.2). The associated attributes table (*.dbf) of a Shapes can be accessed through right-clicking context menu Attributes->Table->Show (see the tutorial 2.1)."},{header:"Display Settings and Data Visualization",slug:"display-settings-and-data-visualization",content:"Users can change Shapes outline, fill, labels and other display settins from the Settings Panel. Some options can connect attribute data and give visualization functionalities (for example 2.1)."}]},{path:"/en/docs/3.3_raster_grids.html",title:"3.3 Raster Grids",pathLocale:"/en/",contents:[{header:"3.3 Raster Grids",slug:"_3-3-raster-grids",content:"MicroCity can open, create and edit SAGA Grid (*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) can be opened as Grid as well. By using modules (see 3.7) other raster file formats, such like ESRI Arc/Info Grid (*.adf) and Surfer Grid (*.grd), can also be imported or exported."},{header:"Opening, Creating, Saving and Closing Grids",slug:"opening-creating-saving-and-closing-grids",content:`Users can click Load button or File->Grid->Load menu item to open a Grid. Creating new Grid can be done from menu File->Grid->New and the pop-up dialog: The above right figure is the data structure and definitions of a Grid. A Grid starts from its bottom left corner which has coordinate (xMin, yMin), contains NX*NY Square Cells. Each cell has its own Integer Coordinate (X, Y), in the range of (0, 0) to (XMax, YMax). +Saving Grid can be done from the right click context menu Save or Save As. You can also close a Grid from the menu and get a prompt dialog to save it.`},{header:"Showing and Editing Grids",slug:"showing-and-editing-grids",content:"Double click a Grid from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle Action botton and select a range of cells in a Grid. Then the value of these cells can be edited in the Attributes Tab of the Settings Panel."},{header:"Display Settings and 3D View",slug:"display-settings-and-3d-view",content:"Users can show cell values, change color and set transparency of a Grid by using Settings Panel. Using button can creat a 3D surface of a Grid in which cell values are translated to elevation (see 3.6)."}]},{path:"/en/docs/3.4_3d_scenes.html",title:"3.4 3D Scenes",pathLocale:"/en/",contents:[{header:"3.4 3D Scenes",slug:"_3-4-3d-scenes",content:"MicroCity 3D Scene (*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (*.3ds), Wavefront OBJ (*.obj) and Stereolithography (*.stl) can be loaded as objects in a scene (see below) but not be stored in the .m3d file."},{header:"Opening, Creating, Saving and Closing 3D Scenes",slug:"opening-creating-saving-and-closing-3d-scenes",content:"Users can click Load button or File->Scene->Load menu item to open a Scene. Creating new Scene can be done from menu File->Scene->New and fill the pop-up dialog as shown below. After pressing Okay button an item will appear in the Data Tab of the Workspace Panel. Then Scene can be saved or closed through right-click menu:"},{header:"Showing and Editing 3D Scenes",slug:"showing-and-editing-3d-scenes",content:"Double click a Scene from the Data tab will give you a scene view. Left-mouse-dragging in a scene veiw will rotate the camera and right-mouse-dragging will translate the camera. Double-left-clicking a scene view can select objects and Double-right-clicking a scene view can popup a context menu (shown below). One can add objects, load objects and set objects, etc.. Note that the Rotation in the coordinate system should obey Left-hand rule. The illustration of the coordinate system and an example of the rotation around y-axis is shown below: The coordinate used in the position and rotation of an object is relative to its parent object. By default, the parent of a new object is null."},{header:"Display Settings",slug:"display-settings",content:"Users can change the background color, reference grid or other display options of a Scene by using Settings Panel."}]},{path:"/en/docs/3.5_tables.html",title:"3.5 Tables",pathLocale:"/en/",contents:[{header:"3.5 Tables",slug:"_3-5-tables",content:"Tabular files including dBase files (*.dbf), Text file (*.txt) and Comma Separated Values (*.csv) can be opened as Table and saved with MicroCity."},{header:"Opening, Creating, Saving and Closing Tables",slug:"opening-creating-saving-and-closing-tables",content:"Users can click Load button or File->Table->Load menu item to open a tabular file. Creating a new Table can be done from menu File->Table->New and the pop-up dialog as shown below. Saving a Table can be done from the right click context menu Save or Save As."},{header:"Showing and Editing Tables",slug:"showing-and-editing-tables",content:`Double click a Table from the Data Tab will give you a table view. Altering a table's stucture can be done by right click the table's head. If you click "Add Field" then, a dialog which guide you (as shown below). If you want insert a record to the table, you can right click the left numbers of the table and select a context menu item.`}]},{path:"/en/docs/3.6_maps_and_layers.html",title:"3.6 Maps and Layers",pathLocale:"/en/",contents:[{header:"3.6 Maps and Layers",slug:"_3-6-maps-and-layers",content:"In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid."},{header:"Opening, Creating, Saving, Printing and Closing Maps",slug:"opening-creating-saving-printing-and-closing-maps",content:"Because Maps are based on Shapes and Grids, they can not be saved or opened independently, but can be saved or opened along with a MicroCity Project (*.mprj). Creating a Map is by double clicking a Shapes or Grid from the Data Tab of the Workspace Panel. A Map window contains four coordinate bars which can be used to locate objects (see below). A Map can also be printed or closed from the context menu of the Maps Tab of the Workspace Panel."},{header:"Adding, Moving, Hiding and Closing Layers in a Map",slug:"adding-moving-hiding-and-closing-layers-in-a-map",content:"A Map can have multiple Layers, each of them represents a data item. One can add a Layer to a Map by double clicking a Shapes or a Grid from the Data Tab. A lower layer can be obscured by upper layers. One can move a layer by dragging, hide a layer by double clicking and close a layer through the menu (as shown below)."},{header:"Controlling Map Views",slug:"controlling-map-views",content:`When a data item or a layer is selected, this layer is called the active layer. One can toggle the Action button to select and edit an object in the active layer. By toggling the Zoom or Pan botton, the map can zoomed in, zoomed out or panned. If one lose in a map, he can use the Zoom to Full Extent button to get a full view of the map. Other zoom controlling buttons can be used to facilitate the map browsing. +The Synchronise button can be used if you want compare difference between two or more maps. The Ruler button can be used to meassure distances. Note that, by default, the unit of the distances measured is kilometer under the coordinate system of Earth. One can change the coordinate system to Non-Earth from the Settings Panel of the Map, and get Cartesian distance without unit. +One can create a 3D surface map by clicking 3D button, which need a appropriately sized Grid (see 3.3).`}]},{path:"/en/docs/3.7_modules.html",title:"3.7 Modules",pathLocale:"/en/",contents:[{header:"3.7 Modules",slug:"_3-7-modules",content:"The functionality of MicroCity can be extended by modules, one type of which is SAGA Module (*.dll). SAGA Modules contains many useful libraries for Shapes and Grids. Another type of Module is MicroCity Script (*.mcs), which can be edited and debugged with ScriptEditor (see 4.1)."},{header:"Loading, Closing and Executing Modules",slug:"loading-closing-and-executing-modules",content:"Modules can be loaded to MicroCity by clicking Load button or Modules->Load Module Library menu item. The Modules Tab of the Workspace Panel will display the loaded Libraries (each of which corresponding to a file) and their inside Modules . One can close or reload a Module Library from the context menu. Executing a moule has many ways: double clicking it, clicking the Execute button from the Settings Panel, or click the Execute context menu item. One can also Debug a MicroCity Script module by clicking the Debug context menu item, that needs the ScriptEditor running in the background. MicroCity can also capture runtime errors and pause the execution of modules."},{header:"Accelerating, Stopping the Execution of a Module",slug:"accelerating-stopping-the-execution-of-a-module",content:`MicroCity Script module is created with Lua language which is very fast. In some cases, if you want much more faster execution speed, you can click the Module Libraries in the Modules Tab of the Workspace Panel and switch the Script Running Mode in the Settings Panel from the Safe Mode to the Fast Mode. Then MicroCity will use LuaJIT to execute modules. +If a module is being executed, one can stop it by click the Execute button in the corresponding Settings. In Safe Mode the execution can be immediately stopped, but in Fast Mode the stopping is depend on the GetReady() function called in the script (see 4.2.`}]},{path:"/en/docs/4.1_si_overview.html",title:"4.1 SI Overview",pathLocale:"/en/",contents:[{header:"4.1 SI Overview",slug:"_4-1-si-overview",content:"MicroCity uses Modules (see 3.7) to extend its functionalities. One type of the modules is MicroCity Script (*.mcs) which can be edited and debugged in the ScriptEditor."},{header:"The Script Editor",slug:"the-script-editor",content:""},{header:"Coding and Debugging MicroCity Scripts",slug:"coding-and-debugging-microcity-scripts",content:"ScriptEditor is based on ZeroBrane. One can find detailed information there. For debugging, you should keep Script Editor being opened. Then right click the module from MicroCity and choose Debug item in the context menu (see 3.7). The execution can be indicated in the Code View of ScriptEditor. You can control the execution and watch variables with Debug Buttons."},{header:"The Lua Language and Embedded Functions",slug:"the-lua-language-and-embedded-functions",content:`MicroCity uses Lua 5.1 as its script language. One can find the reference manual there. MicroCity embeds many useful funtions in Lua, which can not only control user interfaces, manipulate data, but also can solve mathematical models and sun simulations. You should read following chapters for more information. +Conventions in this reference: +There are four major data types in Lua can be passed though embedded functions as parameters, namely Number, Boolean, String and Object. The type Object includes builtin Lua objects, such as Table, Function adn Thread..., as well as MicroCity objects, such as Shapes, Grid, Table and Scene.... To clarify the parameter type in embedded functions, we use capitalization, quotation mark and semantic information to avoid ambiguities in function descriptions. A lowercase word of a paramter means a Number. Sometimes, to present an integer parameter, a letter 'i' followed by a word is used, like iField. Starting with the letter 'b' and followed by a word means a Boolean, like bShow. A quoted word means a String. A capitalized word means an Object or a keyword. Following is an example of a embedded function description. +AddParameter (Module, ParentNode, "Value", "id" [, default = 0]) +In this case, the Module parameter should be a Module object. The ParentNode parameter should be a Node object, but it act as a parent Node. The "Value" parameter is a string, but it represent the builtin type Value in MicroCity, so this string can not be changed. The "id" parameter should be a user specified string. The default parameter is a number. The contents in a pair of '[' and ']' are optional. The character '|' among parameters means "or". +Encoding formats: +MicroCity uses ANSI encoding format to read and write data, such as shp, txt, csv and dbf. ScriptEditor and the embedded funtions use UTF-8 encoding format to read and write data, such as txt or csv.`}]},{path:"/en/docs/4.2_ui_control.html",title:"4.2 UI Control",pathLocale:"/en/",contents:[{header:"4.2 UI Control",slug:"_4-2-ui-control",content:'Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be found in the "user_interface" folder of the Project Tab in ScriptEditor.'},{header:"Basic User Interfaces",slug:"basic-user-interfaces",content:`Print ("hello" [,...]) +Prints values in the Messages Panel. +Note ("hello" [,...]) +Notifies users and pauses the execution. +SetProcessText ("processing") +Sets a text at the bottom left corner of MicroCity. +SetProgress (position, range) +Sets the progress bar of position/range that locates at the bottom right conner of MicroCity. +Sleep (milliseconds) +Pauses the execution for milliseconds. +GetReady () +MicroCity shares the same thread with the lua engine. Heavy calculations in lua will block the MicroCity interface. Use this function inside can let the MicroCity interface respond to user operations. Returns false if user cancel the current execution. +GetClickXY () +Returns x,y where a user clicked at a Map View. +GetDragExtent () +Returns bottom-left and top-right corner coordinate: Lx, By, Rx, Ty, which a user used mouse to drag a rectangle in a Map View.`},{header:"Data Objects",slug:"data-objects",content:`PATH +Internal global variable that holds a string of current working directory, such as "c:\\microcity". +Open (".\\\\shapes.shp" [, ".\\\\grid.sgrd" [, ".\\\\table.dbf" [, ".\\\\scene.m3d" , ...]]]) +Opens and returns Shapes, Table, Grid and Scene object from current working directory or opened data. +Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel) +Closes an opened or created Shapes, Table, Grid, Scene, Network, RndEngine or LPModel object. +Update (Shapes|Grid|Table [, bShow = ture]) +Update current changes of Shapes, Grid or Table object in MicroCity. The bShow indicates whether to create a view of the object. Returns false if user cancel the current execution. +CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...]) +Creates a Map View to show objects which can be arranged in layers by their order in the parameters.`},{header:"Modules and Parameters",slug:"modules-and-parameters",content:`AddModule ("Function" [, "name"]) This function can add a lua function as a module to current module library. The module's default name is the function's name. Returns a Module object. +AddParameter (Module, ParentNode, "Node", "id") +AddParameter (Module, ParentNode, "Value", "id" [, default = 0]) +AddParameter (Module, ParentNode, "Range", "id" [, low = 0 [, high = 1]]) +AddParameter (Module, ParentNode, "Check", "id" [, default = 0]) +AddParameter (Module, ParentNode, "String", "id" [, "string" = "") +AddParameter (Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]]) +AddParameter (Module, ParentNode, "File", "id" [, "c:\\\\default.txt" = ""]) +AddParameter (Module, ParentNode, "Color", "id" [, "color" = "255 255 255") +AddParameter (Module, ParentNode, "Shapes", "id") +AddParameter (Module, ParentNode, "Grid", "id") +AddParameter (Module, ParentNode, "Scene", "id") +AddParameter (Module, ParentNode, "Table", "id") +AddParameter (Module, ParentNode, "Field", "id") +These functions can add a parameter to a module's settings panel. Returns corresponding values or an object. The ParentNode can be set to the first return of a AddParameter function. If "Field" is set at the third place, the parent_node can be set to a Table or Shapes object to get its attributes table's head. +GetParameter (Shapes|Table|Grid|Scene|Module, "id") +Returns the parameter specified by "id" from the object's settings panel. +SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object) +Sets the parameter specified by "id" in the object's settings panel. Returns true if succeed. Note that the choice parameter should start from 1. A parameter's "id" can be found in the parameter's helper text shown as below.`}]},{path:"/en/docs/4.3_shapes_and_tables.html",title:"4.3 Shapes and Tables",pathLocale:"/en/",contents:[{header:"4.3 Shapes and Tables",slug:"_4-3-shapes-and-tables",content:'Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 and 3.2. Because Shapes can be treated as Tables with extra field with geographic data, some of embeded functions for tabular data manipulation can be used both in Shapes and Tables. Sample codes for this chapter can be found in the "shapes_samples" folder of the Project Tab in ScriptEditor.'},{header:"Tabular Data Manipulation",slug:"tabular-data-manipulation",content:`CreateShapes ("name", "Point|Line|Polygon") +Returns a Shapes object. +CreateTable ("Name") +Returns a Table object. +GetFieldCount (Shapes|Table) +Returns the number of fields in a Shapes or Table +GetField (Shapes|Table, iField) +Inputs the index (starts from 1) of a field and returns the field name and type ("Int", "Float", "Double" or "String). +AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...]) +Adds fields to a *Table or Shapes and returns booleans (true or false) by order. +DelField (Shapes|Table, iField) +Returns true if successfully delete a field. +GetRecCount (Shapes|Table) +Returns the total number of records in a Shapes or Table. +AddRecord (Shapes|Table) +Adds a record to a Shapes or Table and returns the index. +GetValue (Shapes|Table, "field_name", index1 [, index2, ...]) +Retrieve values from a specified field and indexes of a Shapes or Table. Returns multiple values by the order of indexes. +SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...]) +Sets values for a specified field and indexes of a Shapes or Table.`},{header:"Geographic Data Manipulation",slug:"geographic-data-manipulation",content:`GetSelections (Shapes) +Returns selected shape objects from a Shapes. +GetShape (Shapes, index1 [, index2, ...]) +Returns Shape objects from a Shapes by the order of indexes. +AddShape (Shapes, Shape) +Adds a Shape object to a Shapes and returns its index. +AddShape (Shapes [, x1, y1, x2, y2, ...]) +Adds a Shape object to a Shapes which defined as points. Returns the Shape object and index. +DelShape (Shape|Shapes) +Deletes a Shape or Shapes object and returns ture if successful. +AddPoint (Shape, x, y [, iPart = 1]) +Adds a point to a Shape and returns ture if successful. +InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]]) +Inserts a point to a Shape and returns ture if successful. +SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]]) +Sets a point coordinates in a Shape and returns ture if successful. +DelPoint (Shape, iPoint [, iPart=1]) +Deletes a point at position iPoint from a Shape and returns ture if successful.. +DelPart (Shape, iPart) +Deletes a part from a Shape and returns ture if successful. +GetPartCount (Shape) +Returns the number of parts in a Shape. +GetPointCount (Shape [, iPart]) +Returns the number of points in a Shape. +GetPointXY (Shape [, iPoint [, iPart = 1]]) +Returns all points' coordinates: x1, y1, x2, y2, ... from a Shape or a specified point's coordinate. +CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...]) +Copys Shape objects to a target Shapes with relative translation (dx, dy) and returns new Shape objects. +MoveShapeTo (dx, dy, Shape1 [, Shape2, ...]) +Translates Shape objects to its relative position (dx, dy). +GetCenterXY (Shapes) +Returns the center coordinate (x, y) of a Shapes. +GetCenterXY (Shapes, index1 [, index2, ...]) +Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects specified by indexes in a Shapes. +GetCenterXY (Shape1 [, Shape2, ...]) +Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects. +GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) +Returns the total distance between every two pairs of coordinates (x, y). +GetShapeLen (Shape1 [, Shape2, ...]) +Returns lengths of Shape objects. +GetShapeArea (Shape1 [, Shape2, ...]) +Returns areas of Shape objects. +GetShapeType (Shape|Shapes) +Returns the type ("Point", "Line" or "Polygon") of the a Shapes or Shape object. +GetExtent (Shapes) +Returns the extent coordinates (Lx, By, Rx, Ty) of a Shapes's extent. +GetExtent (Shapes, index) +Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape indexed in a Shapes. +GetExtent (Shape) +Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape. +GetIntersection (ShapeA, ShapeB) +Returns a Shape (Point, Line or Polygon) object of the intersection of two Shapes. +GetValue (Shape, "field_name") +Returns the value of specified field of a Shape. +SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...]) +Sets values in different fiedds for a Shape. +SetCoorSys ("Earth"|"Non-Earth") +Sets coordinate system. If using "Earth", distances, lenths and areas are calculated according to the earth ellipsoid coordinate system. By default the "Non-Earth" is used, which is cartesian coordinate system.`}]},{path:"/en/docs/4.4_grids.html",title:"4.4 Grids",pathLocale:"/en/",contents:[{header:"4.4 Grids",slug:"_4-4-grids",content:'Grids in MicroCity have simple structure (3.3) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be found in the "grid_samples" folder of the Project Tab in ScriptEditor.'},{header:"Cellular Data Manipulation",slug:"cellular-data-manipulation",content:`CreateGrid ("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]]) +Returns a Grid object. +GetCellSize (Grid) +Returns the Cellsize value of a Grid. +GetGridMaxXY (Grid) +Returns XMax, YMax of a Grid. +ConvertToGridXY (Grid, x1, y1 [, x2, y2, ...]) +Converts real coordinates to coordinates in a Grid. Returns X1, Y1, X2, Y2, ... . +ShapeToGrid (Grid, Shape, value) +Rasterizes a Shape in a Grid. The cell values will be set according to the covering area and the inputed value. +ShapeToGrid (Grid, Shapes, "field_name") +Rasterizes all Shape objects in a Shapes. The cell values will be set according to the covering area and the values of Shapes field. +GetValue (Grid, X1, Y1 [, X2, Y2, ...]) +Returns cells' (specified by Grid coordinates) values: value1, value2, ... . +SetValue (Grid, value, X1, Y1 [, X2, Y2, ...]) +Sets values for cells specified by Grid coordinates. +GetCenterXY (Grid) +Returns the center real coordinate (x, y) of a Grid. +GetCenterXY (Grid, X1, Y1 [, X2, Y2, ...]) +Returns the real coordinates of cells' centers: x1, y1, x2, y2, ... . +GetExtent (Grid) +Returns the leftbottom and righttop corner of a Grid's extent: Lx, By, Rx, Ty. +GetExtent (Grid, X, Y) +Returns the leftbottom and righttop corner of a cell's extent: Lx, By, Rx, Ty. +GetFractalDim (Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0]) +Calculates fractal dimension of the specified area in a Grid. Returns dimension, RSQ of linear regression, and the number of boxes in every fold.`}]},{path:"/en/docs/4.5_3d_scenes.html",title:"4.5 3D Scenes",pathLocale:"/en/",contents:[{header:"4.5 3D Scenes",slug:"_4-5-3d-scenes",content:'Scenes and inside 3D objects (3.4) can be scripted. Sample codes for this chapter can be found in the "3d_samples" folder of the Project Tab in ScriptEditor.'},{header:"3D Scene and Object Manipulation",slug:"_3d-scene-and-object-manipulation",content:`CreateScene ("Title" [, RotSpeed=1] [, TransSpeed=1]) +Creates a new 3d scene and returns the object. +AddZipTo3DPath (Scene, "filename.zip") +Adds a zip file to the search directory and returns true if succeed. It is useful for collecting a large amount of files. +LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg") +Loads six image files as the skybox of a 3d scene. +LoadObject (Scene, "filename.3ds" [,shadow = false [, AnimationSpeed]]) +Loads a 3d object from a file and returns the object. +AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255]) +Adds a light object and returns the object. +Add3DLabel(Scene, "label" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]]) +Adds a 3D label at (0,0,0) and returns the object. +Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0]) +Adds a 3D line object frome (x1, y1, z1) to (x2, y2, z2) and retruns the object. +Add3DRect (Scene, length, width [, r = 180, g = 180, b = 180]) +Adds a 3D rectangular object from (-length/2,0,-width/2) to (length/2,0,width/2) and returns the object. +Add3DBox (Scene, length, width, height [, r = 180, g = 180, b = 180 [, bShowEdge = true]]) +Adds a 3D box object from (-length/2,-height/2,-width/2) to (length/2,height/2,width/2) and returns the object. +AddSphere (Scene, radius [, polycount = 16 [, r = 180, g = 180, b = 180]]) +Adds a sphere at (0,0,0) and returns the object. If the radius parameter is less than 0, returns an invisible object. +GetTexture (Object) +Returns the texture files of a object: "filename1", "filename2", ... . +LoadTexture (Scene, Object, "filename1" [, "filename2", ...]) +Loads texture files to an object. +SetPosition (Object, x, y, z [, absolute = false]) +Sets the position of an object relative to its parent (or the absolute position to the scene). +GetPosition (Object [, absolute = false]) +Gets the position of an object relative to its parent (or the absolute position to the scene). +SetRotation (Object, rx, ry, rz [, absolute = false]) +Sets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene). +GetRotation (Object [, absolute = false]) +Gets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene). +SetScale (Object, sx, sy, sz) +Sets the scale of an object. +GetScale (Object) +Gets the scale of an object. +SetParent (Object, Parent) +Attaches an object to another object as a child. +GetParent (Object) +Gets the parent of an object. +SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]]) +Sets the ID, position, rotation and scale of an object. +DelObject (Object) +Deletes an object. +SetCamera (Scene, x, y, z [,Tx, Ty, Tz]) +Sets the position and target of the scene camera. +GetCamera (Scene) +Gets the camera object of a 3d scene and its position and targt. +GetSelections (Scene) +Returns selected objects from a 3d scene. +GetObjectID (Object1 [, Object2, ...]) +Returns "id"s of objects. +SetObjectID (Object, "id") +Sets the id of an object. +GetObject (Scene, "id") +Finds an object by its id.`}]},{path:"/en/docs/4.6_networks.html",title:"4.6 Networks",pathLocale:"/en/",contents:[{header:"4.6 Networks",slug:"_4-6-networks",content:'GIS vector data (3.2) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sample codes for this chapter can be found in the "network_samples" folder of the Project Tab in ScriptEditor.'},{header:"Network Manipulation",slug:"network-manipulation",content:`CreateNetwork () +Creates an empty network and returns the object. +CreateNetwork (UnTopoLines) +Creates a network from an untopologized "line" Shapes and returns three objects: Network, Nodes (Shapes) and Links (Shapes). +CreateNetwork (Nodes, Links) +Creates a Network object from topologized Nodes and Links Shapes. Returns the Network object. +InitNetwork (Network, Nodes, Links) +Initiates a Network from a Nodes and a Links Shapes. Returns true if succeed. +AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]]) +Adds a new link or update an existing link in the Network. Returns linkID, oID, dID, true/false for adding and true/false for updating. +AddLink (Network, Shapes|Table, index1 [, index2, ...]) +Adds or updates links from the recordset of a Shapes or Table. Returns boolean values. +DelLink (Network, linkID) +Deletes a link from a Network. Returns a boolean value. +GetNearNodeID (Network, x, y [, radius=nil]) +Gets the nearest Network nodes from a coordinate. Returns node ids. +GetNodeXY (Network, nodeID1 [, nodeID2, ...]) +Returns the coordinates of nodes in a Network: x1, y1, x2, y2, ... .`},{header:"Algorithms",slug:"algorithms",content:`GenSTPTree (Network, startID [, endID]) +Generates a Shortest Path Spanning Tree from a node. Returns a boolean value. +GetSTPPath (Network, endID, "NodeID"|"LinkID") +After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link id sequence: id1, id2 ,... . +GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp") +After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shapes index sequence. +GetSTPPath (Network, endID, "NodeShp"|"LinkShp") +After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shape object sequence. +GetSTPLen (Network, endID) +After calling GenSTPTree call this function. Returns a Shortest Path Distance to a end node. +GetSTPLen (Network, startID, endID) +Gets a Shortest Path from a start node to an end node in a Network. Returns the distance. +GetSTPLen (Network, x1, y1, x2, y2) +Gets a Shortest Path from a start coordinate to an end coordinate in a Network. Returns the distance. +SetTrip (Network, oID, dID, amount) +Sets an amount of a trip from an origin to an destination. +SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]]) +After calling SetTrip call this function. Performs the User Equilibium Traffic Assignment and returns a boolean value. +GetFlow (Network, linkID) +Returns the traffic flow of a specified link. +SetFlow (Network, linkID, flow) +Set the traffic flow of a specified link and return a boolean value.`}]},{path:"/en/docs/4.7_des_simulations.html",title:"4.7 Discrete Event Simulations",pathLocale:"/en/",contents:[{header:"4.7 Discrete Event Simulations",slug:"_4-7-discrete-event-simulations",content:'MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, which is very useful for dynamic system analysis. Sample codes for this chapter can be found in the "simulation_samples" folder of the Project Tab in ScriptEditor.'},{header:"Random Number Generation",slug:"random-number-generation",content:`CreateRandEng (seed, "uniform_01") +Creates a binary distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "uniform_real" [, min = 0, max = 1]) +Creates a uniform distributed real random generation engine from a seed and returns the object. +CreateRandEng (seed, "uniform_int" [, min = 0, max = 1]) +Creates an uniform integer random generation engine from a seed and returns the object. +CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2]) +Creates a triangle distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "bernoulli" [, p = 0]) +Creates a bernoulli distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1]) +Creates a cauchy distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "exponential" [, lambda = 1]) +Creates a exponential distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "geometric" [, p = 0]) +Creates a geometric distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "normal" [, mean = 0, sigma = 1]) +Creates a normal distributed random generation engine from a seed and returns the object. +CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1]) +Creates a lognormal distributed random generation engine from a seed and returns the object. +GetNextRandom (Engine) +Gets a random number from a random generation engine.`},{header:"Simulation Control",slug:"simulation-control",content:`CreateEvent (time, Funcion [, arg1, arg2, ...]) +Creates a future event from a Lua Function or a Lua Coroutine. Returns a Coroutine object. +ExecAllEvents () +Calls this at last. It will execute all events as Lua Coroutines. +Delay ([relativeTime = 0]) +Calls this function in a Lua Coroutine will let it first yield then resume it after the specified relative time. If the parameter relativeTime is not set, the current Coroutine will yield and won' be resumed automatically. +Resume ([time, ] Coroutine [, arg1, arg2, ...]) +Resumes a yielded coroutine immediately or at a specified time. +GetSimTime () +Returns the current simulation time.`}]},{path:"/en/docs/4.7_des_simulations_zh.html",title:"4.7 离散事件模拟",pathLocale:"/en/",contents:[{header:"4.7 离散事件模拟",slug:"_4-7-离散事件模拟",content:'MicroCity具有内部模拟时间计数和事件调度机制。它提供了几个嵌入式Lua函数,以便更容易地创建离散事件模拟,这对于动态系统分析非常有用。本章的示例代码可以在 ScriptEditor 中 Project 选项卡的"simulation_samples"文件夹中找到。'},{header:"随机数生成",slug:"随机数生成",content:`CreateRandEng(seed, "uniform_01") +从种子创建一个二进制分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "uniform_real" [, min = 0, max = 1]) +从种子创建一个均匀分布的实数随机生成引擎,并返回该对象。 +CreateRandEng(seed, "uniform_int" [, min = 0, max = 1]) +从种子创建一个均匀分布的整数随机生成引擎,并返回该对象。 +CreateRandEng(seed, "triangle" [, a = 0, b = 1, c = 2]) +从种子创建一个三角形分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "bernoulli" [, p = 0]) +从种子创建一个伯努利分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "cauchy" [, median = 0, sigma = 1]) +从种子创建一个柯西分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "exponential" [, lambda = 1]) +从种子创建一个指数分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "geometric" [, p = 0]) +从种子创建一个几何分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "normal" [, mean = 0, sigma = 1]) +从种子创建一个正态分布的随机生成引擎,并返回该对象。 +CreateRandEng(seed, "lognormal" [, mean = 0, sigma = 1]) +从种子创建一个对数正态分布的随机生成引擎,并返回该对象。 +GetNextRandom(Engine) +从随机生成引擎获取一个随机数。`},{header:"模拟控制",slug:"模拟控制",content:`CreateEvent(time, Function [, arg1, arg2, ...]) +从Lua函数或Lua协程创建一个未来事件。返回一个协程对象。 +ExecAllEvents() +最后调用此函数。它将执行所有事件作为Lua协程。 +Delay([relativeTime = 0]) +在Lua协程中调用此函数将使其首先暂停,然后在指定的相对时间后恢复。如果未设置relativeTime参数,则当前协程将暂停,并且不会自动恢复。 +Resume([time, ] Coroutine [, arg1, arg2, ...]) +立即或在指定时间恢复一个已暂停的协程。 +GetSimTime() +返回当前模拟时间。`}]},{path:"/en/docs/4.8_mixed_integer_programming.html",title:"4.8 Mixed Integer Programming",pathLocale:"/en/",contents:[{header:"4.8 Mixed Integer Programming",slug:"_4-8-mixed-integer-programming",content:'MicroCity employs the lpsolve to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build and solve models. Sample codes for this chapter can be found in the "optimization_samples" folder of the Project Tab in ScriptEditor.'},{header:"Model Creation and Execution",slug:"model-creation-and-execution",content:`CreateLP ([rows = 0 , columns = 0]) +Creates a Mixed Integer Linear Programming model and returns the LPModel object. +SetObjFunction (LPModel, rowTable, "MAX"|"MIN") +Sets the objective function of a LPModel with a Lua Table which stores coefficients of the decision variables. +AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue) +Adds a constraint to a LPModel with a Lua Table which stores coefficients of the decision variables. +SetInteger (LPModel, index) +Sets a decision variable specified by the index as an integer variable. +SetBinary (LPModel, index) +Sets a decision variable of a LPModel specified by the index as a binary variable. +SetUnbounded (LPModel, index) +Sets a decision variable of a LPModel to be unbounded(+/- infinity). +SolveLP (LPModel [, timeoutSec = 60]) +Solves a LPModel and returns 0 as success, -1 as invalid LP model, -2 as nomemory, 1 as suboptimal, 2 as infeasible, 3 as unbounded, 4 as degenerate, 5 as a numerical failure encountered, 6 as the user abort, 7 as a timeout error, 9 as the model could be solved by presolve, 10 as the B&B routine failed, 11 as the B&B was stopped because of a break-at-first, 12 as a feasible B&B solution was found, 13 as no feasible B&B solution found. +GetObjective (LPModel) +Returns the objective function value of a LPModel. +GetVariable (LPModel, index) +Returns the value of a decision variable specified by the index. +GetVariables (LPModel) +Returns all values of the decision variables of a LPModel. +GetDual (LPModel, index) +Returns the dual value of a decision variable specified by the index. +GetDuals (LPModel) +Returns all dual values of the decision variables of a LPModel. +ReadLP("fileName.mps") +Reads a LPModel from a file (*.lp, *.mps) and returns the LPModel if succeed. +WriteLP (LPModel, "fileName.mps") +Writes a LPModel to a file (*.lp, *.mps) and returns true if succeed.`}]},{path:"/en/docs/",title:"MicroCity Desktop Documents",pathLocale:"/en/",contents:[{header:"MicroCity Desktop Documents",slug:"microcity-desktop-documents",content:""},{header:"Contents",slug:"contents",content:`1 Introduction 1.1 What MicroCity can Do 2 Getting Started 2.1 Showing a World Map +2.2 Searching for Countries 3 User Interfaces 3.1 UI Overview +3.2 Vector Shapes +3.3 Raster Grids +3.4 3D Scenes +3.5 Tables +3.6 Maps and Layers +3.7 Modules 4 Scripting Interfaces 4.1 SI Overview +4.2 UI Control +4.3 Shapes and Tables +4.4 Grids +4.5 3D Scenes +4.6 Networks +4.7 Discrete Event Simulations +4.8 Mixed Integer Programming Statement: Part of the content of the documents on this website comes from MicroCity Desktop, and the copyright belongs to the original author.`}]},{path:"/en/notes/3d-objects.html",title:"3D Objects",pathLocale:"/en/",contents:[{header:"3D Objects",slug:"_3d-objects",content:"This section will introduce the objects and their control functions in a 3D scene."},{header:"Adding Objects",slug:"adding-objects",content:`To add objects to the scene, use the following function: +local obj = scene.addobj([type], {key1 = value1, key2 = value2, ...})`},{header:"Optional Object Properties",slug:"optional-object-properties",content:`Objects added to the scene typically support setting some of the following properties: Object Property +Meaning color +The color of the object. The format of the color can support built-in colors, hexadecimal, and RGB. Same as the background color of the scene opacity +Opacity hcolor +The color when the object is selected size +The size of the object. The default value is 1 length +The length of the object, commonly used for box width +The width of the object, commonly used for box height +The height of the object, commonly used for box radius +The size of the object's rounded corners segments +The number of segments, usually used to set the precision of the sphere drawn selectable +Whether the object can be selected name +The name of the object text +The text value of the object font +The font of the text vertices +The set of points that make up the corresponding object The following are the types of objects that can be added to the scene:`},{header:"Object Types",slug:"object-types",content:""},{header:"List of Object Types",slug:"list-of-object-types",content:`label: Text label +points: Set of points +polyline: Set of line segments +box: Cube +sphere: Sphere +polygon: Polygon +light: Light source +mesh: Face made up of points For the sake of brevity, the key properties of the optional objects shown in the example below only display the relevant attributes of the object. Other common properties can be added by referring to the Optional Object Properties.`},{header:"label",slug:"label",content:`label is a text label. The text of the label can be set in the text attribute. +local obj = scene.addobj('label', {text = "Hello World!"})`},{header:"points",slug:"points",content:`points is a collection of points. You can create a single point or multiple points. Each point has three-dimensional coordinates to determine its position in three-dimensional space. The number of points is determined by the vertices attribute. +Here is an example of creating a points object: +-- create a point at position (5,5,5) +scene.addobj("points", {vertices = {5,5,5}, size = 5}) -- create two points, the first at (0,0,0), the second at (5,5,5) +scene.addobj("points", {vertices = {0,0,0, 5,5,5}, size = 5})`},{header:"polyline",slug:"polyline",content:`polyline is a collection of line segments. When multiple points are input in the vertices attribute, line segments will be generated based on the order of the coordinates. +Therefore, although the same coordinates are used in the two examples below, the results are different because the order of the input coordinates is different. +scene.addobj("polyline", {vertices = {0,0,0, 4,6,7, -2,3,5}}) +scene.addobj("polyline", {vertices = {0,0,0, -2,3,5, 4,6,7}}) polyline point order comparison polyline does not have a size attribute.`},{header:"box",slug:"box",content:`box is a cuboid. Its shape can be modified mainly through the length, width, and height attributes. +local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) +Important optional properties of the box object: Property +Meaning length +The length of the cuboid width +The width of the cuboid height +The height of the cuboid Based on the above three attributes, we can modify the shape of the rotating box in the default sample code. +-- Add the length, width, and height attributes (default to 1 if not added) +local obj = scene.addobj('box', {length = 3, width = 4, height = 5}) local x = 1 +local y = 1 +local z = 0 +while scene.render() do x = x + 0.1 y = y + 0.1 obj:setrot(x, y, z) +end Boxes with different lengths, widths, and heights.`},{header:"sphere",slug:"sphere",content:`sphere is used to create a sphere object. Its size can be modified by the radius attribute, and its model quality can be set by setting the segments attribute. Refer to the example of the Earth in the built-in samples for more details. +local obj = scene.addobj('sphere', {radius=15, segments=360}) +Optional attributes for sphere objects: Attribute +Meaning radius +The radius of the sphere. It can be used to control the size of the sphere. segments +The number of rendered surfaces of the sphere. The higher the value, the more detailed the sphere model will be. The impact of different segments on the same sphere`},{header:"polygon",slug:"polygon",content:`polygon is used to create a polygon object, mainly set through the vertices attribute. +local obj = scene.addobj("polygon", {vertices = {-1,-1,0, -1,1,-0, 1,1,0, 1,-1,0}}) Because the polygon in this example is a square, it looks no different from the box introduced above. However, when the shape is set to other types of polygons (such as triangles, pentagons, etc.), the meaning of the polygon can be reflected. Attribute +Meaning +Explanation vertices +The vertices of the polygon +You can set the three-dimensional coordinates of each point in turn in the vertices attribute. The third dimension coordinates do not have an impact but play a placeholder role. size +Volume +Since the third dimension coordinates do not have an impact, and the area is already determined by the vertices of the polygon, the size attribute controls the volume by controlling the third dimension coordinate values of each point. The impact of different size on the same polygon volume`},{header:"External model",slug:"external-model",content:`Reference external files. However, for MicroCityWeb, only the built-in files on the website can be referenced at present. +For example, in the built-in example, a box-type truck is generated in the view by referencing the internal file: +local obj = scene.addobj('/res/2axle.glb') +You can also reference an external model by referencing the URL of the file: +local obj = scene.addobj('https://microcityweb.gitee.io/res/agv.glb') If you have 3D model resources at hand, you can view them in 3D Viewer and export them as .glb models through this website.`},{header:"Light",slug:"light",content:"Set the direction of the light, and the optional parameter vertices is a three-dimensional vector that represents the direction of the light. Since a strong light source has already been set in the MicroCityWeb scene, this will not be discussed in detail here."},{header:"Mesh",slug:"mesh",content:"A face composed of multiple points, commonly found in referenced external models. Due to its limited application, it will not be introduced here."},{header:"Object Control Functions",slug:"object-control-functions",content:"Assuming the 3D object to be manipulated is obj."},{header:"getpos()",slug:"getpos",content:`Gets the position coordinates (x, y, z) of obj. +local x, y, z = obj:getpos()`},{header:"setpos()",slug:"setpos",content:`Sets the position coordinates of obj to (x, y, z). +obj:setpos(x, y, z)`},{header:"getrot()",slug:"getrot",content:`Gets the rotation angles (rx, ry, rz) of obj in the x, y, and z directions. +local rx, ry, rz = obj:getrot()`},{header:"setrot()",slug:"setrot",content:`Sets the rotation angles of obj in the x, y, and z directions to (rx, ry, rz). +obj:setrot(rx, ry, rz)`},{header:"getscale()",slug:"getscale",content:`Gets the scaling ratios (sx, sy, sz) of obj in the x, y, and z directions. +local sx, sy, sz = obj:getscale()`},{header:"setscale()",slug:"setscale",content:`Sets the scaling ratios of obj in the x, y, and z directions to (sx, sy, sz). +obj:setscale(sx, sy, sz)`},{header:"getchildren()",slug:"getchildren",content:`Gets the table of child objects of obj. +local children = obj:getchildren()`},{header:"setchildren()",slug:"setchildren",content:`Sets the table of child objects of obj to children_table. +obj:setchildren(children_table)`},{header:"getparent()",slug:"getparent",content:`Gets the parent object of obj. +local num = obj:getparent()`},{header:"setparent()",slug:"setparent",content:`Sets the parent object of obj to obj0. +obj:setparent(obj0)`},{header:"delete()",slug:"delete",content:`Delete obj. +obj:delete()`}]},{path:"/en/notes/3d-scene.html",title:"3D Scene",pathLocale:"/en/",contents:[{header:"3D Scene",slug:"_3d-scene",content:"This section introduces 3D scenes and their settings."},{header:"MicroCityWeb 3D Scene Coordinate System",slug:"microcityweb-3d-scene-coordinate-system",content:"The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate system, and the specific direction of each coordinate axis is shown in the following figure. Coordinate system in MicroCityWeb Note that the three-dimensional coordinate axes x, y, and z here are manually drawn to show the coordinate system in MicroCityWeb and do not directly exist in the three-dimensional scene."},{header:"Setting up a Scene",slug:"setting-up-a-scene",content:`Setting up a scene requires the use of the setenv function, with the specific usage as follows: +local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true}) +It can be simplified as follows: +local s = scene.setenv({key1 = value1, key2 = value2, ...}) +The variable s holds the returned environment object. The optional parameters of the function will be described in detail below.`},{header:"Optional Parameters of a Scene",slug:"optional-parameters-of-a-scene",content:""},{header:"Parameter List",slug:"parameter-list",content:`grid: background grid of the scene +bgcolor: background color of the scene +camtype: camera view +clear: whether to clear the scene +rotspeed & transpeed*: adjustment of mouse operation speed`},{header:"grid: Background grid of the scene",slug:"grid-background-grid-of-the-scene",content:`Optional values Value +Meaning "none" +default, no grid "plane" +flat grid "sphere" +spherical grid`},{header:"bgcolor: Background color of the scene",slug:"bgcolor-background-color-of-the-scene",content:`Optional value types: Value Type +Example Built-in colors +"black", "white", "gray", etc. Hexadecimal colors +"#ffffff", "#fff", "#000000", "#000", etc. Colors represented by RGB +"rgb(255, 255, 255)", "rgb(0, 0, 0)", etc. Example: +scene.setenv({bgcolor='gray'}) -- Sets the background color to the built-in color "gray" +scene.setenv({bgcolor='#eee'}) -- Sets the background color to the hexadecimal color "#eee" +scene.setenv({bgcolor='rgb(255, 255, 255)'}) -- Sets the background color to white`},{header:"camtype: Camera angle of view",slug:"camtype-camera-angle-of-view",content:`Optional values: Value +Meaning "ortho" +Orthographic. Equivalent to a projection onto the x and y plane. User's view is in two-dimensional space. "persp" +Perspective (default). User's view is in three-dimensional space.`},{header:"clear: Whether to clear the scene",slug:"clear-whether-to-clear-the-scene",content:"When the value is set to true, the scene is cleared. The setenv function does not clear the original scene by default, unless the value of the clear parameter is manually set to true."},{header:"rotspeed & transpeed",slug:"rotspeed-transpeed",content:`Value +Meaning rotspeed +Sets the speed of rotating a 3D object with the mouse. transpeed +Sets the speed of translating a 3D object with the mouse. These two parameters usually do not need to be set specially, and the default values can be used.`},{header:"Others",slug:"others",content:""},{header:"Regarding high-frequency setting scenarios",slug:"regarding-high-frequency-setting-scenarios",content:`2023/03/21: It has been found that setting the scene too frequently can cause excessive memory usage and browser crashes. Therefore, it is recommended to avoid calling the scene.setenv() function in a loop as much as possible. +If it is necessary to do so, make sure that the frequency of calls is relatively low. This allows the browser to have enough time for garbage collection, otherwise it may cause the browser to crash.`}]},{path:"/en/notes/",title:"Notes",pathLocale:"/en/",contents:[{header:"Notes",slug:"notes",content:""},{header:"General Knowledge",slug:"general-knowledge",content:`Quick Start with Lua Language +Versions of MicroCity +Time Advancement Methods +Object-oriented Programming +Regarding Tools`},{header:"MicroCity (Desktop Version)",slug:"microcity-desktop-version",content:`Visualization of Results +Operating Networks +Model Solving`},{header:"MicroCityWeb",slug:"microcityweb",content:`Introduction to User Interface +3D Scene +3D Objects +Discrete Event Simulation and Program Control +Mixed Integer Programming +Debugging`},{header:"Ideas",slug:"ideas",content:`Warehouse Simulation +General Drawing Code +Simulation Ideas for Port AGV Service Process The notes referenced in this page directory apply to the corresponding versions of MicroCity. Special thanks to Sun Zhuo (MicroCity author) for the guidance and assistance during the writing and organizing process. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/cy-simulation.html",title:"Port AGV Service Process 3D Simulation Approach",pathLocale:"/en/",contents:[{header:"Port AGV Service Process 3D Simulation Approach",slug:"port-agv-service-process-3d-simulation-approach",content:"This train of thought is for reference only. Simulating the process of a container terminal is a complex task that involves many factors and entities. This article mainly introduces the approach to simulate the process of AGV receiving services from the yard crane to accepting services from the quay crane using MicroCityWeb."},{header:"Implementing Yard Crane Handling of Containers",slug:"implementing-yard-crane-handling-of-containers",content:""},{header:"Overall Approach",slug:"overall-approach",content:"Implementing the handling of containers by the yard crane is the first step in simulating the yard. I plan to use an object-oriented approach for this part, abstracting the yard crane and the yard as objects."},{header:"Overall Structure",slug:"overall-structure",content:`The specific idea is to treat the yard as a data model that stores various data, such as container entities, coordinates of containers in corresponding positions (rows, columns, heights), etc. The yard crane is treated as an operator responsible for the yard crane's 3D animation and management of data in the yard object. +The benefit of doing this is to decouple the yard crane from the yard, making it easier to expand in the future. In addition, if the object's properties are well considered, multiple objects can be easily created in the same scene to simulate multiple yard cranes operating in the yard.`},{header:"Events and Tasks",slug:"events-and-tasks",content:"I plan to create task sequences for the main entity objects that require movement in the overall process. This allows for parallel operations of multiple yard cranes in the same scene, with each yard crane performing its own tasks without interfering with each other. In addition, a central control program is needed to control the execution of tasks at each time node and the 3D animation of the yard crane."},{header:"Business Process",slug:"business-process",content:"In this simulation, the main focus of the business process is the movement of containers. Therefore, the most important aspect is the transfer of ownership of containers. The process flow of container ownership transfer is shown in the following diagram: Container Object Process Flow"},{header:"Object Structure",slug:"object-structure",content:"The following are the structures of the main objects involved in this simulation."},{header:"Implementation Approach",slug:"implementation-approach",content:""},{header:"Yard Size",slug:"yard-size",content:`For the yard object, since its main function is to store container objects and related data (such as coordinates of corresponding positions), we need to determine the size of the yard. Therefore, determining the size of the yard is a necessary step. When creating the yard object, we need to determine the size of the yard, including the number of rows, columns, and height. This facilitates subsequent operations. +My approach is to first determine the area occupied by the yard and the number of container layers. Based on the relevant data, we can calculate the maximum number of rows and columns that can be used to place containers. Regarding the area occupied by the yard, it can be determined by inputting the coordinates of two points when creating the object. Based on the diagonal formed by connecting the two points, we can determine the area occupied by the yard. +As for the number of container layers, it can be determined by inputting a number when creating the object. Based on these two inputs, we can determine the size of the yard.`},{header:"Events and Tasks",slug:"events-and-tasks-1",content:`Since the yard crane is the main object that needs to be moved in this simulation, we only need to operate the yard crane during each loop of task execution. +Therefore, I plan to treat the task sequence of the yard crane as a queue. During each loop of task execution, we take out the first task from the object's task sequence and execute it. After execution, we check if the task completion condition is met. If so, we delete the task and move on to the next one. This ensures that the yard crane objects execute tasks in order during each loop of task execution. +The method for executing tasks is executeTask(dt), where the object executes tasks based on the duration dt. The executeTask(dt) function contains the logic for processing tasks, including task type determination, task execution, and task deletion. +If there are multiple yard cranes in the scene, simply add these objects to the list of objects executing tasks. During each loop of task execution, the main control program will iterate through this list of objects and execute tasks for each object. Tips +Note that although the task execution appears to be simultaneous in terms of time, it actually depends on the sequence position of the objects. +One example is: suppose two objects need to occupy position A at the same time. According to the order of the task sequence, the object that is executed first will occupy position A, while the object that is executed later will fail to occupy it, even though they are both trying to occupy position A at the same moment. Therefore, it is not strictly simultaneous execution here, but sequential execution according to the task sequence at the same time.`},{header:"Business Process",slug:"business-process-1",content:`The yard crane first obtains the coordinates of the corresponding position (row, column, height) of the container from the yard and moves the spreader to the designated position in the yard to grab the container. The ownership of the container is transferred from the yard (cy.containers) to the yard crane spreader (rmg.attached) (by removing the table reference, setting the value to nil). +The yard crane moves the container to the aisle and releases it there. In the same way, the ownership of the container is transferred from the yard crane spreader (rmg.attached) to the aisle (rmg.stash), indicating that the container can be picked up. +If there is a vehicle that takes away the container, the ownership of the container can be further transferred from the aisle of the yard crane (rmg.stash) to the vehicle.`},{header:"Results",slug:"results",content:""},{header:"Implementation of the Whole Process from AGV Arrival to Service",slug:"implementation-of-the-whole-process-from-agv-arrival-to-service",content:""},{header:"Problem Description",slug:"problem-description",content:"Implement the three-dimensional representation of the process above using event scheduling method."},{header:"What's New",slug:"what-s-new",content:`The implementation of the previous simulation serves as the foundation for this simulation. Compared to the previous simulation, the most significant improvement in this simulation is: Using the object-oriented programming paradigm to create objects of four types: yard crane, yard (data model), AGV, quay crane, and ship (data model), and implement the movement methods for the objects and their components. If you are not familiar with object-oriented programming, you can refer to General Knowledge - Object-Oriented Programming. Continuing with the idea of event-driven simulation, the overall control process is implemented to control multiple objects simultaneously at the same time (primarily achieved through the object's executeTask(dt) and maxStep() functions). In the object-oriented programming paradigm, executeTask(dt) and maxStep() can be seen as interfaces. The main program controls the objects by implementing these two interfaces. (Although Lua seems to lack this concept.) +Using task sequences to implement the flow of each object, achieving mutual waiting between the yard crane and AGV, and between the AGV and quay crane, and coordinating tasks between different objects. +Attempting to extend the flow from the yard to the AGV, and then to the quay crane and ship, implementing two-level queuing and waiting.`},{header:"Object Design",slug:"object-design",content:`Due to the large number of attributes and functions, the design of objects is presented in the form of a mind map. Tips +This section takes up a lot of space. You can also directly jump to the next section Overall Layout.`},{header:"Yard",slug:"yard",content:"The yard remains as the data model."},{header:"Yard Crane",slug:"yard-crane",content:""},{header:"AGV",slug:"agv",content:""},{header:"Quay Crane",slug:"quay-crane",content:"The code and structures involving the quay crane are derived mainly from the yard, so they will not be described in detail later."},{header:"Ship",slug:"ship",content:"The ship object also serves as a data model, designed similarly to the yard."},{header:"Overall Layout",slug:"overall-layout",content:""},{header:"Overall Process",slug:"overall-process",content:"Container Flow Process Compared to the previous simulation, this simulation goes further in terms of the process. It adds the flow of AGV arrival and queuing, as well as the service of the quay crane and container loading onto the ship."},{header:"Process Analysis",slug:"process-analysis",content:`With the introduction of AGVs, the flow between the yard crane, quay crane, and AGV has becomes more complex. First, the arrival of AGVs is random, which may cause queuing. Second, the arrival of AGVs triggers the flows of the yard crane and AGV, which in turn trigger the flow of the quay crane. Therefore, the flow of this simulation is a multi-level flow that needs to consider the coordination between multiple objects. +Especially in the process between AGV and RMG, there is a mutual waiting between AGV and RMG. When the AGV arrives, it needs to notify the RMG to extract the cargo. In the process of extraction by the RMG: The RMG needs to wait for the AGV to arrive at the designated position before it can move the cargo onto the AGV. +The AGV needs to wait for the RMG to grab the container and place it on the AGV before transferring the ownership of the container from the RMG to the AGV. Therefore, the process between the AGV and the RMG is a mutually waiting process. The specific process can be referred to in the diagram below. The process of the quay crane is similar to that of the RMG, which is also a mutually waiting process. The main points are: When the AGV arrives at the designated position, the quay crane may be serving other AGVs, so the AGV has to wait. +When the AGV just enters the service area of the quay crane, it notifies the quay crane to reach the designated position. If the quay crane arrives at the designated position first, it has to wait.`},{header:"Implementation Method",slug:"implementation-method",content:""},{header:"Implementation of Queuing Process",slug:"implementation-of-queuing-process",content:`For AGV queuing, I chose to use cellular automaton as the data model of parking spaces. The length of each parking space is: +Length of Parking Space=Length of 1 Container in the data model+Gap between containers +\\text{Length of Parking Space} = \\text{Length of 1 Container in the data model} + \\text{Gap between containers} +Length of Parking Space=Length of 1 Container in the data model+Gap between containers +Since the length of the AGV is slightly longer than that of 1 container, it needs to occupy the length of 2 parking spaces. When executing a task, the AGV checks if the space ahead is blocked, and if not, it moves forward. If the space ahead is the target bay, it moves forward and waits for the RMG operation, then continues to move forward in terms of cells until it leaves. The queuing principles for the RMG and quay crane are also the same. Diagram of AGV Cellular Automaton Queuing Model`},{header:"Implementation of Event Scheduling Method",slug:"implementation-of-event-scheduling-method",content:`In the previous simulation, I used a variable step size to advance the time for simulation. In this simulation, I used the event scheduling method to accurately advance the events to their occurrence time for execution. +You may have noticed that in the Object Design section, executeTask() and maxstep() are marked as (interface). This is because to calculate the accurate advancement time, I need to implement executeTask() and maxstep() methods in each object. The executeTask() method is used to execute the task, and the maxstep() method is used to calculate the time remaining for the current task to be completed and obtain the maximum advancement time based on that, and then compare it with the interval time dt obtained from the system execution to get the maximum advancement time. +I believe that the following diagram from the course can effectively represent how the event scheduling method is used for simulation and scene refreshing. The first row refers to the business process of simulation, and the Refresh part in the second row refers to refreshing the scene.`},{header:"Results",slug:"results-1",content:`Note +The following parts contain animated GIFs, and the images have a large file size. Since this site is hosted on GitHub Pages, if you don't have a special network environment, the animated GIFs may load slowly or even fail to load. Tips +If you encounter moiré patterns in the animated GIFs while directly viewing them, you can try opening them to enlarge the view and see if there is any improvement. RMG running process Quay crane running process Overall running process This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/debug.html",title:"Debugging",pathLocale:"/en/",contents:[{header:"Debugging",slug:"debugging",content:"This page introduces the functions and shortcuts related to debugging in MicroCity Web."},{header:"Clearing Output",slug:"clearing-output",content:"Right-clicking on the output area allows you to enter commands. Entering print() clears the content of the output area."},{header:"Debugger Shortcuts",slug:"debugger-shortcuts",content:`During the process of debugging a program, especially at breakpoints, you can use F9 (Step Over), F10 (Step Into), and F11 (Step Out) to control the program execution. F9 Step Over: Skips the current line and executes the next line. +F10 Step Into: Enters the current line. If the current line is a function call, it enters the function body. +F11 Step Out: Exits the current function and executes the next line after the function call.`},{header:"Debug Commands",slug:"debug-commands",content:""},{header:"Watching Variables",slug:"watching-variables",content:`Use the debug.watch() command in the console to monitor variables. +For example, if you want to monitor the value of variable a during debugging, you can use the debug.watch('a') command. Right-clicking on the output area allows you to enter commands.`},{header:"Stack Trace",slug:"stack-trace",content:`The debug.traceback() function can print the current stack trace information. +function myFunction() -- Some code logic print(debug.traceback("Stack trace")) -- Other code logic +end function anotherFunction() myFunction() +end anotherFunction() +Output: +Stack trace +stack traceback: +[string "function myFunction() ..."]:3: in function 'myFunction' +[string "function myFunction() ..."]:8: in function 'anotherFunction' +[string "function myFunction() ..."]:11: in main chunk`},{header:"Running Status",slug:"running-status",content:`debug.debug() enters Debug mode. It is often used to enter Debug mode during program execution. If you want to start in Debug mode, you can right-click the top ▶️ button. See User Interface Introduction - Running Status for details. +debug.pause() pauses program execution. The Run button ▶️ at the top will light up, and the Pause button ⏸️ will turn off.`},{header:"Other Debug Commands",slug:"other-debug-commands",content:`Most of Lua's Debug functions are applicable to MicroCity Web. For reference, please see: The Debug Library | Lua 5.4 Reference Manual +Lua Debugging | Runoob Tutorial This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/event-scheduling.html",title:"Discrete Event Simulation and Program Control",pathLocale:"/en/",contents:[{header:"Discrete Event Simulation and Program Control",slug:"discrete-event-simulation-and-program-control",content:""},{header:"Coroutines",slug:"coroutines",content:"MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling."},{header:"coroutine.queue",slug:"coroutine-queue",content:`Adds a function or coroutine to the coroutine queue for execution after a specified relative time. +coroutine.queue(rt, f|co [, argument list...]) +Parameters Parameter +Description rt +Relative time from the current queue. It should be greater than or equal to 0. In other words, it specifies the time after which the input function or coroutine will be executed. f/co +Function or coroutine. If it's a function, you only need to input the function name.`},{header:"coroutine.qtime",slug:"coroutine-qtime",content:`Retrieves the current time of the queue. +local time = coroutine.qtime()`},{header:"Example",slug:"example",content:`Here are two examples provided: Adding Coroutines to the Queue: Demonstrates how to add coroutines to the queue and display the current queue time within the function. +Vehicle Movement: Shows how to use coroutines to refresh the scene based on real-world time.`},{header:"Adding Coroutines to the Queue",slug:"adding-coroutines-to-the-queue",content:`This example demonstrates how to add coroutines to the queue and display the current queue time within the function. +function Show() print("Current time:", coroutine.qtime()) +end function ShowShort() print("Current time (short):", coroutine.qtime()) +end coroutine.queue(10, Show) +coroutine.queue(20, Show) +coroutine.queue(15, ShowShort) +coroutine.queue(5, Show) -- Result: +-- Current time: 5.0 +-- Current time: 10.0 +-- Current time (short): 15.0 +-- Current time: 20.0`},{header:"Vehicle Movement",slug:"vehicle-movement",content:`This example demonstrates how to use coroutines to refresh the scene based on real-world time. +scene.setenv({grid='plane'}) -- Set the scene background grid -- Vehicle +local car = scene.addobj('/res/2axle.glb') +car.speed = 1 -- Car speed -- Initial time +local t = os.clock() +local dt = 0 -- Refresh time state t and dt (based on CPU intervals to synchronize with real-world time) +function refreshtime() dt = os.clock() - t t = os.clock() +end -- Coroutine updates the scene +function update() if not scene.render() then return end -- Render the scene and check if the program is terminated coroutine.queue(dt, update) -- Add the next update based on CPU step time carmove() -- Move the vehicle refreshtime() -- Calculate the current dt +end -- Vehicle movement +function carmove() print("Car moves at", t) local x, y, z = car:getpos() car:setpos(x, y, z + dt * car.speed) +end -- Initial update (add the first update) +-- Since subsequent updates are added within the function, the updates will loop automatically +coroutine.queue(dt, update)`},{header:"Random Numbers",slug:"random-numbers",content:""},{header:"Creating a Random Seed",slug:"creating-a-random-seed",content:`local seed = math.randomseed(x [, dist]) +Parameters Parameter +Description x +Random seed. Different input values will produce different random numbers. To get different values each time, consider setting the random seed x to the current time. dist +Random distribution (optional). If not set, the default is a uniform distribution. If this parameter is set, you can also specify mu and sigma as parameters for the corresponding distribution. The dist parameter can be set to one of three distributions: 'normal': Normal distribution +'exponential': Exponential distribution +'poisson': Poisson distribution In addition, you can set parameters for these distributions, where the mu key represents the mean and the sigma key represents the standard deviation.`},{header:"Example",slug:"example-1",content:`-- Create a random seed with a Poisson distribution +local seed = math.randomseed(os.time(), {distribution = "poisson", mu = "3"}) -- Poisson distribution with a mean of 3 -- Output a random number +print(seed:random())`},{header:"Program Control",slug:"program-control",content:`Program control, in this context, mainly refers to controlling the execution of a program using the buttons in the user interface, including pause, resume, and stop. Command Bar This mainly refers to the first three buttons in the command bar. In MicroCityWeb, program control refers to the pause, resume, and stop of the 3D interface rendering implemented through the scene object. The specific function is as follows: +local state = scene.render() +Here, the return value of scene.render() is stored in the state variable. The state variable can be either true or false, representing the running or terminated state of the program (button 3 in the command bar). +Pausing the rendering of 3D objects is also achieved by calling scene.render(). If the refresh of 3D objects is implemented by continuously calling the scene.render() function and the refresh interval is not controlled by os.sleep(), it is possible to pause the rendering of the 3D interface at a certain state. This is because if os.sleep() is used to control the speed of 3D object movement and the pause button is clicked while the program is in the os.sleep() process, the program may not respond immediately, resulting in the pause button becoming ineffective. Therefore, it is recommended not to use os.sleep() for controlling the speed of 3D object movement, but to use other parameters to control the duration of advancement in order to control the speed of 3D object movement.`}]},{path:"/en/notes/lp.html",title:"Model Solving",pathLocale:"/en/",contents:[{header:"Model Solving",slug:"model-solving",content:`In MicroCity, mathematical models can be solved. In this article, we will introduce the common process of solving mathematical models in MicroCity and provide some tips to help you better build models. +The detailed usage of all functions in the planning model can be found in the document 4.8 Mixed Integer Linear Programming. Tips +The content on this page is based on MicroCity Desktop version. If you are looking for a solution for mixed integer programming in MicroCity Web version, please refer to the corresponding Mixed Integer Programming section in the MicroCity Web notes.`},{header:"Creating Model Objects",slug:"creating-model-objects",content:`Create a planning model object and store it in the variable lp. +local lp = CreateLP() The mathematical model object created in the official documentation is stored in the variable LPModel, which has the same function as lp in this article.`},{header:"Writing Mathematical Models",slug:"writing-mathematical-models",content:`At this point, the object of the mathematical model has been created and stored in the variable lp, and further operations can be performed on it. A mathematical model generally consists of two parts: Objective Function +Constraint Equations Next, let's introduce how to create the objective function.`},{header:"Creating the Objective Function",slug:"creating-the-objective-function",content:`In MicroCity, SetObjectFunction() is used to set the objective function of the model object. It allows you to choose whether to optimize for maximum or minimum. The specific usage is as follows: Maximum +Minimum SetObjFunction(lp, coeff, "max") -- Optimize for maximum SetObjFunction(lp, coeff, "min") -- Optimize for minimum "min" and "max" are case-insensitive, so "MIN" and "MAX" can also be used.`},{header:"Parameter Description and Example",slug:"parameter-description-and-example",content:`Parameter +Description lp +Mathematical model object. Input the mathematical model into the function to set the objective function. coeff +Objective function coefficients, which is a table type variable. Used to determine the coefficients of the objective function in the model. "min" or "max" +Determine whether to optimize for the maximum or the minimum of the objective function. coeff is a coefficient list for the objective function, which is a table type variable. Suppose you want to minimize the function 4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​, the procedure to add the objective function is as follows: +-- Suppose you have already created the model object and stored it in the variable lp -- 4*x1 + 12*x2 + 18*x3 +local coeff = {4, 12, 18} -- Set the objective function: minimize +SetObjFunction(lp, coeff, "min")`},{header:"Adding Constraint Equations",slug:"adding-constraint-equations",content:`In MicroCity, the function for adding model constraints is AddConstraint(), used as follows: ≤ +≥ += -- Use symbols to express +AddConstraint(lp, cons, "<=", b) -- Alternatively, you can use abbreviations +AddConstraint(lp, cons, "le", b) -- Use symbols to express +AddConstraint(lp, cons, ">=", b) -- Alternatively, you can use abbreviations +AddConstraint(lp, cons, "ge", b) -- Use symbols to express +AddConstraint(lp, cons, "==", b) -- Or you can use abbreviations to express it AddConstraint(lp, cons, "eq", b)`},{header:"Parameter Description",slug:"parameter-description",content:`Parameter +Description lp +Mathematical model object. Input the mathematical model into the function to add constraints to it. cons +Constraint equation coefficients. Similar to cons in setting the objective function, it is also a table type variable used to determine the coefficients of each variable in the constraint equation. "<=" or ">=" or "==", or their corresponding alphabetic expressions +Determines the relationship between the constraint equation and the right-hand side. b +A number representing the right-hand side of the constraint equation. It can be a variable or a constant.`},{header:"Example",slug:"example",content:`The objective function 4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​ has been set above. Suppose you want to add two constraint equations for this function: +{x1+3x3≥32x2+2x3≥5 +\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ +Add corresponding constraint equations: +-- Add constraint: x1+3*x3≥3 +cons = { 1, 0, 3 } +AddConstraint(lp, cons, ">=", 3) -- Add constraint: 2*x2+2*x3≥5 +cons = { 0, 2, 2 } +AddConstraint(lp, cons, ">=", 5) +It is not difficult to notice that the number of coefficients is consistent with the number of variables in the objective function. Therefore, before programming the solution, you need to first determine the total number of variables and arrange the positions of each variable.`},{header:"Set Variable Types",slug:"set-variable-types",content:`MicroCity's mathematical programming supports integer programming. If no SetUnbounded() is set for the variables, the default value range for the variables is non-negative real numbers (≥0). The following describes in detail how to set variable types. +You can set the integer variable or 0-1 variable for the i-th variable in the model. If the variable is not set to these types, the default variable is non-negative real number. Integer Variables +0-1 Variables SetInteger(lp, i) -- Integer variable SetBinary(lp, i) --0-1 variable To allow the value of the i-th variable to be negative (by default, it cannot be negative): +SetUnbounded(lp, i)`},{header:"Model Solving and Output",slug:"model-solving-and-output",content:""},{header:"Model Solving",slug:"model-solving-1",content:`Since both the objective function and the constraint equations have been added, solving the model is simple, just one step: +SolveLP(lp) +After executing this statement, the mathematical model stored in the variable lp is solved.`},{header:"Output",slug:"output",content:`After solving the problem, it still needs to be output to understand the result of the solution. The following are commonly used functions for outputting the solution result. +Obtain the objective function value: +GetObjective(lp) +Obtain the value of the i-th variable: +GetVariable(lp, i)`},{header:"SolveLP",slug:"solvelp",content:`The SolveLP() function also has output after the solution is obtained, the meaning of the output code is as follows: Output Code +Meaning 0 +Success -1 +Invalid LP Model -2 +Out of Memory 1 +Suboptimal 2 +Infeasible 3 +Unbounded 4 +Degenerate 5 +Numerical Error 6 +User Termination 7 +Timeout Error For the meaning of other return values, please refer to the documentation 4.8 Mixed Integer Linear Programming for the SolveLP() function.`},{header:"Model Solution Example",slug:"model-solution-example",content:`Here is a simple example of modeling and solving for reference. (Actually it just strings together the previous content) +Example: +minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N +minf=4x_1+12x_2+18x_3\\\\ +s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N +\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N represents the set of natural numbers (non-negative integers) Script: +-- Create linear programming object +local lp = CreateLP() local n = 3 -- Set the number of objective functions -- Objective function: 4*x1 + 12*x2 + 18*x3 +-- Set the coefficients of the objective function, and the objective function is minimized +local coeff = { 4, 12, 18 } +SetObjFunction(lp, coeff, "min") -- Add constraint 1: x1 + 3*x3 ≥ 3 +cons = { 1, 0, 3 } +AddConstraint(lp, cons, ">=", 3) -- Add constraint 2: 2*x2 + 2*x3 ≥ 5 +cons = { 0, 2, 2 } +AddConstraint(lp, cons, ">=", 5) -- Since SetUnbounded() is not set, +-- by default, all variables are non-negative, +-- so there is no need to add constraints for non-negative variables. -- Set all variables to integers +for i = 1, n do SetInteger(lp, i) +end -- Solve the model +SolveLP(lp) -- Output the objective function value +print("Objective function value:", GetObjective(lp)) -- Output the values of each variable +for i = 1, n do print("x", i, "=", GetVariable(lp, i)) +end +Output: +Objective function value: 42 +x1=0 +x2=2 +x3=1`},{header:"Some Techniques for Modeling",slug:"some-techniques-for-modeling",content:""},{header:"Linearization",slug:"linearization",content:`Sometimes we encounter modeling problems with multiple subscripts, such as the decision variable xijx_{ij}xij​, which needs to be linearized. +Let's assume that the shape of the decision variable itself is 3 rows and 4 columns, that is: Column 1 +Column 2 +Column 3 +Column 4 x11x_{11}x11​ +x12x_{12}x12​ +x13x_{13}x13​ +x14x_{14}x14​ x21x_{21}x21​ +x22x_{22}x22​ +x23x_{23}x23​ +x24x_{24}x24​ x31x_{31}x31​ +x32x_{32}x32​ +x33x_{33}x33​ +x34x_{34}x34​ Assuming that the objective function is to sum up these decision variables, which is F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​, if we want to input it into the objective function, we can linearize it as x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​. +Since there are only two dimensions, we can use two for loops to achieve this: +local cons = {} +for i = 1, 3 do -- the first dimension for j = 1, 4 do -- the second dimension cons[4 * (i - 1) + j] = 1 -- fill in the coefficients -- the idea of 4 * (i - 1) + j is similar to carrying end +end -- result: +-- cons has a length of 12, and all values are 1`},{header:"Example: Assignment Model",slug:"example-assignment-model",content:`Let's take a look at the specific usage and convenience of multidimensional linearization using an actual example. +Four people, A, B, C, and D, are assigned to deliver four types of goods, A, B, C, and D, with the corresponding delivery times shown in the table. If each person delivers only one type of goods, who should be assigned to deliver which type of goods to minimize the total time? Person\\Goods +A +B +C +D A +14 +9 +4 +15 B +11 +7 +9 +10 C +13 +2 +10 +5 D +17 +9 +15 +13 Let's assume that the numbers corresponding to goods A, B, C, D are 1, 2, 3, 4 respectively, and xij=1x_{ij}=1xij​=1 represents person i delivering goods j, and xij=0x_{ij}=0xij​=0 represents person i not delivering goods j. +The mathematical model of the above problem can be represented as +minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 +minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ +s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 +\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ +Solution code: +-- efficiency matrix +local cost = { { 14, 9, 4, 15 }, { 11, 7, 9, 10 }, { 13, 2, 10, 5 }, { 17, 9, 15, 13 } +} local lp = CreateLP() -- create the objective function +local coeff = {} +for i = 1, 4 do for j = 1, 4 do -- it is easy to convert a two-dimensional array to a one-dimensional array here coeff[4 * (i - 1) + j] = cost[i][j] end +end SetObjFunction(lp, coeff, "min") -- add constraints +for k = 1, 4 do -- control the value of the i dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- sum up j, check i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) +end +for k = 1, 4 do -- Control the value of the jth dimension +local cons = {} +for i = 1, 4 do +for j = 1, 4 do +if j == k then -- Sum i and check j +cons[4 * (i - 1) + j] = 1 +else +cons[4 * (i - 1) + j] = 0 +end +end +end +AddConstraint(lp, cons, "==", 1) +end +-- Solve the model +SolveLP(lp) +-- Output the objective function value +print("Objective function value:", GetObjective(lp)) +-- Output the decision variables +for i = 1, 4 do -- First dimension +for j = 1, 4 do -- Second dimension +local x = GetVariable(lp, 4 * (i - 1) + j) +if x ~= 0 then +print("x[", i, "][", j, "]=", x) +end +end +end Output +Objective function value: 29 +x[1][3]=1 +x[2][1]=1 +x[3][4]=1 +x[4][2]=1 +| Result | Person | Item | +| ---------- | :---: | :------: | +| $x_{13}=1$ | A | C | +| $x_{21}=1$ | B | A | +| $x_{34}=1$ | C | D | +| $x_{42}=1$ | D | B | ### Handling Intermediate Variables +Sometimes there may be intermediate variables in the model that need to have corresponding positions in the matrix in order to be solved, but these intermediate variables do not participate in the calculation of the objective function value. **You can set the coefficients of these intermediate variables to 0 at their corresponding positions.** Let $x_1, x_2, x_3, x_4$ be the decision variables and $y_1, y_2$ be the intermediate variables. The objective function is: +$$ +z = \\sum_{i=1}^4 x_i +$$ +Then the coefficients of the objective function can be set as: +\`\`\`lua +local fcons = {1, 1, 1, 1, 0, 0} +After that, you can proceed with the general process 😎 This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/lua.html",title:"Quick Start with Lua Language",pathLocale:"/en/",contents:[{header:"Quick Start with Lua Language",slug:"quick-start-with-lua-language",content:"Since MicroCity uses the Lua scripting language, it is necessary to familiarize yourself with the basic usage of Lua before starting to write scripts with MicroCity. This article introduces the commonly used syntax for writing Lua scripts in MicroCity, which can help you quickly understand the overall approach to writing MicroCity scripts based on concepts from other programming languages."},{header:"Variable and Function Definition",slug:"variable-and-function-definition",content:`Lua automatically recognizes variable types, so there is no need to define variable types before variable names. You can assign values directly. +a = 1.5 +b = "string" +c = {} -- c is a table, explained below +Function definition +function add(a, b) return a + b +end +Above is a simple definition of the add() function, which aims to add the two input variables and return the result. +Variables can be global or local, and functions are the same. Here is how to define local variables and functions. +-- Define a local function +local function show(msg) print(msg) +end -- Define a local variable +local a = 1 +If there is a conflict between locally defined content (function or variable) and globally defined content, the locally defined content takes precedence. When such a conflict exists, the content you are operating on is the local content. +If there is no explicit need to manipulate global variables, it is recommended to define variables as local variables as much as possible. This practice may reduce the occurrence of bugs and is a safer approach.`},{header:"Condition",slug:"condition",content:`It's all about if, and there are several specific forms of implementation: Normal form if condition then print("condition==true") +end Form with else if condition then print("condition==true") +else print("condition==false") +end Form with elseif if number > 0 then print("number>0") +elseif number < 0 then print("number<0") +else print("number==0") +end +In Lua, the equality operator is ==, and the inequality operator is ~=. You can apply these operators to conditional expressions. Here is a simple example: +print(1==1) -- true +print(1~=1) -- false`},{header:"Loop",slug:"loop",content:"Here are two most commonly used loops: for and while."},{header:"for",slug:"for",content:`The simplest form +-- Output numbers from 1 to 10, a total of 10 numbers +for i = 1,10 do print(i) +end +If you are familiar with C or C-like languages, the corresponding form of the above code is as follows: +for(int i=1; i<=10; i++){ printf("%d\\n",i); +} +Taking step size into consideration +-- Output numbers from 10 to 1, a total of 10 numbers with a step size of -1 +for i = 10,1,-1 do print(i) +end When the step size is negative, it is important to note that the starting and ending numbers should be in reverse order. Generic loop +You can directly traverse all elements in a table. +i is the index of the table element, starting from 1; v is the value of the table element. +a = {4,7,9} +for i,v in ipairs(a) do print("index=",i,"\\tvalue=",v) +end ipairs is used for arrays (guessing i stands for integer), and pairs is used for objects. Since arrays are also objects, pairs can be used for arrays as well.`},{header:"while",slug:"while",content:`There is only one commonly used method for while. +local condition = true +while condition do print("while==true") condition = false +end +Similar to C-like languages. As long as condition is true, while will continue to run. When condition is set to false, the while loop will end.`},{header:"Loop Operators",slug:"loop-operators",content:`Just like in other languages, the break keyword is used to exit a loop. +In Lua, there is no continue, only break. However, the continue functionality can be achieved by using the if + break structure.`},{header:"Lua's Small Feature: Tables",slug:"lua-s-small-feature-tables",content:`Although Lua refers to its arrays as tables, I think this data structure is more similar to Python sets or JSON, as it can store anything without any structural constraints. +collection = {{"a", 1, 2}, "abc", {2, 3}} +To find the length of an array, simply prepend # before the array name. +list = {1, 2, 3, 4, 5} +for i=1,#list do print(list[i]) +end +In Lua, array (table) indices start from 1, unlike C-like languages where they start from 0. Taking the previously defined collection as an example: +-- collection = {{"a", 1, 2}, "abc", {2, 3}} +print(collection[1][1]) -- a +print(collection[2]) -- abc +print(collection[3][2]) -- 3`},{header:"Indexing",slug:"indexing",content:`Lua table indexing is very flexible and can be done with numbers, strings, or even other types of data. +Here are some simple examples: +local list = {} -- Indexing with numbers +list[1] = "a" -- Indexing with strings +list["b"] = 2 +list.message = "hello world" -- Equivalent to list["message"] = "hello world" print(list[1]) -- a +print(list["b"]) -- 2 +print(list.message) -- hello world`},{header:"Adding Elements",slug:"adding-elements",content:`Adding to a specific position +table.insert(table, pos, value) -- Inserts an element at a specific position (pos) +Or +table.insert(table, value) -- Appends an element at the end +Example +list = {1, 2, 3, 4, 5} +table.insert(list, 6) +-- {1, 2, 3, 4, 5, 6}`},{header:"Removing Elements",slug:"removing-elements",content:`table.remove(table, pos) -- Removes an element at a specific position +Example +list = {1, 2, 3, 4, 5} +table.remove(list, 2) +-- {1, 3, 4, 5}`},{header:"Sorting a Table",slug:"sorting-a-table",content:""},{header:"Default Sorting Method",slug:"default-sorting-method",content:`You can use a function to sort a list, and the simplest usage is as follows: +table.sort(list) -- Sorts the list in ascending order +Here is an example: +-- Function: Print List +function PrintList(list) -- Output the list local listStr = "" for i = 1, #list do listStr = listStr .. list[i] .. " " end print(listStr) +end local list = { 3, 7, 2, 5, 4 } -- Original list PrintList(list) -- Output the original list +table.sort(list) -- Sort the list +PrintList(list) -- Output the sorted list -- Result: +-- 3 7 2 5 4 (Original list) +-- 2 3 4 5 7 (Sorted list)`},{header:"Custom Sorting Method",slug:"custom-sorting-method",content:`The table.sort function can also use a custom sorting rule, but this rule needs to be written in a function. +table.sort(list, function(a, b)) +The function(a, b) is the custom sorting rule, which requires returning a boolean value (true or false) in the end. a and b are any two items in the list, and if the function returns true, then a comes before b, otherwise b comes before a. +Below are two examples for reference.`},{header:"Example 1: Changing the code above to output in descending order",slug:"example-1-changing-the-code-above-to-output-in-descending-order",content:`-- The PrintList() function is omitted here, with the same code as above local list = { 3, 7, 2, 5, 4 } -- Original list PrintList(list) -- Output the original list +table.sort(list, function(a, b) -- Sort the list return a > b -- Sort in descending order, if a > b, then a comes before b +end) +PrintList(list) -- Output the sorted list -- Output: +-- 3 7 2 5 4 (Original list) +-- 7 5 4 3 2 (Sorted list)`},{header:"Example 2: Sorting in a two-dimensional array",slug:"example-2-sorting-in-a-two-dimensional-array",content:`-- Function: Print the list +function PrintList(list) -- Output the list local listStr = "" for i = 1, #list do listStr = listStr .. "\\n" .. list[i][1] .. ", " .. list[i][2] end print(listStr) +end -- Original list +local list = { { 3, 5 }, { 7, 6 }, { 2, 2 }, { 5, 1 }, { 4, 3 } } PrintList(list) -- Output the original list -- Sort in descending order based on the first dimension of each item in the list +table.sort(list, function(a, b) return a[1] > b[1] +end) +PrintList(list) -- Output the sorted list -- Sort in descending order based on the second dimension of each item in the list +table.sort(list, function(a, b) return a[2] > b[2] end) +PrintList(list) -- Output the sorted list -- Output: +-- Original list: +-- 3, 5 +-- 7, 6 +-- 2, 2 +-- 5, 1 +-- 4, 3 -- Sorted based on the first dimension: +-- 7, 6 +-- 5, 1 +-- 4, 3 +-- 3, 5 +-- 2, 2 -- Sorted based on the second dimension: +-- 7, 6 +-- 3, 5 +-- 4, 3 +-- 2, 2 +-- 5, 1`},{header:"Reference of table",slug:"reference-of-table",content:`When there is no deep copy of a table, and it is directly copied, the newly obtained list2 is equivalent to a reference to the original list1, known as shallow copy. When you modify the elements in list2 obtained from shallow copy, the elements in list1 will also change because the two tables are referenced. +The above example code also follows this principle. Below is a new example to highlight this characteristic.`},{header:"Example: Shallow Copy",slug:"example-shallow-copy",content:`function PrintList(list) -- Output the list local listStr = "" for i = 1, #list do listStr = listStr .. list[i] .. " " end print(listStr) +end list1 = { 1, 2, 3, 4, 5 } +PrintList(list1) +-- 1 2 3 4 5 list2 = list1 +PrintList(list2) +-- 1 2 3 4 5 -- Modify the second element in list2 +list2[2] = 10 +PrintList(list2) +-- 1 10 3 4 5 PrintList(list1) +-- 1 10 3 4 5`},{header:"Example: Deep Copy",slug:"example-deep-copy",content:`And what if you want to create a completely new list list2? Then you need to copy each element in the table one by one, also known as deep copy. +-- PrintList function code remains the same as above list1 = { 1, 2, 3, 4, 5 } +PrintList(list1) +-- 1 2 3 4 5 list2 = {} -- Create a new empty list -- Copy elements from list1 to list2 +for index, value in pairs(list1) do table.insert(list2, value) +end +PrintList(list2) +-- 1 2 3 4 5 -- Modify the 2nd element of list2 +list2[2] = 10 +PrintList(list2) +-- 1 10 3 4 5 PrintList(list1) +-- 1 2 3 4 5 (no changes occurred) +In this example, modifying the elements in the deep copy list2 does not affect the original list1. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/mip.html",title:"Mixed integer programming",pathLocale:"/en/",contents:[{header:"Mixed integer programming",slug:"mixed-integer-programming",content:`Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web. Translate info +This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.`},{header:"Creating a Mixed-Integer Programming Model",slug:"creating-a-mixed-integer-programming-model",content:`Creating an integer programming model object. +local mip = math.newmip() -- Assign the created model object to mip`},{header:"Setting the Objective Function",slug:"setting-the-objective-function",content:`In MicroCity Web, the first line of the model is the objective function, added using the mip:addrow() function. +You can choose to maximize or minimize the objective function. The usage is as follows: Maximize +Minimize mip:addrow(coeff, 'max') -- Maximize the objective function mip:addrow(coeff, 'min') -- Minimize the objective function`},{header:"Parameter Description and Examples",slug:"parameter-description-and-examples",content:`Parameter +Purpose mip +Mathematical model object. Sets the objective function for the model coeff +Coefficients of the objective function, a table variable. Determines the coefficients of the objective function in the model. "min" or "max" +Determines whether to minimize or maximize the objective function. coeff is a list of coefficients for the objective function, a table variable. Suppose you want to minimize the function +4x1+12x2+18x3 +4x_1+12x_2+18x_3 +4x1​+12x2​+18x3​ +the approach to adding the objective function is as follows: +-- Assuming you have already created the model object and stored it in the variable mip +-- Set the objective function to 4*x1 + 12*x2 + 18*x3, minimize +mip:addrow({4, 12, 18}, "min")`},{header:"Adding Constraints",slug:"adding-constraints",content:""},{header:"Adding Constraint Equations",slug:"adding-constraint-equations",content:`In MicroCity Web, use mip:addrow() to add the remaining constraint equations. The usage is as follows: ≥ += mip:addrow(cons, ">=", b) mip:addrow(cons, "==", b)`},{header:"Parameter Description",slug:"parameter-description",content:`Parameter +Purpose mip +The integer programming model object created at the beginning cons +Coefficients of the constraint equation. Like cons in setting the objective function, it's a table variable. Determines the coefficients of the variables in the constraint equation. "<=" or ">=" or "==" +Determines the relationship between the constraint equation and the right-hand side. b +The right-hand side of the constraint equation.`},{header:"Example",slug:"example",content:`The objective function has been set to 4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​. Suppose you want to add two constraint equations for this function: +{x1+3x3≥32x2+2x3≥5 +\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. {x1​+3x3​≥32x2​+2x3​≥5​ +Add the corresponding constraint equations: +-- Add constraint: x1 + 3*x3 ≥ 3 +mip:addrow({ 1, 0, 3 }, ">=", 3) -- Add constraint: 2*x2 + 2*x3 ≥ 5 +mip:addrow({ 0, 2, 2 }, ">=", 5) +It can be noticed that the number of coefficients is the same as the number of variables in the objective function. Therefore, before programming, it is necessary to determine the total number of variables and arrange the positions of each variable.`},{header:"Setting Variable Types",slug:"setting-variable-types",content:`MicroCity's mathematical programming supports integer programming. The default variable range is non-negative real numbers (≥0). Below is a detailed method for setting variable types. +You can set the i-th variable in the model as an integer variable or a 0-1 variable. If you don't set the variable to these types, it defaults to a non-negative real number. Integer Variable +0-1 Variable -- Set the first variable (first column, col 1) as an integer variable +mip:addrow('c1', 'int') -- Set the second variable (second column, col 2) as a 0-1 variable +mip:addrow('c2', 'bin')`},{header:"Model Solution and Output",slug:"model-solution-and-output",content:""},{header:"Model Solution",slug:"model-solution",content:`Since the objective function and constraint equations have been added, solving the model is straightforward: +mip:solve() +After executing this statement, the mathematical model stored in the variable mip is solved 🎉`},{header:"Output",slug:"output",content:`After solving, you still need to output; otherwise, you won't know the results. Below are some commonly used functions for outputting the solution. +Get the value of the objective function: +mip['obj'] +Get the value of the i-th variable: +mip['c'..i] +Here is a simple example from modeling to solving for reference. (It's just putting the pieces together) +Example: +minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈N +minf=4x_1+12x_2+18x_3\\\\ +s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N +\\end{matrix}\\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​ N represents the set of natural numbers (non-negative integers) Script +local mip = math.newmip() -- Set objective functio +mip:addrow({4, 12, 18}, "min") -- Add constraints +mip:addrow({ 1, 0, 3 }, ">=", 3) -- x1 + 3*x3 ≥ 3 +mip:addrow({ 0, 2, 2 }, ">=", 5) -- 2*x2 + 2*x3 ≥ 5 -- Set all variables as integers +for i = 1, 3 do mip:addrow('c'..i, 'int') +end -- Solve the model +mip:solve() -- Output the value of the objective function +print("Objective function value:", mip['obj']) -- Output the value of each variable +for i = 1, 3 do print("x"..i.."=",mip['c'..i]) +end +Output +Objective function value: 42.0 +x1= 0.0 +x2= 2.0 +x3= 1.0 Online Execution +Check this example in MicroCityWeb`},{header:"Some Modeling Techniques",slug:"some-modeling-techniques",content:""},{header:"Linearization",slug:"linearization",content:`Sometimes we encounter modeling problems with multiple subscripts, such as decision variables xijx_{ij}xij​, where iii and jjj are indices. In such cases, linearization encoding is necessary. +Suppose the decision variable itself has a shape of 3 rows and 4 columns, i.e.: Col 1 +Col 2 +Col 3 +Col 4 x11x_{11}x11​ +x12x_{12}x12​ +x13x_{13}x13​ +x14x_{14}x14​ x21x_{21}x21​ +x22x_{22}x22​ +x23x_{23}x23​ +x24x_{24}x24​ x31x_{31}x31​ +x32x_{32}x32​ +x33x_{33}x33​ +x34x_{34}x34​ Suppose the objective function wants to sum these decision variables, i.e. F=∑i=13∑j=14xijF=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​. If you want to input this into the objective function, you can linearize it as x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​. +Since there are only two dimensions, you can use two for loops to achieve this: +local cons = {} +for i = 1, 3 do -- First dimension for j = 1, 4 do -- Second dimension cons[4 * (i - 1) + j] = 1 -- Fill in the coefficient -- The idea here is similar to carrying in arithmetic end +end`},{header:"Example: Assignment Model",slug:"example-assignment-model",content:`Now let's look at the specific usage of multi-dimensional linearization and its convenience using a practical example. +People A, B, C, and D deliver goods A, B, C, and D, respectively. The required time is shown in the table below. If each person delivers only one type of goods, which person should be assigned to deliver which type of goods to minimize the total time? Person\\Item +A +B +C +D A +14 +9 +4 +15 B +11 +7 +9 +10 C +13 +2 +10 +5 D +17 +9 +15 +13 Assuming goods A, B, C, D correspond to indices 1, 2, 3, 4, respectively, let xij=1x_{ij}=1xij​=1 represent person i delivering goods j, and xij=0x_{ij}=0xij​=0 represent person i not delivering goods j. +The mathematical model for the above problem can be represented as +minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1 +minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ +s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 +\\end{matrix}\\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​ +Solution code +-- Efficiency matrix +local cost = { {14, 9, 4, 15}, {11, 7, 9, 10}, {13, 2, 10, 5}, {17, 9, 15, 13} +} local mip = math.newmip() -- Create the objective function +local coeff = {} +for i = 1, 4 do for j = 1, 4 do -- Easily convert the 2D array to a 1D array here coeff[4 * (i - 1) + j] = cost[i][j] end +end mip:addrow(coeff, "min") -- Add constraints +for k = 1, 4 do -- Control the value of the first dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if i == k then -- Sum for j, check i cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) +end for k = 1, 4 do -- Control the value of the second dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then -- Sum for i, check j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end mip:addrow(cons, "==", 1) +end -- Solve the model +mip:solve() -- Output the value of the objective function +print("Objective function value:", mip['obj']) -- Output the decision variables +for i = 1, 4 do -- First dimension for j = 1, 4 do -- Second dimension local x = mip['c' .. 4 * (i - 1) + j] if x ~= 0 then print("x[" .. i .. "][" .. j .. "]=", x) end end +end +Output +Objective function value: 29.0 +x[1][3]= 1.0 +x[2][1]= 1.0 +x[3][4]= 1.0 +x[4][2]= 1.0 Online Execution +Check this example in MicroCityWeb Result +Person +Item x13=1x_{13}=1x13​=1 +A +C x21=1x_{21}=1x21​=1 +B +A x34=1x_{34}=1x34​=1 +C +D x42=1x_{42}=1x42​=1 +D +B`},{header:"Handling Intermediate Variables",slug:"handling-intermediate-variables",content:`Sometimes, there are intermediate variables in a model that must have corresponding positions in the matrix to be solved, and these intermediate variables do not participate in the calculation of the objective function value. The coefficients of the intermediate variables at their corresponding positions can be set to 0. +Suppose x1,x2,x3,x4x_1, x_2, x_3, x_4x1​,x2​,x3​,x4​ are decision variables, and y1,y2y_1, y_2y1​,y2​ are intermediate variables. The objective function is: +z=∑i=14xi +z=\\sum_{i=1}^4x_i +z=i=1∑4​xi​ +The coefficients of the objective function can be set as follows: +local fcons = {1, 1, 1, 1, 0, 0} +-- The first 4 elements correspond to decision variables, +-- and the last 2 elements correspond to intermediate variables +Afterward, you can proceed with the general process 😎`}]},{path:"/en/notes/network.html",title:"Operating Networks",pathLocale:"/en/",contents:[{header:"Operating Networks",slug:"operating-networks",content:""},{header:"Network Topology",slug:"network-topology",content:`Network topology, in simple terms, refers to a network with nodes and connections between them. If we think of connections as roads, then you need to solve the following problems: Is this road one-way or two-way? +Where does the road start? Where does it end? In general, each road in a network diagram is considered to be one-way. If a two-way road is needed, you simply need to add a road in the opposite direction. Like this: This way, each road has a direction. It is common to use the symbol O for the starting point and the symbol D for the destination point. Using O and D, the direction of each road can be clearly described. +For the example in the above diagram, the road at the top has O=1, D=2, so the direction is described as from 1 to 2; the road at the bottom has O=2, D=1, so the direction is described as from 2 to 1.`},{header:"Building Network Topology using Functions",slug:"building-network-topology-using-functions",content:`MicroCity can handle networks, and the specific usage of all functions can be found in the reference document: 4.6 Networks +Here are some simple methods for creating network objects in MicroCity: +local network = CreateNetwork() Create an empty network object and return it. network is the returned empty network object. +After creating the object, you can use functions like AddLink and DelLink to create connections in the network object. See the reference document for specific usage. +local network, nodes, links = CreateNetwork(Lines) +Here, Lines is a vector graphic object of type Line. In this usage, the CreateNetwork() function in MicroCity can directly add starting points and endpoints to the road connections and automatically label the O and D points in the returned links object. +In other words, you only need to provide the network connections, and the remaining work of topology can be automatically completed by the function. I believe this may be the most commonly used method for creating network diagrams and conducting topology.`},{header:"Simple Example of Network Topology",slug:"simple-example-of-network-topology",content:`-- Open the connection layer +Shapes = Open("Shapes.shp") -- Create network topology +network, network_nodes, network_links = CreateNetwork(Shapes) -- Create a layer to store the topologized network nodes +Nodes = CreateShapes("Nodes", "point") +-- Copy the network nodes obtained from topoization to the layer +AddField(Nodes, "ID", "int") +for i = 1, GetRecCount(network_nodes) do CopyShapeTo(Nodes, 0, 0, GetShape(network_nodes, i)) +end -- Create a layer to store the topologized network connections +Links = CreateShapes("Links", "line") +-- Copy the original attribute fields from the network connections to the layer +for i = 1, GetFieldCount(Shapes) do AddField(Links, GetField(Shapes, i)) +end +-- Add attribute fields for the connections, and corresponding data will be added later using functions +AddField(Links, "ID", "int") +AddField(Links, "O", "int") +AddField(Links, "D", "int") +AddField(Links, "IMPEDANCE", "double") +AddField(Links, "DIRECTION", "int") +AddField(Links, "CAPACITY", "double") +-- Copy the network lines obtained from topoization to the layer (including corresponding data) +for i = 1, GetRecCount(network_links) do CopyShapeTo(Links, 0, 0, GetShape(network_links, i)) +end -- Update the layers +Update(Nodes) +Update(Links) The example is modified from the built-in editor of MicroCity. Although the network connection was established at the beginning, it is possible that during the topology process, the nodes on the connection may overlap, causing the continuous connection to be divided into multiple segments. Therefore, the resulting Links layer may be different from the input layer. The topology nodes Nodes obtained from the topology process correspond to the resulting links Links, so it is recommended to use the topological processing result of the Links layer as the connection between network nodes.`},{header:"Pitfall: Creating Network Objects",slug:"pitfall-creating-network-objects",content:`If you need to create a network again using the CreateNetwork(Nodes, Links) function, you need to retain the attributes added during the topological process, otherwise there will be errors in network initialization: +AddField(Links, "ID", "int") +AddField(Links, "O", "int") +AddField(Links, "D", "int") +AddField(Links, "IMPEDANCE", "double") -- impedance +AddField(Links, "DIRECTION", "int") -- direction +AddField(Links, "CAPACITY", "double") -- capacity +If you are only doing a one-time topology of the network and will not use the topologically processed network to create a network object again, you still need to create the above attributes first. The topologically processed data is not filled in according to the attribute names, but according to their positions. +If only O and D attributes are created, the ID data will be filled in the O attribute, and the O data will be filled in the D attribute. If only the ID, O, and D attributes are created in the order mentioned above, the data will be filled correctly due to the data order being filled based on their positions.`},{header:"CopyShapeTo Function",slug:"copyshapeto-function",content:`The CopyShapeTo() function is used in the topological process to copy a Shape object to the corresponding position in the Shapes layer and perform position transformation in the Shapes layer based on the input dx and dy. Here, dx and dy represent the displacements in the x and y directions (referred to as deltax and deltay). +CopyShapeTo(TargetShapes, dx, dy, Shape1 [, Shape2, ...]) +Based on the usage of the function, it also supports copying to multiple layers and then performing the transformation. If you only want to copy the shape to the corresponding position of the corresponding layer without transformation, you can set dx and dy to 0, like this: +CopyShapeTo(TargetShapes, 0, 0, Shape1 [, Shape2, ...]) +For the specific usage of the CopyShapeTo() function, please refer to 4.3 Vector Graphics and Tables`},{header:"Using the Network Topology Algorithm",slug:"using-the-network-topology-algorithm",content:"After performing the network topology, you can use the built-in functions to solve many problems, such as generating a minimum spanning tree, finding the shortest path, or calculating the shortest distance. This article will take the calculation of the shortest path and its length as an example to explain the process and pitfalls of calculating the shortest path."},{header:"Calculating the Shortest Path and Its Length",slug:"calculating-the-shortest-path-and-its-length",content:"To calculate the shortest path, it is necessary to determine which two points in the network the shortest path is between. Here, startID and endID represent the starting point and the endpoint, respectively. Let's assume that you have already created a network object and stored it in a variable named Network. If you don't know how to create a network graph, you can refer to the Network Topology process described above."},{header:"Creating a Minimum Spanning Tree",slug:"creating-a-minimum-spanning-tree",content:`Step 1: First, create a minimum spanning tree with startID as the starting point. Theoretically, after creating a minimum spanning tree with the starting point, you can obtain the shortest distance from the starting point to any point on the network. You can use the GenSTPTree() function to create a minimum spanning tree. +GenSTPTree(Network, startID [, endID]) +The endID here is not necessary, but if it is available, you can provide it to the function. In other words, you have two ways to accomplish this: +GenSTPTree(Network, startID) -- Method 1 +GenSTPTree(Network, startID, endID) -- Method 2 (recommended) +It is generally believed that the more complete the information provided, the better the execution effect. Since you already know endID before calculating the shortest path, it is recommended to provide it to the function. The usage of this function with brackets has been explained here, and this notation will be used directly in the following text. Step 2, obtain the information corresponding to the shortest path. As mentioned earlier, the shortest route between two points can only be determined after the starting point and the destination point are determined. Since the minimum spanning tree was created using the starting point startID earlier, now we only need to provide the destination point endID in order to obtain the shortest path and its length. The following explains the methods to obtain the shortest path length and the shortest path using the Network object.`},{header:"Obtaining the Shortest Path Length",slug:"obtaining-the-shortest-path-length",content:`MicroCity's documentation provides three ways to obtain the shortest path. +The first method is used when the shortest path spanning tree has already been calculated and the information for the starting point has been inputted. Therefore, now only the information for the destination point needs to be provided (even if it has been provided already). The function requires a network object Network and the endpoint endID is used as follows: +local len = GetSTPLen(Network, endID) +The second method calculates the shortest path length between two points on the network by providing the starting point startID and the destination point endID. This usage does not require generating the shortest path spanning tree before calculating the shortest path and can be used directly. The Network parameter represents the network object and is used as follows: +local len = GetSTPLen(Network, startID, endID) +The third method calculates the shortest path length between two points on the network by providing the xy coordinates of the starting and destination points. This usage also does not require generating the shortest path spanning tree before calculating the shortest path and can be used directly. The coordinates of the starting point are set as x1 and y1, the coordinates of the destination point are set as x2 and y2, and the Network parameter represents the network object and is used as follows: +local len = GetSTPLen(Network, x1, y1, x2, y2)`},{header:"Obtaining the Shortest Path",slug:"obtaining-the-shortest-path",content:`MicroCity's documentation provides three pieces of information that can be obtained, namely: The sequence of point or line IDs +The sequence of point or line indices +The sequence of point or line shapes. For detailed usage of the functions, please refer to 4.6 Networks - Algorithms. Here, only the second method, which returns the sequence of point or line indices, will be used as an example. +To return the sequence of points: +GetSTPPath (Network, endID, "iNodeShp") +To return the sequence of lines: +GetSTPPath (Network, endID, "iLinkShp") +This way, the sequence of point or line indices can be obtained.`},{header:"Pitfall: Sequences",slug:"pitfall-sequences",content:`In Getting Started with Lua, we introduced sets in Lua, which provide rich features to assist in code writing. However, we have not heard of sequences. A sequence is something like this: +local x, y = GetCenterXY(Shapes) -- using this function temporarily +Here, x and y form a sequence. Here's another scenario: +GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) -- using another function here temporarily +In this case, the more points that are inputted, the more return values there will be. If four points are inputted, it can be handled like this: +-- Normal case +d1, d2, d3, d4 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -- Only the first two return values can be kept +d1, d2 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) -- Of course, only one return value can be kept as well +d1 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4) +The number of input parameters and output parameters in the above function are related. If n points are inputted as parameters, n distances will be returned. However, for the network topology, when returning the shortest path, the returned values are always parameter sequences, and I don't know how many parameters the function will give me; and when there are too many output parameters, it is also not feasible to manually create many variables to store these parameters. +-- Wrong approach: +local indexList = GetSTPPath(Network, endID, "iLinkShp") +-- The GetSTPPath() function does not return a table +-- The indexList obtained here is only the index of the first Link, which is a numerical value. +Since the left side of the equal sign cannot be changed, let's make changes on the right side. Do you remember how to define a simplest table? +local list = {1, 2, 3, 4, 5} +The [to_be_replace[x]] on the right side can actually be seen as a sequence. So, as long as you add parentheses to the return value of a function, you can pick them all up ( •̀ ω •́ )✧ +local indexList = { GetSTPPath(Network, endID, "iLinkShp") } +The indexList obtained using the above method is a variable of table type. Then, you can start performing various operations on the collection 😋 This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/oop.html",title:"Object-Oriented Programming",pathLocale:"/en/",contents:[{header:"Object-Oriented Programming",slug:"object-oriented-programming",content:`Object-Oriented Programming (OOP) is a programming paradigm that abstracts real-world entities into objects in the program world. Objects communicate with each other through message passing, forming the functionality of a program. According to online sources, OOP has three main characteristics: encapsulation, inheritance, and polymorphism. However, in this simulation, encapsulation is the most frequently used, while the opportunities for inheritance and polymorphism are rare. Additionally, I haven't implemented object message passing in MicroCity yet. If I do, I will update this article accordingly. Therefore, the following mainly introduces how to use encapsulation in Lua code for MicroCity. Tips +The code examples in this article are applicable to MicroCityWeb and may not necessarily work for the desktop version of MicroCity. Furthermore, this article is based on personal insights and does not guarantee absolute correctness in terms of concepts.`},{header:"Basic Concepts of Object-Oriented Programming",slug:"basic-concepts-of-object-oriented-programming",content:""},{header:"Classes and Objects",slug:"classes-and-objects",content:`In simple terms, a class is a template for objects, and an object is an instance of a class. +A class is a fundamental concept in object-oriented programming that represents a category of things. The concept of a class can be understood as a category of objects—such as AGVs, shelves, and gantry cranes. You can think of a class as a template for a category of things, and objects are specific instances created based on this template. +A good example is the mentioned shelf. A shelf is a class, and a specific shelf is an object. The shelf class contains various attributes, such as the shelf's location and the items it holds. Different shelf objects created from the shelf class belong to the shelf class, such as Shelf 1, Shelf 2, etc. Although their attributes may differ, they are all objects of the shelf class.`},{header:"Class Attributes and Methods",slug:"class-attributes-and-methods",content:"In MicroCity simulation, based on my personal experience, classes usually have attributes but not necessarily methods. Continuing with the example of a shelf mentioned earlier, attributes are the characteristics of a class, such as the location of the shelf and the items on the shelf. Methods represent the behaviors of a class and are usually implemented with functions, such as an AGV lifting or placing a shelf, an AGV moving, or driving a shelf."},{header:"Advantages and Disadvantages of Using Object-Oriented Programming in Simulation",slug:"advantages-and-disadvantages-of-using-object-oriented-programming-in-simulation",content:""},{header:"Advantages",slug:"advantages",content:`In MicroCity, when dealing with scenarios involving the movement of multiple objects of the same type and playing animations of object movements (such as AGVs, shelves, and gantry cranes), a considerable amount of coordinate calculations and position settings are required. If each object needs to be implemented individually, the code for modifying the coordinate of each object will become very long, making it difficult to maintain. By using the object-oriented programming paradigm, data processing code can be encapsulated into individual objects, making the code more readable and maintainable. +Furthermore, if multiple objects of the same type need to be created in a scene, each object may have different parameters. By encapsulating using object-oriented methods, each object's parameters can be encapsulated within the objects themselves. When the simulation process or scale becomes more complex, the reusability of the code can be increased. +For simulations, the most important aspect is understanding the business process and business logic. Using object-oriented programming can make the simulation's business process and logic more clear, improve code readability, and increase maintainability. Furthermore, when it is necessary to modify the business logic of a class of objects, you only need to enter the class and make the modification. For example, modifying the scheduling algorithm for all gantry cranes in a port only needs to be done once because all gantry cranes share the same scheduling algorithm. +Based on personal experience, when using object-oriented methods to encapsulate objects, it is mostly intended to create a generic object and then create multiple objects of the same type in subsequent simulations automatically or manually, with different parameters for each object. This increases code reusability and improves code readability, providing convenience for future maintenance and modifications, and lays a foundation for large-scale simulations.`},{header:"Disadvantages",slug:"disadvantages",content:"If the simulation is small in scale and involves simple operations with a small codebase, it is not recommended to use object-oriented methods for code encapsulation. Using object-oriented methods will increase the number of lines of code, and may make the code appear more complex than the original problem. (Of course, there will be no consequences if you still choose to use it, except that it may look strange.) Specifically, you can refer to the provided code examples in the following sections and notice that most of the code is dedicated to describing classes and their business logic, while the code for the business process is simple and occupies a small proportion."},{header:"Implementation of Object-Oriented Programming in Lua",slug:"implementation-of-object-oriented-programming-in-lua",content:"In Lua, the concept of object-oriented programming is typically implemented using tables. A table is a data structure in Lua that can represent arrays, dictionaries, objects, etc. In object-oriented programming, tables can be used to represent objects."},{header:"Example",slug:"example",content:`Since the objects created in MicroCity are tables, we can encapsulate the object's attributes directly in a table and return that table when creating an object. +Here's an example: +-- The function will return an AGV object +function AGV() -- Create a 3D object of an AGV in MicroCity local agv = scene.addobj('/res/agv.glb') -- Set the properties of the object agv.position = {0, 0, 0} -- Set the position of the object agv.speed = 1 -- Set the speed of the object function agv:move(dx, dy, dz) agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- Modify the object's coordinates agv:setpos(agv.position[1], agv.position[2], agv.position[3]) -- Set the object's position scene.render() -- Render the scene (Not recommended to call here, just for demonstration purposes) end return agv -- Return the object +end -- Object usage +local obj = AGV() -- Create an object +obj:move(1, 0, 0) -- Move the object 1 unit in the x direction +Or you can choose to encapsulate the object within a table and return that table after creating the object. +-- The function will return an AGV object +function AGV() -- Set the object's properties directly in the table to be returned local agv = { object = scene.addobj('/res/agv.glb'), position = {0, 0, 0}, speed = 1 } function agv:move(dx, dy, dz) agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- Modify the object's coordinates agv.object:setpos(agv.position[1], agv.position[2], agv.position[3]) -- Set the object's position scene.render() -- Render the scene (Not recommended to call here, just for demonstration purposes) end return agv -- Return the object +end -- Object usage +local agv = AGV() -- Create an object +agv:move(1, 0, 0) -- Move the object 1 unit in the x direction +There is also another method to create objects using setmetatable, this belongs to advanced usage, but I feel like it is not used very often. However, it seems like this method can be used to achieve class inheritance, if you are interested, you can search for it yourself. Here is the code implementation of the shelf class that I wrote for an earlier assignment as a reference. (Now I feel like this class is not written very well 😂, for example, x and y can be replaced with pos = {x, y}, and x_origin and y_origin can be replaced with origin = {x, y}). +-- Shelf +Shelf = { x = 1, y = 1, cargo = {"box"}, -- Items on the shelf x_origin = 1, -- Shelf's original x coordinate y_origin = 1 -- Shelf's original y coordinate +} function Shelf:New(x, y) local self = {} setmetatable(self, { __index = Shelf }) self.__index = self self.x = x self.y = y -- Set the original coordinates self.x_origin = x self.y_origin = y return self +end`},{header:"Types of Classes",slug:"types-of-classes",content:`Here, I would like to summarize the main types of classes that I have created. 3D entity classes: These classes mainly control the movement of 3D entities, such as AGVs and cranes. Most of them have physical entities that need to be moved. Some even include sub-objects, such as crane objects that have hoists, ropes, and cranes as sub-objects. +Data model classes: These classes represent various entities in a system, such as yards, shelves, and goods. For example, a yard class contains data about the yard's dimensions, the goods in the yard, and the containers in the yard. It should be noted that I do not strictly categorize these types, as certain classes may possess the characteristics of multiple types. For instance, an AGV class also includes data about the AGV's position and speed, while a shelf class merely stores the shelf model. The movement of the shelf model is controlled by the AGV, and the more important function of the shelf class is to record the information of the goods on the shelf. Therefore, I consider these types as rough distinctions, and the specific implementation should be based on the actual business processes and requirements. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/plots.html",title:"Generic Drawing Code",pathLocale:"/en/",contents:[{header:"Generic Drawing Code",slug:"generic-drawing-code",content:`This section provides some pre-written drawing objects, which are convenient for direct use when visualizing data. Info +All open source code on this page is licensed under the MIT license and can be used freely. However, please retain the copyright information when publicly distributing.`},{header:"Histogram",slug:"histogram",content:`A histogram is generally used to display the frequency or frequency distribution of various data values in a data set. It divides the data into several intervals (or "bins") according to a certain interval and then plots the frequency (or frequency) of each interval as a bar chart on the y-axis to reflect the distribution of the data. +Here is an example of a histogram drawn using the histogram object I wrapped.`},{header:"Importing the Histogram",slug:"importing-the-histogram",content:'First, import the histogram code. There are currently two options: Download the code file and import it (recommended): [Download the histogram code file](#Code file download) Histogram.lua and import it into MicroCityWeb. Then, reference the file to use it. The code reference is as follows: require("Histogram") --Reference the histogram Copy the code: Copy the code from the Histogram.lua file directly into your code. The code is shown [below](#Histogram Code).'},{header:"Creating a Histogram Object",slug:"creating-a-histogram-object",content:`Create a histogram object. +local plot = Histogram(list) -- list is the data set +You can also set the properties of the graph when creating the object. +local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end}) +Setting the properties is not necessary and can be done as needed. In this case, only the range, scale, and fdisp properties are set.`},{header:"Setting Histogram Properties",slug:"setting-histogram-properties",content:`The above example provides a simple demonstration of setting histogram properties. According to the code, more properties can be set. See the table below for details: Property +Function +Example origin +Set the origin of the graph (bottom-left point) +origin = {-50, -50}, set the origin of the graph at position (-50,-50) size +Set the length of the x and y axes of the graph +size = {100, 100}, set the length of the x and y axes of the graph to 100 each scale +Set the graduations of the x and y axes +scale = {3, 2}, set the graduations of the x and y axes of the graph to 3 and 2 respectively axislabel +Set the titles of the x and y axes +axislabel = {"x", "y"}, set the titles of the x and y axes of the graph to "x" and "y" respectively range +Set the display range of the x and y axes +range = {0, 10, 0, 20}, set the x-axis range of the graph to [0,10] and the y-axis range to [0,20] filled +Set whether to fill the bar chart +filled = false, set the bar chart to unfilled. The default style is filled fdisp +The display function for data labels, which defaults to the quantity. When setting the display function for data labels, it will also affect the display of y-axis tick marks. +fdisp = function(v) return (v/n*100).."%" end, change the data labels to display in proportion (assuming n is the sample size)`},{header:"Advanced Usage of Histograms",slug:"advanced-usage-of-histograms",content:"Dynamically refresh the data plot. Modify the data in the graph. Here, we use adding data to the graph as an example. Let's assume rnd is the data to be added. You can also directly modify the value of plot.data. table.insert(plot.data, rnd) Refresh the graph. plot:refresh()"},{header:"Example",slug:"example",content:""},{header:"Basic Usage Example: Drawing a Poisson Distribution",slug:"basic-usage-example-drawing-a-poisson-distribution",content:`require("Histogram") --Reference the histogram local seed = math.randomseed(1, { distribution = "poisson", mu = "3" +}) +local list = {seed:random()} --Static drawing +for i = #list, 400 do table.insert(list, seed:random()) +end local histplot = Histogram(list, { range = {0, 10, 0, 50}, scale = {1, 5} +}) +scene.render()`},{header:"Advanced Usage Example: Dynamically Refreshing Plot of the Poisson Distribution",slug:"advanced-usage-example-dynamically-refreshing-plot-of-the-poisson-distribution",content:`This is an example of plotting the Poisson distribution and dynamically refreshing the data plot. It is assumed that the Histogram object has been imported and the scene is set for 2D display. +require("Histogram") -- Import the histogram local seed = math.randomseed(1, { distribution = "poisson", mu = "3" +}) +local list = {seed:random()} local histplot = Histogram(list, { range = {0, 10, 0, 50}, scale = {1, 8} +}) +scene.render() -- Dynamic drawing +local count = 1 +while count < 1000 do local rnd = seed:random() table.insert(histplot.data, rnd) histplot:refresh() count = count + 1 scene.render() +end`},{header:"Subplots",slug:"subplots",content:"Subplots are a way to position and size multiple plots within a single interface. The name is borrowed from MATLAB."},{header:"Importing Subplots",slug:"importing-subplots",content:'First, import the code for subplots. Like histograms, there are two options for importing: Download the code file and import (recommended): Download the subplot code file, import the Subplot.lua file in MicroCityWeb, and then use the code. Use the following code to import:require("Subplot") -- Import the subplot code Copy the code: Copy the code from the Subplot.lua file directly into your code. In this case, there is no need to import the code. See the code below.'},{header:"Creating Subplot Objects",slug:"creating-subplot-objects",content:`When creating a subplot, you must specify the number of rows and columns. The number of rows and columns determines the number of subplots. +local subplot = Subplot(rows, cols) +You can also set additional properties to define the position and size of the subplots. Here is an example of setting the position and size of the subplots when creating them: +local subplot = Subplot(rows, cols, {span=10, diag={-80, -70, 80, 70}})`},{header:"Setting Subplot Properties",slug:"setting-subplot-properties",content:`Here, we will provide a detailed description of the properties of subplots. Setting these properties is optional and can be done as needed. Property +Description +Example span +Sets the spacing between subplots +span=10, sets the spacing between subplots to 10 in all directions diag +Sets the position and size of a subplot by specifying the coordinates of the two diagonal points +diag = {-80, -70, 80, 70}, sets the diagonal range of the subplot from coordinates (-80,-70) to (80,70)`},{header:"Reading Subplot Values",slug:"reading-subplot-values",content:`After creating a subplot with properties, or modifying the properties and refreshing, you can read the values of the subplots, including the origin position and size of each subplot, using the following attributes. Note +Here, it is assumed that the subplot object is stored in the subplot variable after creation. Attribute +Meaning +Example originpt +The origin position of each subplot in the Subplot object +The origin position of the subplot in the i-th row and j-th column can be obtained by subplot.originpt[i][j][1] and subplot.originpt[i][j][2] psize +The size of each subplot in the Subplot object +The width and height of the subplot in the subplot can be obtained by subplot.psize[1] and subplot.psize[2].(assuming all subplots have the same size)`},{header:"Example",slug:"example-1",content:`This is an example of drawing the range of subplots. Assume that the Subplot object has been imported and the scene has been set to 2D display. +Here, the display range of each subplot in a 2x3 subplot is drawn as a rectangle. The range of each subplot is represented by four gray points, and the position of each subplot is represented by a blue rectangle. +require("Subplot") -- import the Subplot library local subplot = Subplot(2, 3, {span = 10}) -- Draw the boundary points of the Subplot object +local lb = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[2],0}}) +local lt = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[4],0}}) +local rb = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[4],0}}) +local rt = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[2],0}}) -- Draw the range of each subplot +for i = 1, subplot.row do for j = 1, subplot.col do scene.addobj("polyline", {size = 8, color = "blue", vertices={ subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0, subplot.originpt[i][j][1], subplot.originpt[i][j][2], 0, subplot.originpt[i][j][1], subplot.originpt[i][j][2]+subplot.psize[2], 0, subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2]+subplot.psize[2], 0, subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0, } }) end +end +scene.render()`},{header:"Code",slug:"code",content:"You can remove the scene.setenv code at the beginning depending on the combination of your code. The scene.render() in the code is used to refresh the image during dynamic drawing."},{header:"Code File Download",slug:"code-file-download",content:`A list of code files can be found in ModelResource/libs Name +Link Histogram +ModelResource/libs/Histogram.lua Subplot +ModelResource/libs/Subplot.lua`},{header:"Histogram Code",slug:"histogram-code",content:`Histogram +-- Initial scene settings +local s = scene.setenv({camtype = "ortho"}) -- Returns a histogram object +function Histogram(data, ...) local plot = { -- Default value settings origin = {-50, -50}, -- Coordinate origin coordinates size = {100, 100}, -- Coordinate axis length scale = {3, 2}, -- Coordinate axis scale values range = {0, 10, 0, 20}, -- xy-axis range axislabel = {"x", "y"}, filled = true, -- Whether to fill fdisp = function(v) -- Data label display return v end, } -- Import parameters and fallback if ... ~= nil then for k, v in pairs(...) do plot[k] = v end end local barShape = "polygon" if plot.filled == false then barShape = "polyline" end -- Initialization plot.axes = {} -- Coordinate axes plot.originlabel = {} -- The zero point may have dual coordinates plot.bars = {} -- Data bars plot.xvalue = {} -- x-axis tick values (excluding the minimum value) plot.data = data function plot:deldata() -- Delete data (private) if #plot.bars == 0 then return end for i = #plot.bars, 1, -1 do -- print("plot.bar:",i) plot.bars[i][2]:delete() plot.bars[i][1]:delete() end plot.zero:delete() for i = #plot.originlabel, 1, -1 do plot.originlabel[i]:delete() end for i = #plot.axes, 1, -1 do for j = #plot.axes[i], 1, -1 do plot.axes[i][j][2]:delete() plot.axes[i][j][1]:delete() end end end function plot:refresh() -- Called when drawing repeatedly (public) plot:deldata() +-- Calculate coordinate scale parameters +local xmax = math.max(math.max(table.unpack(plot.data)), plot.range[2]) +local xmin = math.min(math.min(table.unpack(plot.data)), plot.range[1]) +local valueRange = xmax - xmin +plot.range[1], plot.range[2] = xmin, xmax +-- Statistical drawing values +local barData = {} +for i = 1, #data do -- Deep copy +table.insert(barData, data[i]) +end +plot.barValue = {} +-- Draw zero point +plot.zero = scene.addobj("points", { +vertices = {plot.origin[1], plot.origin[2], 0}, +size = 10 +}) +if plot.range[1] == plot.range[3] then -- Both are 0 +plot.originlabel[1] = scene.addobj("label", { +text = plot.range[1], +size = 4 +}) +plot.originlabel[1]:setpos(plot.origin[1] - 4, plot.origin[2] - 4, 0) +else +plot.originlabel[1] = scene.addobj("label", { +text = plot.range[1], +size = 4 +}) +plot.originlabel[1]:setpos(plot.origin[1], plot.origin[2] - 4, 0) +plot.originlabel[2] = scene.addobj("label", { +text = plot.range[3], +size = 4 +}) +plot.originlabel[2]:setpos(plot.origin[1] - 4, plot.origin[2], 0) +end +-- X-axis Scale +local xaxis = {} -- x-axis object, with elements as {point, label} +for j = 1, (plot.range[2] - plot.range[1]) / plot.scale[1] do -- index of the scale +local xpt = plot.origin[1] + j * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] -- X-axis scale position +local pt = scene.addobj("points", { +vertices = {xpt, plot.origin[2], 0}, +size = 5 +}) -- scale point +local label = scene.addobj("label", { +text = string.format("%.1f", plot.range[1] + j * plot.scale[1]), +size = 4 +}) -- scale label +table.insert(plot.xvalue, plot.range[1] + j * plot.scale[1]) -- current x-axis value +label:setpos(xpt, plot.origin[2] - 4, 0) +xaxis[j] = {pt, label} -- add object to x-axis collection +end +plot.axes[1] = xaxis for i = 1, #plot.axes[1] do -- based on x-axis score local ub = plot.xvalue[i] -- current loop maximum value -- print("Loop", i, "ub=", ub) -- for debugging local value = 0 for j = #barData, 1, -1 do if barData[j] <= ub then value = value + 1 table.remove(barData, j) end end plot.barValue[i] = value -- record value end local ymax = math.max(table.unpack(plot.barValue)) plot.range[4] = math.max(ymax, plot.range[4]) -- Y-axis scale +local yaxis = {} -- y-axis objects, each element is {point, label} +for i = 1, (plot.range[4] - plot.range[3]) / plot.scale[2] do -- index of each scale local ypt = plot.origin[2] + i * plot.size[2] / (plot.range[4] - plot.range[3]) * plot.scale[2] -- Y-scale position local pt = scene.addobj("points", { vertices = {plot.origin[1], ypt, 0}, size = 5 }) -- scale point local label = scene.addobj("label", { text = plot.fdisp(plot.range[3] + i * plot.scale[2]), size = 4 }) -- scale label label:setpos(plot.origin[1] - 4, ypt, 0) yaxis[i] = {pt, label} +end +plot.axes[2] = yaxis -- Draw data +local xunit = plot.size[1] / (plot.range[2] - plot.range[1]) * #plot.axes[1] -- x-axis division value +local yunit = plot.size[2] / (plot.range[4] - plot.range[3]) -- y-axis division value -- Draw histogram based on the values +for i = 1, #plot.axes[1] do -- Drawing local xl = plot.origin[1] + (i - 1) * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] local xr = plot.origin[1] + i * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] local yb, yt = plot.origin[2], plot.origin[2] + plot.barValue[i] * yunit local bar = scene.addobj(barShape, { vertices = {xl, yb, 0, xr, yb, 0, xr, yt, 0, xl, yt, 0, xl, yb, 0} }) local label = scene.addobj("label", { text = plot.fdisp(plot.barValue[i]), size = 4 }) label:setpos((xl + xr) / 2, yt + 2, 0) plot.bars[i] = {bar, label} +end +function plot:draw() -- Draw initialization -- Coordinate axis object plot.coord = scene.addobj("polyline", { vertices = {plot.origin[1] + plot.size[1], plot.origin[2], 0, plot.origin[1], plot.origin[2], 0, plot.origin[1], plot.origin[2] + plot.size[2], 0} }) -- Coordinate axis title if plot.axislabel~=nil then plot.axislabel[1] = scene.addobj("label", { text = plot.axislabel[1], size = 4 }) plot.axislabel[1]:setpos(plot.origin[1] + plot.size[1], plot.origin[2] - 8, 0) plot.axislabel[2] = scene.addobj("label", { text = plot.axislabel[2], size = 4, }) plot.axislabel[2]:setpos(plot.origin[1]-4, plot.origin[2] + plot.size[2]+6, 0) plot.axislabel[2]:setrot(0,0,1) end +end plot:draw() +plot:refresh() +scene.render() +return plot +end`},{header:"Subplot code",slug:"subplot-code",content:`Subplot +-- Attribute parameters +-- local diag = {-80, -70, 80, 70} -- lbx,lby,rtx,rty +-- local span = 10 +-- local row, col = 2, 2 +function Subplot(row, col, ...) local subplot = { span = 10, diag = {-80, -70, 80, 70}, originpt = {}, -- Store coordinates of each row and column psize = {} -- Subplot size } subplot.row, subplot.col = row, col \`\`\`lua +-- Import parameters and fallback +if ... ~= nil then for k, v in pairs(...) do subplot[k] = v end +end function subplot:refresh() -- Calculate parameters subplot.psize = { (subplot.diag[3]-subplot.diag[1] - (subplot.col-1)*subplot.span)/subplot.col, (subplot.diag[4]-subplot.diag[2] - (subplot.row-1)*subplot.span)/subplot.row } local gwidth, gheight = subplot.psize[1]+subplot.span, subplot.psize[2]+subplot.span -- Recalculate originpt subplot.originpt = {} for i = 1, subplot.row do subplot.originpt[i]={} for j = 1, subplot.col do subplot.originpt[i][j] = {subplot.diag[1]+(j-1)*gwidth, subplot.diag[2]+(i-1)*gheight} end end +end subplot:refresh() +return subplot +end This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/timelapse.html",title:"Time Advancement Methods",pathLocale:"/en/",contents:[{header:"Time Advancement Methods",slug:"time-advancement-methods",content:"The time advancement method in simulation refers to how the simulation time is progressed during the simulation process."},{header:"Classification of Time Advancement Methods",slug:"classification-of-time-advancement-methods",content:`There are three major categories of common simulation time advancement methods: Event scheduling method: Event scheduling method is an event-based simulation method that sorts events in the simulation system and simulates them based on the order of their occurrence. +Fixed increment advancement method: The fixed increment advancement method refers to fixing a time increment during the simulation process. After setting the starting time, the simulation time is advanced based on the time increment. +Master clock advancement method: The master clock advancement method refers to controlling the entire simulation system during the simulation process using a master clock. It controls the simulation process by controlling the clock.`},{header:"Example",slug:"example",content:""},{header:"Event Scheduling Method",slug:"event-scheduling-method",content:`The event scheduling method is an event-based simulation method that sorts events in the simulation system and simulates them based on the order of their occurrence. During the simulation process, the simulation system determines the next event to occur based on the current simulation time and the time of each event, and advances the simulation time to the time when the event occurs. +The event scheduling method consists of the following three main steps, which are also the main steps of the control program for the event scheduling method: Time scanning: Determine the time when the next event will occur and advance the simulation clock to that moment. +Event identification: Correctly identify the event that is about to occur. +Event execution: Correctly execute the event that has occurred. The basic principle flowchart of the event scheduling method is as follows: +For the specific implementation of the event scheduling method in MicroCityWeb, please refer to Discrete Event Simulation and Program Control - Coroutine.`},{header:"Fixed Increment Advancement Method",slug:"fixed-increment-advancement-method",content:"The fixed increment advancement method refers to fixing a time increment during the simulation process and advancing the time simulation based on the increment from the starting time. Within each time step, if no event occurs, the simulation clock is advanced by one unit of time T; if there are multiple events within the step, these events are considered to occur at the end of the step. Example"},{header:"Code Flow Example",slug:"code-flow-example",content:`while scene.render() do t = t + dt if t % cycle ~= work_time then d = d + v * dt print("Time after departure:", t, "hours") else print("Time after departure:", t, "hours, resting") end car:setpos(CastToLine(d)) -- Linear trajectory os.sleep(200) +end This is the main flow of the code and cannot be used directly.`},{header:"Master Clock Advancement Method",slug:"master-clock-advancement-method",content:`The master clock advancement method refers to controlling the entire simulation system during the simulation process using a master clock. It controls the simulation process by controlling the clock. The master clock advancement method can be divided into two types: synchronous master clock and asynchronous master clock. Synchronous master clock means that all modules use the same master clock for advancement, while asynchronous master clock means that different modules use different master clocks for advancement. +The last part of the Automated Warehouse Simulation Approach mentions the improvement space and ultimately implements the master clock advancement method with synchronous master clock. The implementation is done but the code is not included.`},{header:"Changes from the Automated Warehouse Simulation to the Master Clock Advancement Method",slug:"changes-from-the-automated-warehouse-simulation-to-the-master-clock-advancement-method",content:`Specifically, the following changes were made based on the original approach: Most of the os.sleep() related to the event scheduling method were deleted. Due to the simplicity of the simulation process, the event scheduling method related to loading and unloading operations is retained to optimize resource utilization. +Set a global simulation clock and change the idea of the Agv:Move() function from "executing tasks and refreshing the scene at a fixed step size" to "monitoring changes in the simulation clock duration, executing tasks based on the duration changes, and refreshing the scene". +Added simulation speed adjustment. From the above changes, it can be seen that the core of the simulation has shifted from event tasks to the simulation clock. In this, the part of scene refreshing is implemented using os.clock().`},{header:"Example of Master Clock Advancement Method",slug:"example-of-master-clock-advancement-method",content:`Below is a simple example of the dominant clock driving method and the os.clock() function, modified from the built-in block rotation example in MicroCityWeb. +local obj = scene.addobj('box') -- Initial position +local x = 1 +local y = 1 +local z = 0 local rx, ry = 0.1, 0.1 -- Rotation speed in the x and y directions +local simspeed = 10 -- Simulation speed local t = 0 -- Global simulation clock +local t0 = os.clock() -- Record the start time of the simulation +while scene.render() do local dt = os.clock() - t0 -- Calculate the time difference since the last recorded time t = t + dt -- Move the simulation clock forward by the corresponding time difference -- Set the current rotation position of the block x = x + rx * dt * simspeed y = y + ry * dt * simspeed obj:setrot(x, y, z) t0 = os.clock() -- Record the simulation time +end +Explanation: When the simulation speed simspeed is 1, it means that the simulation clock is moving at the same speed as the real-world clock. simspeed can be considered as an acceleration factor. +dt represents the time difference between two recorded times, and the time step in the simulation is calculated as dt * simspeed. +Info +It should be noted that the value of the time increment dt is generally not the same in each loop cycle, and the specific value of dt generally depends on the computational power of the computer. Tips +Sometimes there is not much time-consuming operation between two recorded times, and the calculated dt may be 0. Generally, there is a scene.render() between two time recordings, which usually ensures a non-zero time difference between the two samples. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/tools.html",title:"Tools",pathLocale:"/en/",contents:[{header:"Tools",slug:"tools",content:`Possible tools that may come in handy: MapShaper - a map editor tool. It allows you to edit .geojson files and export them as .shp files. +Three.js Editor - an online 3D object editor for Three.js. 🔨 Work In Progress... This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/versions.html",title:"Versions of MicroCity",pathLocale:"/en/",contents:[{header:"Versions of MicroCity",slug:"versions-of-microcity",content:""},{header:"MicroCity",slug:"microcity",content:"When MicroCity software was initially launched, there was only a desktop version available, which could only run on Windows operating systems. Over time, the developer (@mixwind) realized that this limitation prevented many potential users from using the software because they might be using other operating systems such as MacOS, Linux, and others."},{header:"MicroCityWeb",slug:"microcityweb",content:`🎯Visit MicroCity Web 📍(Offline version) Download +To address this issue, the developer decided to develop MicroCityWeb, which is a version that can be directly run in a web browser. MicroCityWeb does not require any installation, just access its website using a modern browser such as Google Chrome or Microsoft Edge. Although running in a browser may cause some performance loss compared to the desktop version, it allows users to use the software on almost any operating system, such as Windows, MacOS, Linux for computers, and Android for mobile devices and tablets. +Although MicroCityWeb has been developed by the creators of MicroCity, you can still continue to use the previously developed desktop version of MicroCity. However, the desktop version will no longer receive updates for new features. All new features and improvements will be focused on the MicroCityWeb version. This decision aims to ensure that MicroCity can focus on one version and provide the best possible experience in that version. It also makes it easier to manage and maintain MicroCity, avoiding version control issues. +It should be noted that although the desktop version will no longer receive updates for new features, it can still be used. If users are already accustomed to using the desktop version, they can continue to do so. However, if users want to experience the latest features and improvements, they will need to switch to the MicroCityWeb version. +The MicroCityWeb version also provides an offline version packaged for browsers (see link above 🔗link). Note +However, due to updates to the Chromium browser engine, certain outdated system versions may not be supported (such as Windows versions 8.1 and below, 32-bit Windows operating systems, etc.).`},{header:"Compatibility",slug:"compatibility",content:`Due to the use of experimental JavaScript functions, MicroCityWeb may have compatibility issues running on the following browser engines: Most browsers on iOS and iPadOS (due to Apple's requirement to use Safari's browser engine) +Firefox browser Compatibility issues and some technical details encountered during testing on 29th September 2023 iOS and iPadOS: Unable to open local files (due to the use of showOpenFilePicker() method) Firefox: Unable to open local files (due to the use of showOpenFilePicker() method) Regarding the impact of the showOpenFilePicker() method, please refer to MDN Web Docs | showOpenFilePicker().`},{header:"Summary",slug:"summary",content:`The launch of MicroCityWeb version makes the software more user-friendly and popular, benefiting a wider range of users. At the same time, the MicroCity desktop version is still available, allowing users who are accustomed to this version to continue using it and facilitating their transition to the MicroCityWeb version. +At the time of writing this note, the MicroCityWeb is being used for the first time in a teaching environment and is able to function properly and provide certain simulation capabilities. The author's learning experience with MicroCity is as follows: MicroCity (desktop version): Logistics information management +MicroCityWeb: Logistics system simulation The content of this note is for reference only. If there are any discrepancies in the content due to time factors, you are also welcome to make corrections to the content of this note on Github through a Pull Request 🥳. Please check the Pull Request for further details. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/visualization.html",title:"Visualization of Results",pathLocale:"/en/",contents:[{header:"Visualization of Results",slug:"visualization-of-results",content:"This article introduces various methods for visualizing computational results. This includes changing the color of the content, changing the size of shapes, and changing the attribute labels displayed for elements."},{header:"Changing Shape Color",slug:"changing-shape-color",content:`In the graphic properties box located at the bottom left corner of the program interface, the type of color displayed can be changed by modifying the Type attribute under the Colors section. There are 3 options available: Unique Symbol: Specifies a specific color for all graphics in the same layer, which will not be discussed further here. +Lookup Table: Displays the corresponding color based on a numerical query from a table. +Graduated Color: Sets a gradient color based on the numerical values in the table.`},{header:"Lookup Table - Changing Color Based on Table Values",slug:"lookup-table-changing-color-based-on-table-values",content:"By changing the Type attribute to Lookup Table, the color of the graphics can be modified based on the values in the table, achieving the effect of selecting specific graphics. In this example, the Attribute of Lookup Table is changed to SELECT in order to control the color of lines based on the values in the SELECT column of the table (as shown in the above image of attribute settings). When the value is 0, the color is displayed as black, and when the value is 1, the color is displayed as red. The values in the SELECT column of the table and the specific settings in the Lookup Table are shown in the following images. The final effect achieved is shown below."},{header:"Graduated Color - Displaying Gradient Color Based on Values",slug:"graduated-color-displaying-gradient-color-based-on-values",content:"By changing the Type attribute to Graduated Color, different colors can be displayed based on the varying numerical values in the table, achieving the effect of displaying a gradient color. In this example, a gradient color is displayed based on the population size of each country. It can be observed that China has a large population, hence the color displayed is red, while India also has a significant population, resulting in an orange color. Other regions have smaller populations, but differences can still be discerned through the colors. The Colors attribute under Graduated Color can also be adjusted with other color schemes. The settings interface is shown in the following image, but each individual setting will not be listed here. If interested, the manual can be referred to for example 2.1 Showing a World Map to manually experiment with changing this attribute."},{header:"Changing the Display Size of Shapes and Labels",slug:"changing-the-display-size-of-shapes-and-labels",content:""},{header:"Selection of Reference System",slug:"selection-of-reference-system",content:`There are 2 reference systems for displaying the size of content: one based on the map and one based on the screen. In this case, both the size of shapes and the display of labels are set to the same reference system. +When content is displayed based on the map, the size of the content will be synchronized and scaled according to the size of the map, as shown in the following images: (Enlarging the content based on the map) (Shrinking the content based on the map) When content is displayed based on the screen, the size of the content remains relatively consistent regardless of the map scaling, as shown in the following image: (Enlarging the content based on the screen) +Translate into English: (Shrunk with the screen as the reference system) Therefore, when drawing, the reference system should be selected according to the purpose of the drawing. If you need to draw shapes with a specific size or label with a specific size on a map, such as drawing a circle with a radius of 10 km, you should use the map as the reference system. +If you only need labels and graphics to be displayed clearly at any size, you can choose the screen as the reference system.`},{header:"Application examples of reference system",slug:"application-examples-of-reference-system",content:"Draw dots in the picture, set the radius of the circle to be the same as the size of the circle, and set the center of the circle to be the center of each green dot. The size of the gray circle represents the coverage range of each green dot. In the picture, the gray circle is drawn for each green dot with a radius of 16, representing the coverage range of each green dot. These gray circles are stored in a layer called Range.shp, and the layer type is Points."},{header:"Setting the reference system",slug:"setting-the-reference-system",content:`The size reference system for graphics and labels can be set in the bottom left corner of the program interface. The two positions marked in the picture can adjust the size reference system for graphics and the size reference system for labels respectively. Setting the size reference system for graphics: Adjust the size reference system for graphics under the Size column in the Size relates to... section. Adjust the Default Size to adjust the size of the graphics relative to the coordinate system. +Setting the size reference system for labels: Adjust the size reference system for labels under the Labels column in the Size relates to... section. Adjust the Default Size to adjust the size of the labels relative to the coordinate system.`},{header:"Changing the displayed labels",slug:"changing-the-displayed-labels",content:""},{header:"Manually changing the displayed labels",slug:"manually-changing-the-displayed-labels",content:`The size reference system for graphics and labels can be set in the bottom left corner of the program interface. The labels displayed in the picture above are ID. If you need to change it to other columns in the table, you can change the Attribute property under the Labels column to achieve it. +The position to be changed is shown in the picture. If you need to display the value in the corresponding MSG column in the table, you only need to change the Attribute property value under the Labels column to MSG. However, every time the graphics are changed and the Update() function is executed, the label will be hidden. If the script to be executed contains the Update() function for this layer, there is no need to manually reconfigure the displayed labels after each script execution. The displayed labels can be automatically selected through the script.`},{header:"Automatically changing the displayed labels",slug:"automatically-changing-the-displayed-labels",content:`The value of an attribute can be changed using the SetParameter() function. Taking the Attribute property under the Labels column in the picture above as an example, you can see that its ID is LABEL_ATTRIB and its type is Choice in the bottom bar. It should be noted that when the type is Choice, the parameter values are numbered starting from 1 and the numbering corresponds to the contents of the drop-down menu in order. After clicking on this property, you can see that MSG is in the second position. Since the numbering in Lua usually starts from 1, the number for ID here corresponds to 1, and the number for MSG corresponds to 2. The object to be operated on is MSG, so the function needs to fill in the parameter value of type Choice as 2. +Now that all the required parameters have been obtained, the SetParameter() function can be used to change the displayed labels. +-- transports is the graphic layer +SetParameter(transports, "LABEL_ATTRIB", 2) The SetParameter() function needs to be executed after the Update() function, otherwise the effect will be overwritten by the Update() function. Now let's take a closer look at the specific usage of the SetParameter() function: +SetParameter(Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object) Parameter +Meaning Parameter1 +The input object, which can be Shapes, Table, Grid, Scene, or Module Parameter2 +The id corresponding to the attribute. In the previous context, it is LABEL_ATTRIB Parameter3 +If you need to change the attribute value, it only accepts three types: Number, String, and Object The introduction of the SetParameter() function can be found in the 4.2 User Interface Control document, please refer to it.`},{header:"Using Raster Grids",slug:"using-raster-grids",content:`Raster grids can also be used for visualization, and I believe the most common application of raster grids is to draw heat maps. The generation of a heat map is mainly achieved by modifying the value of each cell on the raster grid. If you are not familiar with the specific structure of raster grids, you can refer to the 3.3 Raster Grids document. For controlling raster grids using scripts, you can refer to the 4.4 Grids document. +One scenario of using raster grids to draw heat maps is plotting price maps. When plotting a price map, we can iterate through each grid point on the raster grid, calculate the sum of distances from that grid point to each warehouse, and set the value of that grid point to this sum. This way, we can obtain a heat map. This method helps us visualize the distribution of prices and discover the trends and patterns of prices. This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/warehouse-simulation.html",title:"Ideas for Warehouse Automation Simulation",pathLocale:"/en/",contents:[{header:"Ideas for Warehouse Automation Simulation",slug:"ideas-for-warehouse-automation-simulation",content:"The ideas in this article are for reference only and it is recommended to make appropriate improvements."},{header:"Specific Problem: Warehouse Simulation based on Cellular Automata",slug:"specific-problem-warehouse-simulation-based-on-cellular-automata",content:`In this problem, the locations of inbound and outbound can be changed, and the forklift is an AGV. +In other words, this is actually a cellular automata simulation of a mobile rack warehouse. The AGV can pass through the bottom of the rack, move to the bottom of the rack, lift the rack, and transport it to the inbound/outbound point.`},{header:"Basic Assumptions",slug:"basic-assumptions",content:`All items on the racks are the same. +Only one item is placed on each rack. Therefore, outbound and inbound can be considered as completely opposite processes, so here we only need to discuss the outbound case in detail. It is assumed that there is already an item on the rack by default.`},{header:"Overall Implementation Idea",slug:"overall-implementation-idea",content:`Assign (x,y)(x, y)(x,y) coordinates to each cell in the entire 3×33\\times33×3 warehouse to facilitate subsequent movement operations. +With AGV as the core, operate the racks. When the AGV is in the lifted state and moves the rack, you only need to synchronize the coordinate position of the rack with the position of the AGV to achieve the effect of AGV moving the rack.`},{header:"Business Process",slug:"business-process",content:"Randomly generate the order list according to the required quantity, and the AGV moves the racks to the outbound point in order based on the order list."},{header:"Business Logic",slug:"business-logic",content:`When performing outbound, the AGV first finds the nearest rack and moves to the position of that rack, lifts the rack. For the rack (AGV), set the destination for movement and calculate the difference in Manhattan distance. Before each movement, determine the direction of rack movement (xxx or yyy direction) by checking for obstacles. +If both directions are blocked, prioritize the yyy direction (as specified) and recursively move away the obstacles in this direction to make space for the rack to move. If there is no space in the yyy direction, then move in the xxx direction.`},{header:"Process Optimization: About the Old Method and the New Method",slug:"process-optimization-about-the-old-method-and-the-new-method",content:`Both of these methods are viable, but the new method optimizes for specific scenarios by reducing the number of steps through obstacle prediction. See the problem in the figure below: +Old Method: No Obstacle Prediction (Inbound and outbound points are at position x=3,y=3x=3,y=3x=3,y=3) 👉 After the AGV completes the outbound operation for the first rack and moves towards the second rack, it finds that the first rack blocks the way, so it goes back to move the first rack away, and then proceeds to do the outbound operation for the second rack. +New Method: Obstacle Prediction (Inbound and outbound points are at position x=3,y=3x=3,y=3x=3,y=3) 👉 After the AGV completes the outbound operation for the first rack, it checks if other racks need to be moved before it can reach the inbound/outbound point. If necessary, it moves the obstructed racks and then proceeds to do the outbound operation for the next rack. Info +In line with the principle of minimizing the occupation of the inbound/outbound points, when there is an empty space, the AGV will move the rack at the inbound/outbound point. Therefore, some seemingly redundant operations are not without comprehensive considerations. Optimal layout schemes for different numbers of racks (animated graphics) +The case with 8 racks has already been shown above. Here, we only show the cases with 5 and 7 racks from the table. For other cases, please refer to the appendix.`},{header:"Collection and Analysis of Simulation Data",slug:"collection-and-analysis-of-simulation-data",content:""},{header:"Maximum Inbound/Outbound Efficiency",slug:"maximum-inbound-outbound-efficiency",content:`The simulation results are shown in the figure below, representing the layout of racks with the best efficiency for the same number of racks. Optimal rack layout: For the same number of racks, the layout with the minimum number of operations (ticks) to retrieve all items. Explanation of the Layout Diagram White: No rack is placed. +Light gray: Rack, but the AGV is initially positioned below this rack. +Gray: Rack. Explanation of the Table Rack Quantity: Number of racks in the layout diagram. +Old Ticks: Number of operations to retrieve items using the old method (no obstacle prediction). +New Ticks: Number of operations to retrieve items using the new method (with obstacle prediction). The new method will be explained later. +Highlighted in yellow: Scheme with the minimum number of operations (minimum ticks) in the same layout.`},{header:"Maximum Space Utilization",slug:"maximum-space-utilization",content:`If all positions are filled with racks, it will not be possible to access all racks. Therefore, the method with the highest space utilization is to place 8 racks. +Color Indications Green: Rack with items. +Purple: Rack without items. +Light purple: Rack lifted by the AGV. +Dark purple: AGV below this rack, but the rack is not lifted. +Dark gray: Inbound/outbound points. Sometimes, when the refresh rate is too fast, it may not be possible to see the rack being lifted by the AGV. The entry and exit points are located at position x=2, y=3.`},{header:"Innovations",slug:"innovations",content:`Additional consideration for different types of goods. +Each simulation generates demand based on the random arrangement of goods on the shelves. +Object-oriented programming. Using an object-oriented approach helps in abstracting the problem and improving the flow of the process. Good naming conventions make the program's logic and flow clear, ensuring that you won't forget everything after a night's sleep 😂 Different types of goods are represented by different colors. The meaning of AGV state colors, empty shelf colors, and entry/exit point colors remains the same. Purple: Shelf without goods +Light purple: Shelf lifted by AGV +Dark purple: AGV is positioned beneath the shelf but hasn't lifted it +Dark gray: Entry/exit point Example with 5 shelves: Example with 8 shelves:`},{header:"Simulation Enhancement: 3D Automated Warehouse Simulation",slug:"simulation-enhancement-3d-automated-warehouse-simulation",content:"In this part, the question has slightly changed. The requirement is to add a third dimension to the cellular automaton warehouse simulation and create a simulation of an automated warehouse. The specific requirement is shown in the image above."},{header:"Overall Approach",slug:"overall-approach",content:""},{header:"Adding the Third Dimension",slug:"adding-the-third-dimension",content:`Based on the core of the Cellular Automaton-based Warehouse Simulation, the part of the simulation that uses cellular automata will be rewritten as an internal data table to serve as an internal data model, monitoring and controlling the state of the entire simulation process. +Since the Cellular Automaton-based Warehouse Simulation uses an object-oriented approach to encapsulate objects, and object methods are extensively used in building the business logic and flow, only the object methods need to be rewritten (e.g., Agv:Move(dx, dy)) to achieve the transition from cellular automaton simulation to 3D automated warehouse simulation. If the overall program structure is well-designed, applying "object-oriented" techniques will significantly improve maintainability and reduce the difficulty of migration. The AGV and shelf models can be directly reused. For the goods, you only need to set the relative height list from the shelves to achieve automatic placement of goods at the specified height. Tips +If you need to reuse existing models, or if you want to upload models to the repository maintained by the author of this document, please refer to the documentation on 3D Objects - External Models.`},{header:"Significant Fluctuation in the Demand for Inbound and Outbound Goods",slug:"significant-fluctuation-in-the-demand-for-inbound-and-outbound-goods",content:`According to the requirements, there are basically only two scenarios: 3 shelves and 6 shelves. +Since the number of shelves is limited and the Cellular Automaton-based Warehouse Simulation has obtained the best layout for warehouse performance, the corresponding optimal layouts for the respective number of shelves can be directly reused. In this problem, only the placement of goods in fixed shelf layouts needs to be considered. +For the case of 3 shelves, the optimal layout is a symmetrical configuration in terms of height, with a distance of 1 from the entry/exit point. Therefore, only one scenario needs to be simulated, and the data collected from it. +For the case of 6 shelves, three scenarios were selected for multiple simulations to obtain the average, maximum, and minimum Ticks consumed by each scenario for inbound and outbound operations. Ticks represents the number of times the AGV moves and serves as a unit of operation time. Further improvements are mentioned in the following section: Areas for Enhancement. Based on the above analysis, since there are limited scenarios, the best layout for goods can be determined by simulating the placement of goods at various positions, randomizing the types of demanded goods while keeping the total demand constant, and analyzing the obtained data.`},{header:"Enhancements",slug:"enhancements",content:`During testing, it was found that the original strategy of moving shelves was not reasonable. Therefore, the shelf movement strategy was improved. +Old Strategy: Find the shelf closest to the AGV that contains the requested goods and move it to the entry/exit point. As seen in the animation, the AGV has moved the shelf containing the required goods (represented by blue blocks) to the entry/exit point. However, because the AGV moves the shelf adjacent to the one with the requested goods, it doesn't perform the outbound operation on the goods already at the entry/exit point. +New Strategy: Find the shelf closest to the entry/exit point that contains the requested goods and move it to the entry/exit point. By changing the strategy, the aforementioned issue has been resolved.`},{header:"Innovation",slug:"innovation",content:`Due to the large number of tests, the main process is written into a function for adaptive improvement, achieving automatic simulation tests for all cases and outputting data. The following figure is an example of running the automatic simulation test. Code for the automatic simulation test process, for reference only: +-- Batch test +local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- Test demands (upper limit) sequence local output_string_list = {} -- List of test result strings +for k, v in ipairs(cargo_ubs) do local test_result = {} -- Test result sequence for this demand upper limit cargo_ub = v -- Set the quantity upper limit for j = 1, test_count do scene.setenv({ grid = 'plane', clear = true }) -- Clear the scene print("Test (", j, "/", test_count, "): Demand quantity is", cargo_ub) local tick = ModelRun() -- Run the simulation model and return the test result table.insert(test_result, tick) -- Insert the test result into the test result sequence end local output_string = "" print("Test result sequence for demand quantity", cargo_ub, ":") for i = 1, #test_result do -- Output the test result sequence to the list string output_string = output_string .. test_result[i] .. "\\t" end print(output_string) table.insert(output_string_list, output_string) +end -- Output the list of test results +for i, str in ipairs(output_string_list) do print("Test result sequence for demand quantity", cargo_ubs[i], ":", str) +end +A bug was discovered during the automatic simulation test process, as described in the following text.`},{header:"Shelf Layout Scheme",slug:"shelf-layout-scheme",content:`Color Legend Light Blue: Inbound and outbound points +White: Empty space +Dark Blue, Red, Yellow: Colors corresponding to 3 types of goods Assumptions Each shelf contains 2 items of the same type +Random demand for goods, no preference for type +Only one item is taken out at a time`},{header:"Simulation Results and Analysis",slug:"simulation-results-and-analysis",content:"Simulate and test each quantity scenario in the layout scheme for each item 30 times, and calculate the maximum, minimum, and average values of the results for each scenario. The final conclusion is that in the case of 6 shelves, Layout Scheme 2 performs the best."},{header:"Scheme 3: 3 shelves",slug:"scheme-3-3-shelves",content:""},{header:"Scheme 6",slug:"scheme-6",content:'Trend in Average Ticks for Scheme 6 Optimal layout scheme for Scheme 6: Scheme 2 Trend graph of "Demand Quantity - Shortest Average Service Time" for each sub-scheme should also be plotted. Taking Scheme 6-1 as an example, the x-axis represents the quantity of goods demanded, and the y-axis represents the shortest average service time (Ticks).'},{header:"Improvement Space",slug:"improvement-space",content:`Since the specific execution time of the event is not given in the title, and the time unit is not specified, we only measure the number of operations on the shelves as the time cost. In other words, the time is calculated afterwards, and I think most of the students might have the same idea at this point. Although there is no problem with the final result, the idea can be changed to adapt to later studies. +The current approach is task-driven. Although it can obtain the correct result, it does not make use of simulation time. This approach does not have any issues when controlling only one entity. However, when dealing with multiple entities simultaneously, the current approach cannot handle the situation where multiple entities complete tasks at the same time, and can only achieve the situation where multiple entities complete tasks one after another. The specific process of the current approach is as follows: +Since the time advance method is used, the simulation world has its own time. For us, we can control the simulation speed by multiplying a multiplier on the simulation time, which is the simulation speed. In addition, this approach is more flexible in supporting multiple objects. The specific process is as follows: +This way, the simulation is changed to be time-centric, and the progress of all entities in the scene can be refreshed directly when refreshing the task execution progress. Since the simulation is time-centric, it is necessary to set the rate/time of various operations to ensure the accuracy of time calculation. In MicroCityWeb, there are some techniques that can be used for time advance simulation.`},{header:"Update simulation time with system time",slug:"update-simulation-time-with-system-time",content:`The os.clock() function can get the current system time (in seconds, but in decimal). With this function, synchronization between simulation time and real time can be achieved. Usage examples can be found in Time Lapse (Chinese only). +Since time is the core of the entire simulation, it is necessary to specify the time required for operations that were not previously defined. In the improved part, the additional time required for the following operations is considered: Time required for goods to enter and leave the storage +Time required for the AGV to lift and lower the shelves This post is translated using ChatGPT, please feedback if any omissions.`}]},{path:"/en/notes/web-ui.html",title:"Introduction to the User Interface",pathLocale:"/en/",contents:[{header:"Introduction to the User Interface",slug:"introduction-to-the-user-interface",content:"The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb."},{header:"Overview of Interface Zones",slug:"overview-of-interface-zones",content:`Overall, the interface of MicroCityWeb can be roughly divided into four areas: Top - Blue Area: performs various operations on code and files +Left - Green Area: code editor +Right - Red Area: view area +Bottom - Yellow Area: output information, recognize program running status Next, we will provide a detailed description of the usage and functions of these areas.`},{header:"Blue: Command Area",slug:"blue-command-area",content:"The content of this area is shown in the following figure, with nine available buttons."},{header:"Program Control",slug:"program-control",content:"The first three buttons are mainly used to control program execution. Their specific functions are as follows: Run/Debug: Clicking the left mouse button will run the code in the code editor on the left-hand side of the webpage, while right-clicking will debug the code. Pause: If the program is running, clicking this button will pause its execution (if supported). Stop/Force Stop: If the program is running, clicking the left mouse button will stop its execution. If left-clicking does not stop the script, right-clicking can forcibly terminate its execution."},{header:"Code Editing",slug:"code-editing",content:`Buttons 4-7 are mainly related to code editing. Show/Hide Editor: If the left code editor is open, clicking this button will close it. If it's closed, clicking it will reopen it. If you right-click, the editor can be expanded to full screen. Open Built-In Code: You can directly load built-in code (import built-in models), such as cubes, trucks, earth, world maps, etc. The specific models will be introduced in detail when the red canvas area is introduced. Built-in code list Open Local Code: +Left-click: A dialog box will pop up when you left-click, and you can choose a code file (.lua) on your local machine. After confirming the selection to open the file, the text of the code file will be automatically imported into the code editor on the left. +Right-click: You can select one or more files to upload to MicroCityWeb by right-clicking. The "Save" button (⑦) on the right can be clicked to view the list of uploaded files. Save Code: +Left-click: When you save a file for the first time, a save file dialog box will pop up after you click the save button. You can choose the save location and fill in the file name. If you have previously saved the file locally and you have made modifications to the file and want to save the changes, you can simply click the save button to save the changes directly to the previously saved file. +Right-click: You can view the list of uploaded files, and you can click on a file in the list and download it to your local machine.`},{header:"Others",slug:"others",content:`Share. After clicking the button, a dialog box for entering a password will pop up. Afterwards, you will receive a link that anyone can use to access your share. +If you enter a password in the dialog box, others who open the link can only run your program code and observe the running result, but cannot view your code (unless you tell them the password); if you do not enter a password, others can not only run your code to view the running result but also view the code you have written. View help documentation.`},{header:"Green: Code Editor",slug:"green-code-editor",content:"The integrated code editor on the left side of MicroCityWeb is based on AceEditor and therefore has some of its features."},{header:"Keyboard Shortcuts",slug:"keyboard-shortcuts",content:`Below are some commonly used keyboard shortcuts to help you edit code more efficiently. +Most Common +Ctrl+Z: Undo +Line Operations +Ctrl+D: Delete a line +Ctrl+Shift+D: Duplicate a line +Alt+↑: Move line of code up +Alt+↓: Move line of code down +Find Content +Ctrl+K: Find the next occurrence of selected content in the code +Indentation +Ctrl+[: Increase code indentation +Ctrl+]: Decrease code indentation +Modify Values +Ctrl+Shift+↑: Increase the numeric value before the cursor by 1 +Ctrl+Shift+↓: Decrease the numeric value before the cursor by 1`},{header:"Red: Canvas area",slug:"red-canvas-area",content:`Built-in code can be imported into the scene, see Command Area - Code Editing for details. +After importing the scene code, click the "Run" button to load the scene. Built-in car model Built-in Earth model`},{header:"Scene Operations",slug:"scene-operations",content:`Scene operations, including viewpoint movement and rotation, need to be performed in the canvas area. Therefore, the following will introduce the basic operations of the canvas area. Zooming in and out of the scene: Scroll the mouse wheel up to zoom in and down to zoom out. +Translation: Hold down the right mouse button and drag. +Rotation Scene rotation: Hold down the left mouse button and drag to rotate from your viewpoint. +Object rotation: Click on the object, the color of the object changes, and then hold down the left mouse button on the object to rotate around the object's center. These operation rules apply to both two-dimensional and three-dimensional objects.`},{header:"Yellow: Code Output Area",slug:"yellow-code-output-area",content:`After opening MicroCityWeb, the code output area is shown below. Clicking on the code output area will cause the entire area to move up, allowing you to see more historical output information. Regarding the information output in this area, the code output area will output the following information: Script output: The left side is the output of the script, including the output time and content. +Script running status: The first line on the right side shows the script running status. "state: ready" indicates that the script is ready to start running (not yet running), and "state: running" indicates that the script is running. +MicroCityWeb version number: Indicates the current version number of MicroCityWeb being used. If there is a difference from the known version, you can force a refresh to load the latest version.`},{header:"Notes",slug:"notes",content:"Turn off automatic translation: If your operating system language is not English and the browser has automatic translation enabled, it needs to be manually disabled, otherwise there will be errors when running the code."}]},{path:"/images/doc/",title:"",pathLocale:"/",contents:[{header:"",slug:"",content:"This folder contains images used by documentation pages."}]},{path:"/404.html",title:"",pathLocale:"/",contents:[]}],F="update-vuepress-plugin-full-text-search2-search-index";var C=b(V),q=j(()=>{const e=new Map;for(const t of C.value)e.set(t.path,t);return e});import.meta.webpackHot&&(__VUE_HMR_RUNTIME__[F]=e=>{C.value=e});function W(e){const t=b([]);let s=null;return L(e,()=>{s&&clearTimeout(s),s=setTimeout(i,100)}),t;function i(){const c=e.value.toLowerCase().trim();if(!c){t.value=[];return}const a=new Map,n=new Set;for(const o of C.value)for(const r of B(o,c)){n.add(r.parentPageTitle);let l=a.get(r.parentPageTitle);l||(l=[],a.set(r.parentPageTitle,l)),l.push(r)}const d=[...n].sort((o,r)=>{const l=a.get(o);return a.get(r).length-l.length});t.value=[...a].flatMap(([,o])=>o).sort((o,r)=>o.parentPagePriority-r.parentPagePriority||d.indexOf(o.parentPageTitle)-d.indexOf(r.parentPageTitle)||o.priority-r.priority)}}function*B(e,t){const s=S(e.title,t);if(s){yield{path:e.path,parentPageTitle:w(e),title:e.title,display:s,page:e,content:null,parentPagePriority:1,priority:1};return}for(const i of e.contents){const c=S(i.header,t);if(c){yield{path:e.path+(i.slug?`#${i.slug}`:""),parentPageTitle:w(e),title:e.title,display:c,page:e,content:null,parentPagePriority:10,priority:2};continue}const a=S(i.content,t);a&&(yield{path:e.path+(i.slug?`#${i.slug}`:""),parentPageTitle:w(e),title:e.title,display:[{type:"header",str:`${i.header} +`},...a],page:e,content:null,parentPagePriority:10,priority:10})}}function w(e){const t=e.path.split("/");let s="/";return t[1]&&(s=`/${t[1]}/`),(q.value.get(s)||e).title}function S(e,t){const s=[];let i=0;const c=e.toLowerCase().replace(/\s/gu," ");let a=0,n=c.indexOf(t,a);if(n<0)return null;for(;n>=0;){const o=n+t.length;if(d(e.slice(a,n),"normal"),d(e.slice(n,o),"highlight"),a=o,n=c.indexOf(t,a),i>100)break}return d(e.slice(a),"normal"),s.filter(o=>o.str);function d(o,r){let l=o;r==="normal"&&l.length>100&&i===0&&(l=`… ${l.slice(-10)}`);let m=!1;if(i+l.length>100){if(s.some(g=>g.type==="ellipsis"))return;l=l.slice(0,Math.max(100-i,1)),m=!0}s.push({type:r,str:l}),i+=l.length,m&&(s.push({type:"ellipsis",str:" …"}),i+=2)}}var U={"/":{placeholder:"搜索"},"/en/":{placeholder:"Search"}};const H=U,Y=D({name:"SearchBox",props:{locales:{type:Object,required:!1,default:()=>H}},setup(e){const{locales:t}=I(e),s=b(""),i=b(!1),c=b(-1),a=W(s),n=j(()=>s.value&&i.value&&a.value.length),d=_(),o=z(),r=j(()=>t.value[o.value]??{});function l(){if(!n.value)return;let h=c.value-1;h<0&&(h=a.value.length-1),g(h)}function m(){if(!n.value)return;let h=c.value+1;h>=a.value.length&&(h=0),g(h)}function g(h){c.value=h}function P(){c.value=-1}function A(h){if(!n.value)return;const k=a.value[h];k&&d.push(k.path)}return{query:s,focused:i,focusIndex:c,suggestions:a,activeSuggestion:n,onUp:l,onDown:m,focus:g,unfocus:P,go:A,locale:r}}}),X={class:"search-box",role:"search"},$=["placeholder"],Z=["onMousedown","onMouseenter"],Q=["href"],J={key:0,class:"parent-page-title"},K={class:"suggestion-row"},ee={class:"page-title"},te={class:"suggestion-content"};function ne(e,t,s,i,c,a){return u(),p("div",X,[N(f("input",{ref:"input","onUpdate:modelValue":t[0]||(t[0]=n=>e.query=n),"aria-label":"Search",class:y({focused:e.focused}),placeholder:e.locale.placeholder??"Search",autocomplete:"off",spellcheck:"false",onFocus:t[1]||(t[1]=()=>e.focused=!0),onBlur:t[2]||(t[2]=()=>e.focused=!1),onKeyup:[t[3]||(t[3]=x(n=>e.go(e.focusIndex),["enter"])),t[4]||(t[4]=x((...n)=>e.onUp&&e.onUp(...n),["up"])),t[5]||(t[5]=x((...n)=>e.onDown&&e.onDown(...n),["down"]))]},null,42,$),[[R,e.query]]),e.activeSuggestion?(u(),p("ul",{key:0,class:"suggestions",onMouseleave:t[7]||(t[7]=(...n)=>e.unfocus&&e.unfocus(...n))},[(u(!0),p(T,null,M(e.suggestions,(n,d)=>(u(),p("li",{key:d,class:y(["suggestion",{focused:d===e.focusIndex}]),onMousedown:o=>e.go(d),onMouseenter:o=>e.focus(d)},[f("a",{href:n.path,onClick:t[6]||(t[6]=E(()=>{},["prevent"]))},[n.parentPageTitle&&(!e.suggestions[d-1]||e.suggestions[d-1].parentPageTitle!==n.parentPageTitle)?(u(),p("div",J,v(n.parentPageTitle),1)):G("v-if",!0),f("div",K,[f("div",ee,v(n.title||n.path),1),f("div",te,[(u(!0),p(T,null,M(n.display,(o,r)=>(u(),p("span",{key:r,class:y(o.type)},v(o.str),3))),128))])])],8,Q)],42,Z))),128))],32)):G("v-if",!0)])}const ie=O(Y,[["render",ne],["__scopeId","data-v-fd6cd4d5"],["__file","SearchBox.vue"]]);export{ie as default}; diff --git a/assets/Subplot_Vertical-oXTmfxKU.js b/assets/Subplot_Vertical-oXTmfxKU.js new file mode 100644 index 00000000..6b4fe5fa --- /dev/null +++ b/assets/Subplot_Vertical-oXTmfxKU.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/Histogram-hCqM-8K4.png",t="/MicroCityNotes/assets/Subplot_Vertical-X1t_RUlM.png";export{s as _,t as a}; diff --git a/assets/add_field-ZFhY51wb.js b/assets/add_field-ZFhY51wb.js new file mode 100644 index 00000000..f1cc9a4d --- /dev/null +++ b/assets/add_field-ZFhY51wb.js @@ -0,0 +1 @@ +const A="/MicroCityNotes/assets/new_table-Elg2D_3m.png",P="/MicroCityNotes/assets/table_menu-enNFenIu.png",n="/MicroCityNotes/assets/table_view_menu-1OnsnofR.png",f="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfgAAAEsCAMAAAAYWVF0AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAHjUExURfHx8a2trScnJwB412RkZGlpaXBwcP///8jIyOHh4QAAAP/bkGtra9v//zo6kLb//5Db/+HBfwA6kDoAZv//2/+2ZoCAgMHh4f//tn/B4Wa2/6Dh4ZA6ADMzfzoAAJA6OrZmAOHhoMzMzOHhwQAAOuGgWjqQ2wBmtl1dXQAAZjMAWmYAZsF/M1qg4dvbkGYAOjN/wQAzf9uQOoCZsX8zAABaoGYAAH8zM7GZgAUHCAAAWgAAM6BaADMAAICNpr3IyKa9yICAjcjIsZmAgFoAAMjIvSYmJqaNgI2mvVoAM72mjToAOsixmZmxyJBmAMi9po2AgDMAM1oAWoCAmbZmZtv/ttv/27HIyFFRUbbbkMHhwVozM2ZmZiUlJTpmZgAzWgA6ZmY6Oj09PVBQUCQkJG5ubm9vb6BaWtuQZjMzWpCQZjo6ZpCQ25CQOj4+PldXV0VHShkZGTs7O1ozf9u2ZrGxmTo6ADo6OmY6AJA6ZlozALb/2y4uLktLS0BAQGVlZU5OTmJiYlxcXFZWVm1tbWNjY0ZGRmFhYWxsbGhoaF9fX42ZsTNaWsGgWn9/wX/BoMF/WrGZjZmNgICNmY2NgKB/M1paMwA6On9aAFp/f8HhoLa2ZpDbtrZmOpC2kGY6kDqQtopAvkwAAA0RSURBVHja7d2JXxvHGcZxt3URWgFCHEIIbAsDkokRAQLYNXLigyS1nfqIE8dO7dROaqeu6yRN0+Zqm973fd/tn9p5Z2ZXWoS4JNjr93wcSWgVe9mvZme1emf2QNce5Pb373eRrfLgwYP793/09lvHPvnxT2/e7Lrd0/POPv7rB7pSJIEBHngCPAGeAE+AJ8AT4En04YcHen33OplL/fZR4Xi2eTEJaZyj5v6o0wJ+aLzSAn5o3HGcgTngI5mjnzvacLcBfOb9wWwr+KLvrwI+evI+dz/8YrlUBD6m8n53H/zQkX4NWViR/Xqvd+/BZ9QOQZ4sa/iGxST88n53H7xSLzzZr0AVckk9tvdeH19W8PIC9S5Q8I2LSaThS2X9n2716sa997X4YUdSVvCNi0mUd/V61+3MZDeHNz8DH6ODu+GZrOgXZR8+NG529XLvg9c7+JeydlfvLiZR/jhXqthbtTuf+qoSde99B3eZw45T1Ad3DYtJtE/gkOQEeOAJ8AR4Elf4n7ERkgn/CzZCMuF/zkagjyfAE+BJPOEPkAQGeOAJ8AR4Em/4gyS02Vv4bhLSAA888MADDzzwwO8O3nHj/Zsn8/n8Uw3rcDL/he7ui76nyH7Cf6YD2QDe/kvu/bPPK+cX8k8/44cncYfX5qJ/7vzZP+Xzn1dtXeX6N1WLP3c+nz97pvvK1T/+QRY07RrIXsGn28x24E9qS3Wr4M/o5q9b/Av5p65cffqZZ58/e+bK1bNnzp2//spFhX/llxhFFt708H74iwJ//ZVuwXXh5bE84b4BTjb2ByRGLV7BK28/vK/l5/Uen8QCvqGP36LF6/cHjT5g+Nyhkc7Ae0f1Ai/9fLfb0s+dd1u6uf+9HOdxcBcU/LTqoOfbgW/1OV6O4eUgXt4K647q3T4+T4MPDH721Fh6Ym1+9/Ato3f1JKTwk0tVafWnxhT8xNryrDR//dz0wgjwMYbPPTGmbicujOYOvbo0r5+5Njq9nE7Xqu22eBIB+LVq7uFH82YfcGJ04sUx9Qf4ZLT4086ydPmOszqars3PLqeBT0gf/4+1qjxQLT6de/jF0V3BR3qYSHecxrzs5Kh+enVUNXTVx6u3w8II8PGGb/wcP7v62zXnS9LYNzy0Az5W8Btl40M74GMPv/GhXRLhM3293m0C4Hd95k5vq8NlM51lJOFlDk5nYM6VBn4H8JceZSMM71/xmMDvRelVM/zgP8uy/RZlpnL14LHjFEvOlMxYL7eRgFfSZm3VA9kHDAC/HfiPP8za7XepX3b8w05Rpip3Z7WPBrxZ20zfjfFi1Fv8PtTV2003XDbbb+hIv2wz89/LcmGSJ/vDDi99fMVb20zfnEy+Dfz24Ic+vKU2l9rXTzXAz8kmneqPSIu3a5vpe2+gF/jtwqeGX1PNfibb1OKjcnDnra16B/QBv334ofGZ7GJF9/EevPSaqZeyEYG3a6veAap3WhwAfnvwcsWSwopz914jvFyUqhKlo3q1turBsOO8RovnlC3wwEcF/lMdCPBRhE+3HeCBp/QqMqVXtHhaPPDAAw/81gMpgY8H/KwptNxT+OiUMnSvX+nYwuvS6m+MdBh+s+IlvUyuOh5l+KEj/VssCMH7ZjP4iQuj9WafO/Q3GUOTnlxynIURdat+2CX85sVL4S3K6hx8yFu8GT5lB0rmTlf1CNmaLrCtzcsP7cC3LF4yX94VU6lhtVe4rL+gD0lNloGXL2fcNbPVY32XZx7rR3rh3Q9kj+b9dpfN7qvkOP8bN7u6yzO3+txfrbASUA3CZvD1kdCTJ0YFWYZK64p6udUjaNuC37h4yXx5V1Gbqpg5XNTfeIakJsvAlyq6SyraVdLVY8WUeWQWmoZtfzuzTB4WvqYXyDNSx6H/gqHxckBVR5vCnxpzD/FWXXizF8iddtzndtnHty5e0vCF41n1R55UryiEpCZLr33huH3b2lW2tSTmkVmofQvub9frwtsFttzI/AXyy4YP3vbxZqCkD96OpGmvxbcoXjKLS+VF/WW33nghqcny76/0f171mH006MFn3N+u1+sgis3w8n4IH7w9qv+zHihp4SeX3D4+/eZYe/Atipfs4kf3+s02GswWQlKT1Qxfrx6zjwZ9Ld5/FLg4cKO5xfeFEl4f0Fcn9EBJC6+P6pftbft9/AbFS3bjjdvdwGJFd5dhqMnqNk23UoevV4+ZR2ahOjpJuSvtwn+lX45bZIEPvrBS1McGiThlu0Xxkv04p7eRPdoPSU1W/ai+knHd3Oox88iuqVrvgfpvZ/p4fXJCFsw1wsvzfw3k82tYz9XrPWXIzo/t0SnbYH7LsMIvVlKJgC8FdZqSb+f4kgb4xMLvfbElCWPpFeXVCW3xwAMPPPDAAw888G3AD7c+Z1GvTTrc9KJMn/cdR5Dwsva35Ju3IvA7bfGti6vq8DJhxvrai6Arl7y1l7XTk7YBv1P4jK08KknBklekNPUtx9Zg6U2rN6/3ssyjD2yRpnnS/SsCgpcvYoHfObypPNIFSQ1FSr4WL3PljNdf5u3qb5gn69VPwcCHep6mELd4rwClsUjJB1/ySnD0yzz4OVuXs+9zz/jhdUEo8LuD1wVJDUVKvoM7pS3iagObl7nw75kng4anxbcBn5KCpJfrRUq+Fm/vzAZeVJ272+IHs2Fo8fTxbcDbgqR6kVKp6IO3fbx+mdRqFRv7+GDh3bpp4Hf0Of6W7eP1p/WGIiVdtNTwiU/9rF6gX2YGXtij+plsKiB4Psdz5g544IF34Q8Cn0z47wKfTPi3Kb1KZulVDy0+mS0eeOCBBx544HeR5vN0QZyyNSmshHpq/eDgv9Nu6ZVs1pL3uqGNq66Cgy+VQzWVUXjgv9dm6ZVclLCwElp4WR/gd7qr31bp1eOivmKRWTjkzhel/ydbj7XvF/rTa28muio5Jk2TWwHfbunVrb7ef/9H6nD0Qm++KD1TlHcXTIuXqS+8Fu+f3Ar4LVv8VqVXHx/513/nzPw3amHDtEHuvDGZfb/QX3d9P+/Br5vcCvjtwbcuvRrMLr5f1rsGvbAR3tZjDQ8EU4ix6K7PRpNbAb89+NQmpVcyq5A345WvxQdaemWmt/K1+FQUJzUOFn6L0quM6eNlxqv6fFFuH1/Y9wv9mYO7itvHbzS5FfA9nSi9MtPa6hmv6vNF9dp6rNS+X+iv2565uXuv393Nr5/cCnhO2QIPPPDAhxK+k5MfAR8l+A5Od9ZD6VUyLzho4VMkmS2eDQw8SQD8O8DHFb75GgWN8D3ARx6+fg0y4IEHPjHwudNyaUl7rVm5+tgC8EmAn1yq2usP5q6Nyg+0+GTAi7O5DJ1cgk49BXwy4KW1S0PXF52UH4BPSIt/Ql9M1nfRSeCT08fP6otOyj5/loO7uMPL9YNPjak7ud6ovuhketpxfrVpi/868HE9c7f5KVtaPPAEeAI8AZ4ED9+xYkvgIwXfuQCfUHg+x9PiCfAEeBJP+DeATyb868An83P8TeCTeebuIPDAE+AJ8CSW8BzcJRSeEzgxgG89Xgr4OMNPrFXT6TfHgE8avB00qYdLSnW9lNdPLskISuBj3uLn3bfAtdHp5XS6Ni9/phlQkYQ+vpo2wyUnXhybuCC3dgQl8PE+qp82Q+PVba2qmroeXLMKfPzhVd9uhkump5dnq2lp8RzcxR1+el737ma4pNrDPxzT3XyLA33gY3Rwp3frdrhkuras9wCOs0yL58wd8MADDzzwwJOEwDOJcbTgO1ZseRv4KMEzoAJ44IFnJA3wjKQBfvO8C3wy4Y8BDzxJ0Od4D56ENnty5s6FJ5EI8MADDzzwwO8Y/rMktNkm/MSav8pu80uTePC0prCmFbyuna/Wf67Nr7/g4KsnRoGPIbxcYuy0pz25Xhn4GMOnp0+Npc0AyZrjrP5FX2bSXoIq9/AjR4ZP1/SlJ4GPF7wMkDMDJG2Lz11zrz1mW7xaNPEb4OMGP7lUtQMkLXz9onN1eHb1sWzxdoCkhtfjJv3wMqamCnwM+3g7QFIPmDSXmTQXlq0f3PkuPQh8PI7qq+4ASYE34yZl6GRtQcGP1NTS38kAWlp8HD/HmwGSAm/HTaod/t+lxcsw+YVfy1UogY8RfIdO2bKBkwXfBTzwBHgCPAkTfMeKLYGPFHznAjzwBHgCPAGeAE+AJ8AT4AnwBHgCPAGeBABP6RUtngBPgCfAE+AJ8AR4AjwBngBPgCfAE+AJ8AR44IEHHnjggQd+x6H0ihZPgCfAE+AJ8AR4AjwBngBPgCfAE+AJ8AR4AjzwwAMPPPDAAw888MADDzzwzfA/AD6Z8G8Bn0z4Y8DTxxPgCfAEeAI8AZ5EEf6HwCcT/ifAJxP+y8ADT4AncYe/AzzwJEHwzwEPPAGexB3+08ADT4AnwBPgCfAEeAI8AZ4AT8ILT0KbPYUnCQvwwBPgCfAktvAksDxnc+fOt2923e7peeP1d7v2K/8HJyX+walUsMUAAAAASUVORK5CYII=";export{A as _,P as a,n as b,f as c}; diff --git a/assets/app-DaLjD81q.js b/assets/app-DaLjD81q.js deleted file mode 100644 index 850afac6..00000000 --- a/assets/app-DaLjD81q.js +++ /dev/null @@ -1,16 +0,0 @@ -function $o(e,t){const n=Object.create(null),r=e.split(",");for(let o=0;o!!n[o.toLowerCase()]:o=>!!n[o]}const Te={},dn=[],gt=()=>{},Oa=()=>!1,Ia=/^on[^a-z]/,Yn=e=>Ia.test(e),No=e=>e.startsWith("onUpdate:"),He=Object.assign,Ho=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Da=Object.prototype.hasOwnProperty,he=(e,t)=>Da.call(e,t),Q=Array.isArray,hn=e=>Fr(e)==="[object Map]",Hi=e=>Fr(e)==="[object Set]",ae=e=>typeof e=="function",ve=e=>typeof e=="string",Hr=e=>typeof e=="symbol",xe=e=>e!==null&&typeof e=="object",Fi=e=>(xe(e)||ae(e))&&ae(e.then)&&ae(e.catch),Bi=Object.prototype.toString,Fr=e=>Bi.call(e),Ma=e=>Fr(e).slice(8,-1),zi=e=>Fr(e)==="[object Object]",Fo=e=>ve(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Mn=$o(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Br=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},$a=/-(\w)/g,bt=Br(e=>e.replace($a,(t,n)=>n?n.toUpperCase():"")),Na=/\B([A-Z])/g,nn=Br(e=>e.replace(Na,"-$1").toLowerCase()),zr=Br(e=>e.charAt(0).toUpperCase()+e.slice(1)),Zr=Br(e=>e?`on${zr(e)}`:""),tn=(e,t)=>!Object.is(e,t),Er=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},vo=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Ha=e=>{const t=ve(e)?Number(e):NaN;return isNaN(t)?e:t};let Es;const go=()=>Es||(Es=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Jn(e){if(Q(e)){const t={};for(let n=0;n{if(n){const r=n.split(Ba);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Je(e){let t="";if(ve(e))t=e;else if(Q(e))for(let n=0;nve(e)?e:e==null?"":Q(e)||xe(e)&&(e.toString===Bi||!ae(e.toString))?JSON.stringify(e,ji,2):String(e),ji=(e,t)=>t&&t.__v_isRef?ji(e,t.value):hn(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,o])=>(n[`${r} =>`]=o,n),{})}:Hi(t)?{[`Set(${t.size})`]:[...t.values()]}:xe(t)&&!Q(t)&&!zi(t)?String(t):t;let et;class Wa{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=et,!t&&et&&(this.index=(et.scopes||(et.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=et;try{return et=this,t()}finally{et=n}}}on(){et=this}off(){et=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},Wi=e=>(e.w&Bt)>0,Ki=e=>(e.n&Bt)>0,Ga=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let r=0;r{(u==="length"||!Hr(u)&&u>=a)&&l.push(c)})}else switch(n!==void 0&&l.push(i.get(n)),t){case"add":Q(e)?Fo(n)&&l.push(i.get("length")):(l.push(i.get(Xt)),hn(e)&&l.push(i.get(bo)));break;case"delete":Q(e)||(l.push(i.get(Xt)),hn(e)&&l.push(i.get(bo)));break;case"set":hn(e)&&l.push(i.get(Xt));break}if(l.length===1)l[0]&&yo(l[0]);else{const a=[];for(const c of l)c&&a.push(...c);yo(Bo(a))}}function yo(e,t){const n=Q(e)?e:[...e];for(const r of n)r.computed&&Cs(r);for(const r of n)r.computed||Cs(r)}function Cs(e,t){(e!==ft||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}function Ja(e,t){var n;return(n=Lr.get(e))==null?void 0:n.get(t)}const Qa=$o("__proto__,__v_isRef,__isVue"),Yi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Hr)),Ts=Za();function Za(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=me(this);for(let s=0,i=this.length;s{e[t]=function(...n){Cn();const r=me(this)[t].apply(this,n);return Tn(),r}}),e}function Xa(e){const t=me(this);return Ze(t,"has",e),t.hasOwnProperty(e)}class Ji{constructor(t=!1,n=!1){this._isReadonly=t,this._shallow=n}get(t,n,r){const o=this._isReadonly,s=this._shallow;if(n==="__v_isReactive")return!o;if(n==="__v_isReadonly")return o;if(n==="__v_isShallow")return s;if(n==="__v_raw"&&r===(o?s?dc:el:s?Xi:Zi).get(t))return t;const i=Q(t);if(!o){if(i&&he(Ts,n))return Reflect.get(Ts,n,r);if(n==="hasOwnProperty")return Xa}const l=Reflect.get(t,n,r);return(Hr(n)?Yi.has(n):Qa(n))||(o||Ze(t,"get",n),s)?l:Be(l)?i&&Fo(n)?l:l.value:xe(l)?o?Zn(l):Qn(l):l}}class Qi extends Ji{constructor(t=!1){super(!1,t)}set(t,n,r,o){let s=t[n];if(gn(s)&&Be(s)&&!Be(r))return!1;if(!this._shallow&&(!xr(r)&&!gn(r)&&(s=me(s),r=me(r)),!Q(t)&&Be(s)&&!Be(r)))return s.value=r,!0;const i=Q(t)&&Fo(n)?Number(n)e,Vr=e=>Reflect.getPrototypeOf(e);function ir(e,t,n=!1,r=!1){e=e.__v_raw;const o=me(e),s=me(t);n||(tn(t,s)&&Ze(o,"get",t),Ze(o,"get",s));const{has:i}=Vr(o),l=r?Vo:n?Wo:Vn;if(i.call(o,t))return l(e.get(t));if(i.call(o,s))return l(e.get(s));e!==o&&e.get(t)}function lr(e,t=!1){const n=this.__v_raw,r=me(n),o=me(e);return t||(tn(e,o)&&Ze(r,"has",e),Ze(r,"has",o)),e===o?n.has(e):n.has(e)||n.has(o)}function ar(e,t=!1){return e=e.__v_raw,!t&&Ze(me(e),"iterate",Xt),Reflect.get(e,"size",e)}function Ls(e){e=me(e);const t=me(this);return Vr(t).has.call(t,e)||(t.add(e),Lt(t,"add",e,e)),this}function xs(e,t){t=me(t);const n=me(this),{has:r,get:o}=Vr(n);let s=r.call(n,e);s||(e=me(e),s=r.call(n,e));const i=o.call(n,e);return n.set(e,t),s?tn(t,i)&&Lt(n,"set",e,t):Lt(n,"add",e,t),this}function As(e){const t=me(this),{has:n,get:r}=Vr(t);let o=n.call(t,e);o||(e=me(e),o=n.call(t,e)),r&&r.call(t,e);const s=t.delete(e);return o&&Lt(t,"delete",e,void 0),s}function Ss(){const e=me(this),t=e.size!==0,n=e.clear();return t&&Lt(e,"clear",void 0,void 0),n}function cr(e,t){return function(r,o){const s=this,i=s.__v_raw,l=me(i),a=t?Vo:e?Wo:Vn;return!e&&Ze(l,"iterate",Xt),i.forEach((c,u)=>r.call(o,a(c),a(u),s))}}function ur(e,t,n){return function(...r){const o=this.__v_raw,s=me(o),i=hn(s),l=e==="entries"||e===Symbol.iterator&&i,a=e==="keys"&&i,c=o[e](...r),u=n?Vo:t?Wo:Vn;return!t&&Ze(s,"iterate",a?bo:Xt),{next(){const{value:f,done:d}=c.next();return d?{value:f,done:d}:{value:l?[u(f[0]),u(f[1])]:u(f),done:d}},[Symbol.iterator](){return this}}}}function St(e){return function(...t){return e==="delete"?!1:this}}function oc(){const e={get(s){return ir(this,s)},get size(){return ar(this)},has:lr,add:Ls,set:xs,delete:As,clear:Ss,forEach:cr(!1,!1)},t={get(s){return ir(this,s,!1,!0)},get size(){return ar(this)},has:lr,add:Ls,set:xs,delete:As,clear:Ss,forEach:cr(!1,!0)},n={get(s){return ir(this,s,!0)},get size(){return ar(this,!0)},has(s){return lr.call(this,s,!0)},add:St("add"),set:St("set"),delete:St("delete"),clear:St("clear"),forEach:cr(!0,!1)},r={get(s){return ir(this,s,!0,!0)},get size(){return ar(this,!0)},has(s){return lr.call(this,s,!0)},add:St("add"),set:St("set"),delete:St("delete"),clear:St("clear"),forEach:cr(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(s=>{e[s]=ur(s,!1,!1),n[s]=ur(s,!0,!1),t[s]=ur(s,!1,!0),r[s]=ur(s,!0,!0)}),[e,n,t,r]}const[sc,ic,lc,ac]=oc();function jo(e,t){const n=t?e?ac:lc:e?ic:sc;return(r,o,s)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?r:Reflect.get(he(n,o)&&o in r?n:r,o,s)}const cc={get:jo(!1,!1)},uc={get:jo(!1,!0)},fc={get:jo(!0,!1)},Zi=new WeakMap,Xi=new WeakMap,el=new WeakMap,dc=new WeakMap;function hc(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function pc(e){return e.__v_skip||!Object.isExtensible(e)?0:hc(Ma(e))}function Qn(e){return gn(e)?e:Uo(e,!1,tc,cc,Zi)}function tl(e){return Uo(e,!1,rc,uc,Xi)}function Zn(e){return Uo(e,!0,nc,fc,el)}function Uo(e,t,n,r,o){if(!xe(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const s=o.get(e);if(s)return s;const i=pc(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return o.set(e,l),l}function pn(e){return gn(e)?pn(e.__v_raw):!!(e&&e.__v_isReactive)}function gn(e){return!!(e&&e.__v_isReadonly)}function xr(e){return!!(e&&e.__v_isShallow)}function nl(e){return pn(e)||gn(e)}function me(e){const t=e&&e.__v_raw;return t?me(t):e}function rl(e){return Tr(e,"__v_skip",!0),e}const Vn=e=>xe(e)?Qn(e):e,Wo=e=>xe(e)?Zn(e):e;function Ko(e){$t&&ft&&(e=me(e),Gi(e.dep||(e.dep=Bo())))}function qo(e,t){e=me(e);const n=e.dep;n&&yo(n)}function Be(e){return!!(e&&e.__v_isRef===!0)}function _e(e){return ol(e,!1)}function Ln(e){return ol(e,!0)}function ol(e,t){return Be(e)?e:new mc(e,t)}class mc{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:me(t),this._value=n?t:Vn(t)}get value(){return Ko(this),this._value}set value(t){const n=this.__v_isShallow||xr(t)||gn(t);t=n?t:me(t),tn(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Vn(t),qo(this))}}function ne(e){return Be(e)?e.value:e}const vc={get:(e,t,n)=>ne(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return Be(o)&&!Be(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function sl(e){return pn(e)?e:new Proxy(e,vc)}class gc{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>Ko(this),()=>qo(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function _c(e){return new gc(e)}function Go(e){const t=Q(e)?new Array(e.length):{};for(const n in e)t[n]=yc(e,n);return t}class bc{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Ja(me(this._object),this._key)}}function yc(e,t,n){const r=e[t];return Be(r)?r:new bc(e,t,n)}class Ec{constructor(t,n,r,o){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new zo(t,()=>{this._dirty||(this._dirty=!0,qo(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!o,this.__v_isReadonly=r}get value(){const t=me(this);return Ko(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function wc(e,t,n=!1){let r,o;const s=ae(e);return s?(r=e,o=gt):(r=e.get,o=e.set),new Ec(r,o,s||!o,n)}function Nt(e,t,n,r){let o;try{o=r?e(...r):e()}catch(s){Xn(s,t,n)}return o}function st(e,t,n,r){if(ae(e)){const s=Nt(e,t,n,r);return s&&Fi(s)&&s.catch(i=>{Xn(i,t,n)}),s}const o=[];for(let s=0;s>>1,o=Ue[r],s=Un(o);svt&&Ue.splice(t,1)}function xc(e){Q(e)?mn.push(...e):(!Tt||!Tt.includes(e,e.allowRecurse?Yt+1:Yt))&&mn.push(e),ll()}function ks(e,t=jn?vt+1:0){for(;tUn(n)-Un(r)),Yt=0;Yte.id==null?1/0:e.id,Ac=(e,t)=>{const n=Un(e)-Un(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function al(e){Eo=!1,jn=!0,Ue.sort(Ac);try{for(vt=0;vtve(m)?m.trim():m)),f&&(o=n.map(vo))}let l,a=r[l=Zr(t)]||r[l=Zr(bt(t))];!a&&s&&(a=r[l=Zr(nn(t))]),a&&st(a,e,6,o);const c=r[l+"Once"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,st(c,e,6,o)}}function cl(e,t,n=!1){const r=t.emitsCache,o=r.get(e);if(o!==void 0)return o;const s=e.emits;let i={},l=!1;if(!ae(e)){const a=c=>{const u=cl(c,t,!0);u&&(l=!0,He(i,u))};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!s&&!l?(xe(e)&&r.set(e,null),null):(Q(s)?s.forEach(a=>i[a]=null):He(i,s),xe(e)&&r.set(e,i),i)}function Ur(e,t){return!e||!Yn(t)?!1:(t=t.slice(2).replace(/Once$/,""),he(e,t[0].toLowerCase()+t.slice(1))||he(e,nn(t))||he(e,t))}let ze=null,ul=null;function Sr(e){const t=ze;return ze=e,ul=e&&e.type.__scopeId||null,t}function Fe(e,t=ze,n){if(!t||e._n)return e;const r=(...o)=>{r._d&&zs(-1);const s=Sr(t);let i;try{i=e(...o)}finally{Sr(s),r._d&&zs(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function Xr(e){const{type:t,vnode:n,proxy:r,withProxy:o,props:s,propsOptions:[i],slots:l,attrs:a,emit:c,render:u,renderCache:f,data:d,setupState:m,ctx:b,inheritAttrs:w}=e;let L,A;const S=Sr(e);try{if(n.shapeFlag&4){const y=o||r;L=ut(u.call(y,y,f,s,m,d,b)),A=a}else{const y=t;L=ut(y.length>1?y(s,{attrs:a,slots:l,emit:c}):y(s,null)),A=t.props?a:kc(a)}}catch(y){Hn.length=0,Xn(y,e,1),L=se(tt)}let g=L;if(A&&w!==!1){const y=Object.keys(A),{shapeFlag:B}=g;y.length&&B&7&&(i&&y.some(No)&&(A=Pc(A,i)),g=Vt(g,A))}return n.dirs&&(g=Vt(g),g.dirs=g.dirs?g.dirs.concat(n.dirs):n.dirs),n.transition&&(g.transition=n.transition),L=g,Sr(S),L}const kc=e=>{let t;for(const n in e)(n==="class"||n==="style"||Yn(n))&&((t||(t={}))[n]=e[n]);return t},Pc=(e,t)=>{const n={};for(const r in e)(!No(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function Rc(e,t,n){const{props:r,children:o,component:s}=e,{props:i,children:l,patchFlag:a}=t,c=s.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&a>=0){if(a&1024)return!0;if(a&16)return r?Ps(r,i,c):!!i;if(a&8){const u=t.dynamicProps;for(let f=0;fe.__isSuspense;function dl(e,t){t&&t.pendingBranch?Q(e)?t.effects.push(...e):t.effects.push(e):xc(e)}function hl(e,t){return Jo(e,null,t)}const fr={};function Qe(e,t,n){return Jo(e,t,n)}function Jo(e,t,{immediate:n,deep:r,flush:o,onTrack:s,onTrigger:i}=Te){var l;const a=Ui()===((l=$e)==null?void 0:l.scope)?$e:null;let c,u=!1,f=!1;if(Be(e)?(c=()=>e.value,u=xr(e)):pn(e)?(c=()=>e,r=!0):Q(e)?(f=!0,u=e.some(y=>pn(y)||xr(y)),c=()=>e.map(y=>{if(Be(y))return y.value;if(pn(y))return Zt(y);if(ae(y))return Nt(y,a,2)})):ae(e)?t?c=()=>Nt(e,a,2):c=()=>{if(!(a&&a.isUnmounted))return d&&d(),st(e,a,3,[m])}:c=gt,t&&r){const y=c;c=()=>Zt(y())}let d,m=y=>{d=S.onStop=()=>{Nt(y,a,4)}},b;if(yn)if(m=gt,t?n&&st(t,a,3,[c(),f?[]:void 0,m]):c(),o==="sync"){const y=Su();b=y.__watcherHandles||(y.__watcherHandles=[])}else return gt;let w=f?new Array(e.length).fill(fr):fr;const L=()=>{if(S.active)if(t){const y=S.run();(r||u||(f?y.some((B,G)=>tn(B,w[G])):tn(y,w)))&&(d&&d(),st(t,a,3,[y,w===fr?void 0:f&&w[0]===fr?[]:w,m]),w=y)}else S.run()};L.allowRecurse=!!t;let A;o==="sync"?A=L:o==="post"?A=()=>Ye(L,a&&a.suspense):(L.pre=!0,a&&(L.id=a.uid),A=()=>jr(L));const S=new zo(c,A);t?n?L():w=S.run():o==="post"?Ye(S.run.bind(S),a&&a.suspense):S.run();const g=()=>{S.stop(),a&&a.scope&&Ho(a.scope.effects,S)};return b&&b.push(g),g}function $c(e,t,n){const r=this.proxy,o=ve(e)?e.includes(".")?pl(r,e):()=>r[e]:e.bind(r,r);let s;ae(t)?s=t:(s=t.handler,n=t);const i=$e;bn(this);const l=Jo(o,s.bind(r),n);return i?bn(i):en(),l}function pl(e,t){const n=t.split(".");return()=>{let r=e;for(let o=0;o{Zt(n,t)});else if(zi(e))for(const n in e)Zt(e[n],t);return e}function kr(e,t){const n=ze;if(n===null)return e;const r=Gr(n)||n.proxy,o=e.dirs||(e.dirs=[]);for(let s=0;s{e.isMounted=!0}),Kr(()=>{e.isUnmounting=!0}),e}const nt=[Function,Array],ml={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:nt,onEnter:nt,onAfterEnter:nt,onEnterCancelled:nt,onBeforeLeave:nt,onLeave:nt,onAfterLeave:nt,onLeaveCancelled:nt,onBeforeAppear:nt,onAppear:nt,onAfterAppear:nt,onAppearCancelled:nt},Hc={name:"BaseTransition",props:ml,setup(e,{slots:t}){const n=es(),r=Nc();let o;return()=>{const s=t.default&&gl(t.default(),!0);if(!s||!s.length)return;let i=s[0];if(s.length>1){for(const w of s)if(w.type!==tt){i=w;break}}const l=me(e),{mode:a}=l;if(r.isLeaving)return eo(i);const c=Os(i);if(!c)return eo(i);const u=wo(c,l,r,n);Co(c,u);const f=n.subTree,d=f&&Os(f);let m=!1;const{getTransitionKey:b}=c.type;if(b){const w=b();o===void 0?o=w:w!==o&&(o=w,m=!0)}if(d&&d.type!==tt&&(!Jt(c,d)||m)){const w=wo(d,l,r,n);if(Co(d,w),a==="out-in")return r.isLeaving=!0,w.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&n.update()},eo(i);a==="in-out"&&c.type!==tt&&(w.delayLeave=(L,A,S)=>{const g=vl(r,d);g[String(d.key)]=d,L[It]=()=>{A(),L[It]=void 0,delete u.delayedLeave},u.delayedLeave=S})}return i}}},Fc=Hc;function vl(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function wo(e,t,n,r){const{appear:o,mode:s,persisted:i=!1,onBeforeEnter:l,onEnter:a,onAfterEnter:c,onEnterCancelled:u,onBeforeLeave:f,onLeave:d,onAfterLeave:m,onLeaveCancelled:b,onBeforeAppear:w,onAppear:L,onAfterAppear:A,onAppearCancelled:S}=t,g=String(e.key),y=vl(n,e),B=(_,O)=>{_&&st(_,r,9,O)},G=(_,O)=>{const k=O[1];B(_,O),Q(_)?_.every(z=>z.length<=1)&&k():_.length<=1&&k()},H={mode:s,persisted:i,beforeEnter(_){let O=l;if(!n.isMounted)if(o)O=w||l;else return;_[It]&&_[It](!0);const k=y[g];k&&Jt(e,k)&&k.el[It]&&k.el[It](),B(O,[_])},enter(_){let O=a,k=c,z=u;if(!n.isMounted)if(o)O=L||a,k=A||c,z=S||u;else return;let C=!1;const M=_[dr]=re=>{C||(C=!0,re?B(z,[_]):B(k,[_]),H.delayedLeave&&H.delayedLeave(),_[dr]=void 0)};O?G(O,[_,M]):M()},leave(_,O){const k=String(e.key);if(_[dr]&&_[dr](!0),n.isUnmounting)return O();B(f,[_]);let z=!1;const C=_[It]=M=>{z||(z=!0,O(),M?B(b,[_]):B(m,[_]),_[It]=void 0,y[k]===e&&delete y[k])};y[k]=e,d?G(d,[_,C]):C()},clone(_){return wo(_,t,n,r)}};return H}function eo(e){if(tr(e))return e=Vt(e),e.children=null,e}function Os(e){return tr(e)?e.children?e.children[0]:void 0:e}function Co(e,t){e.shapeFlag&6&&e.component?Co(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function gl(e,t=!1,n){let r=[],o=0;for(let s=0;s1)for(let s=0;s!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function oe(e){ae(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:o=200,timeout:s,suspensible:i=!0,onError:l}=e;let a=null,c,u=0;const f=()=>(u++,a=null,d()),d=()=>{let m;return a||(m=a=t().catch(b=>{if(b=b instanceof Error?b:new Error(String(b)),l)return new Promise((w,L)=>{l(b,()=>w(f()),()=>L(b),u+1)});throw b}).then(b=>m!==a&&a?a:(b&&(b.__esModule||b[Symbol.toStringTag]==="Module")&&(b=b.default),c=b,b)))};return ce({name:"AsyncComponentWrapper",__asyncLoader:d,get __asyncResolved(){return c},setup(){const m=$e;if(c)return()=>to(c,m);const b=S=>{a=null,Xn(S,m,13,!r)};if(i&&m.suspense||yn)return d().then(S=>()=>to(S,m)).catch(S=>(b(S),()=>r?se(r,{error:S}):null));const w=_e(!1),L=_e(),A=_e(!!o);return o&&setTimeout(()=>{A.value=!1},o),s!=null&&setTimeout(()=>{if(!w.value&&!L.value){const S=new Error(`Async component timed out after ${s}ms.`);b(S),L.value=S}},s),d().then(()=>{w.value=!0,m.parent&&tr(m.parent.vnode)&&jr(m.parent.update)}).catch(S=>{b(S),L.value=S}),()=>{if(w.value&&c)return to(c,m);if(L.value&&r)return se(r,{error:L.value});if(n&&!A.value)return se(n)}}})}function to(e,t){const{ref:n,props:r,children:o,ce:s}=t.vnode,i=se(e,r,o);return i.ref=n,i.ce=s,delete t.vnode.ce,i}const tr=e=>e.type.__isKeepAlive;function Bc(e,t){_l(e,"a",t)}function zc(e,t){_l(e,"da",t)}function _l(e,t,n=$e){const r=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Wr(t,r,n),n){let o=n.parent;for(;o&&o.parent;)tr(o.parent.vnode)&&Vc(r,t,n,o),o=o.parent}}function Vc(e,t,n,r){const o=Wr(t,e,r,!0);nr(()=>{Ho(r[t],o)},n)}function Wr(e,t,n=$e,r=!1){if(n){const o=n[e]||(n[e]=[]),s=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;Cn(),bn(n);const l=st(t,n,e,i);return en(),Tn(),l});return r?o.unshift(s):o.push(s),s}}const At=e=>(t,n=$e)=>(!yn||e==="sp")&&Wr(e,(...r)=>t(...r),n),jc=At("bm"),De=At("m"),Uc=At("bu"),Wc=At("u"),Kr=At("bum"),nr=At("um"),Kc=At("sp"),qc=At("rtg"),Gc=At("rtc");function Yc(e,t=$e){Wr("ec",e,t)}function zt(e,t,n,r){let o;const s=n&&n[r];if(Q(e)||ve(e)){o=new Array(e.length);for(let i=0,l=e.length;it(i,l,void 0,s&&s[l]));else{const i=Object.keys(e);o=new Array(i.length);for(let l=0,a=i.length;lIr(t)?!(t.type===tt||t.type===Ce&&!bl(t.children)):!0)?e:null}const To=e=>e?Rl(e)?Gr(e)||e.proxy:To(e.parent):null,$n=He(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>To(e.parent),$root:e=>To(e.root),$emit:e=>e.emit,$options:e=>Qo(e),$forceUpdate:e=>e.f||(e.f=()=>jr(e.update)),$nextTick:e=>e.n||(e.n=er.bind(e.proxy)),$watch:e=>$c.bind(e)}),no=(e,t)=>e!==Te&&!e.__isScriptSetup&&he(e,t),Jc={get({_:e},t){const{ctx:n,setupState:r,data:o,props:s,accessCache:i,type:l,appContext:a}=e;let c;if(t[0]!=="$"){const m=i[t];if(m!==void 0)switch(m){case 1:return r[t];case 2:return o[t];case 4:return n[t];case 3:return s[t]}else{if(no(r,t))return i[t]=1,r[t];if(o!==Te&&he(o,t))return i[t]=2,o[t];if((c=e.propsOptions[0])&&he(c,t))return i[t]=3,s[t];if(n!==Te&&he(n,t))return i[t]=4,n[t];Lo&&(i[t]=0)}}const u=$n[t];let f,d;if(u)return t==="$attrs"&&Ze(e,"get",t),u(e);if((f=l.__cssModules)&&(f=f[t]))return f;if(n!==Te&&he(n,t))return i[t]=4,n[t];if(d=a.config.globalProperties,he(d,t))return d[t]},set({_:e},t,n){const{data:r,setupState:o,ctx:s}=e;return no(o,t)?(o[t]=n,!0):r!==Te&&he(r,t)?(r[t]=n,!0):he(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(s[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:o,propsOptions:s}},i){let l;return!!n[i]||e!==Te&&he(e,i)||no(t,i)||(l=s[0])&&he(l,i)||he(r,i)||he($n,i)||he(o.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:he(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Is(e){return Q(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Lo=!0;function Qc(e){const t=Qo(e),n=e.proxy,r=e.ctx;Lo=!1,t.beforeCreate&&Ds(t.beforeCreate,e,"bc");const{data:o,computed:s,methods:i,watch:l,provide:a,inject:c,created:u,beforeMount:f,mounted:d,beforeUpdate:m,updated:b,activated:w,deactivated:L,beforeDestroy:A,beforeUnmount:S,destroyed:g,unmounted:y,render:B,renderTracked:G,renderTriggered:H,errorCaptured:_,serverPrefetch:O,expose:k,inheritAttrs:z,components:C,directives:M,filters:re}=t;if(c&&Zc(c,r,null),i)for(const Y in i){const K=i[Y];ae(K)&&(r[Y]=K.bind(n))}if(o){const Y=o.call(n,n);xe(Y)&&(e.data=Qn(Y))}if(Lo=!0,s)for(const Y in s){const K=s[Y],ye=ae(K)?K.bind(n,n):ae(K.get)?K.get.bind(n,n):gt,Me=!ae(K)&&ae(K.set)?K.set.bind(n):gt,Ve=V({get:ye,set:Me});Object.defineProperty(r,Y,{enumerable:!0,configurable:!0,get:()=>Ve.value,set:Oe=>Ve.value=Oe})}if(l)for(const Y in l)yl(l[Y],r,n,Y);if(a){const Y=ae(a)?a.call(n):a;Reflect.ownKeys(Y).forEach(K=>{Ht(K,Y[K])})}u&&Ds(u,e,"c");function R(Y,K){Q(K)?K.forEach(ye=>Y(ye.bind(n))):K&&Y(K.bind(n))}if(R(jc,f),R(De,d),R(Uc,m),R(Wc,b),R(Bc,w),R(zc,L),R(Yc,_),R(Gc,G),R(qc,H),R(Kr,S),R(nr,y),R(Kc,O),Q(k))if(k.length){const Y=e.exposed||(e.exposed={});k.forEach(K=>{Object.defineProperty(Y,K,{get:()=>n[K],set:ye=>n[K]=ye})})}else e.exposed||(e.exposed={});B&&e.render===gt&&(e.render=B),z!=null&&(e.inheritAttrs=z),C&&(e.components=C),M&&(e.directives=M)}function Zc(e,t,n=gt){Q(e)&&(e=xo(e));for(const r in e){const o=e[r];let s;xe(o)?"default"in o?s=Se(o.from||r,o.default,!0):s=Se(o.from||r):s=Se(o),Be(s)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>s.value,set:i=>s.value=i}):t[r]=s}}function Ds(e,t,n){st(Q(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function yl(e,t,n,r){const o=r.includes(".")?pl(n,r):()=>n[r];if(ve(e)){const s=t[e];ae(s)&&Qe(o,s)}else if(ae(e))Qe(o,e.bind(n));else if(xe(e))if(Q(e))e.forEach(s=>yl(s,t,n,r));else{const s=ae(e.handler)?e.handler.bind(n):t[e.handler];ae(s)&&Qe(o,s,e)}}function Qo(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:o,optionsCache:s,config:{optionMergeStrategies:i}}=e.appContext,l=s.get(t);let a;return l?a=l:!o.length&&!n&&!r?a=t:(a={},o.length&&o.forEach(c=>Pr(a,c,i,!0)),Pr(a,t,i)),xe(t)&&s.set(t,a),a}function Pr(e,t,n,r=!1){const{mixins:o,extends:s}=t;s&&Pr(e,s,n,!0),o&&o.forEach(i=>Pr(e,i,n,!0));for(const i in t)if(!(r&&i==="expose")){const l=Xc[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const Xc={data:Ms,props:$s,emits:$s,methods:Dn,computed:Dn,beforeCreate:Ke,created:Ke,beforeMount:Ke,mounted:Ke,beforeUpdate:Ke,updated:Ke,beforeDestroy:Ke,beforeUnmount:Ke,destroyed:Ke,unmounted:Ke,activated:Ke,deactivated:Ke,errorCaptured:Ke,serverPrefetch:Ke,components:Dn,directives:Dn,watch:tu,provide:Ms,inject:eu};function Ms(e,t){return t?e?function(){return He(ae(e)?e.call(this,this):e,ae(t)?t.call(this,this):t)}:t:e}function eu(e,t){return Dn(xo(e),xo(t))}function xo(e){if(Q(e)){const t={};for(let n=0;n1)return n&&ae(t)?t.call(r&&r.proxy):t}}function ou(e,t,n,r=!1){const o={},s={};Tr(s,qr,1),e.propsDefaults=Object.create(null),wl(e,t,o,s);for(const i in e.propsOptions[0])i in o||(o[i]=void 0);n?e.props=r?o:tl(o):e.type.props?e.props=o:e.props=s,e.attrs=s}function su(e,t,n,r){const{props:o,attrs:s,vnode:{patchFlag:i}}=e,l=me(o),[a]=e.propsOptions;let c=!1;if((r||i>0)&&!(i&16)){if(i&8){const u=e.vnode.dynamicProps;for(let f=0;f{a=!0;const[d,m]=Cl(f,t,!0);He(i,d),m&&l.push(...m)};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!s&&!a)return xe(e)&&r.set(e,dn),dn;if(Q(s))for(let u=0;u-1,m[1]=w<0||b-1||he(m,"default"))&&l.push(f)}}}const c=[i,l];return xe(e)&&r.set(e,c),c}function Ns(e){return e[0]!=="$"}function Hs(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function Fs(e,t){return Hs(e)===Hs(t)}function Bs(e,t){return Q(t)?t.findIndex(n=>Fs(n,e)):ae(t)&&Fs(t,e)?0:-1}const Tl=e=>e[0]==="_"||e==="$stable",Zo=e=>Q(e)?e.map(ut):[ut(e)],iu=(e,t,n)=>{if(t._n)return t;const r=Fe((...o)=>Zo(t(...o)),n);return r._c=!1,r},Ll=(e,t,n)=>{const r=e._ctx;for(const o in e){if(Tl(o))continue;const s=e[o];if(ae(s))t[o]=iu(o,s,r);else if(s!=null){const i=Zo(s);t[o]=()=>i}}},xl=(e,t)=>{const n=Zo(t);e.slots.default=()=>n},lu=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=me(t),Tr(t,"_",n)):Ll(t,e.slots={})}else e.slots={},t&&xl(e,t);Tr(e.slots,qr,1)},au=(e,t,n)=>{const{vnode:r,slots:o}=e;let s=!0,i=Te;if(r.shapeFlag&32){const l=t._;l?n&&l===1?s=!1:(He(o,t),!n&&l===1&&delete o._):(s=!t.$stable,Ll(t,o)),i=t}else t&&(xl(e,t),i={default:1});if(s)for(const l in o)!Tl(l)&&i[l]==null&&delete o[l]};function Or(e,t,n,r,o=!1){if(Q(e)){e.forEach((d,m)=>Or(d,t&&(Q(t)?t[m]:t),n,r,o));return}if(vn(r)&&!o)return;const s=r.shapeFlag&4?Gr(r.component)||r.component.proxy:r.el,i=o?null:s,{i:l,r:a}=e,c=t&&t.r,u=l.refs===Te?l.refs={}:l.refs,f=l.setupState;if(c!=null&&c!==a&&(ve(c)?(u[c]=null,he(f,c)&&(f[c]=null)):Be(c)&&(c.value=null)),ae(a))Nt(a,l,12,[i,u]);else{const d=ve(a),m=Be(a);if(d||m){const b=()=>{if(e.f){const w=d?he(f,a)?f[a]:u[a]:a.value;o?Q(w)&&Ho(w,s):Q(w)?w.includes(s)||w.push(s):d?(u[a]=[s],he(f,a)&&(f[a]=u[a])):(a.value=[s],e.k&&(u[e.k]=a.value))}else d?(u[a]=i,he(f,a)&&(f[a]=i)):m&&(a.value=i,e.k&&(u[e.k]=i))};i?(b.id=-1,Ye(b,n)):b()}}}let kt=!1;const hr=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",pr=e=>e.nodeType===8;function cu(e){const{mt:t,p:n,o:{patchProp:r,createText:o,nextSibling:s,parentNode:i,remove:l,insert:a,createComment:c}}=e,u=(g,y)=>{if(!y.hasChildNodes()){n(null,g,y),Ar(),y._vnode=g;return}kt=!1,f(y.firstChild,g,null,null,null),Ar(),y._vnode=g,kt&&console.error("Hydration completed but contains mismatches.")},f=(g,y,B,G,H,_=!1)=>{const O=pr(g)&&g.data==="[",k=()=>w(g,y,B,G,H,O),{type:z,ref:C,shapeFlag:M,patchFlag:re}=y;let ie=g.nodeType;y.el=g,re===-2&&(_=!1,y.dynamicChildren=null);let R=null;switch(z){case _n:ie!==3?y.children===""?(a(y.el=o(""),i(g),g),R=g):R=k():(g.data!==y.children&&(kt=!0,g.data=y.children),R=s(g));break;case tt:S(g)?(R=s(g),A(y.el=g.content.firstChild,g,B)):ie!==8||O?R=k():R=s(g);break;case Nn:if(O&&(g=s(g),ie=g.nodeType),ie===1||ie===3){R=g;const Y=!y.children.length;for(let K=0;K{_=_||!!y.dynamicChildren;const{type:O,props:k,patchFlag:z,shapeFlag:C,dirs:M,transition:re}=y,ie=O==="input"&&M||O==="option";if(ie||z!==-1){if(M&&mt(y,null,B,"created"),k)if(ie||!_||z&48)for(const K in k)(ie&&K.endsWith("value")||Yn(K)&&!Mn(K))&&r(g,K,null,k[K],!1,void 0,B);else k.onClick&&r(g,"onClick",null,k.onClick,!1,void 0,B);let R;(R=k&&k.onVnodeBeforeMount)&&rt(R,B,y);let Y=!1;if(S(g)){Y=Al(G,re)&&B&&B.vnode.props&&B.vnode.props.appear;const K=g.content.firstChild;Y&&re.beforeEnter(K),A(K,g,B),y.el=g=K}if(M&&mt(y,null,B,"beforeMount"),((R=k&&k.onVnodeMounted)||M||Y)&&dl(()=>{R&&rt(R,B,y),Y&&re.enter(g),M&&mt(y,null,B,"mounted")},G),C&16&&!(k&&(k.innerHTML||k.textContent))){let K=m(g.firstChild,y,g,B,G,H,_);for(;K;){kt=!0;const ye=K;K=K.nextSibling,l(ye)}}else C&8&&g.textContent!==y.children&&(kt=!0,g.textContent=y.children)}return g.nextSibling},m=(g,y,B,G,H,_,O)=>{O=O||!!y.dynamicChildren;const k=y.children,z=k.length;for(let C=0;C{const{slotScopeIds:O}=y;O&&(H=H?H.concat(O):O);const k=i(g),z=m(s(g),y,k,B,G,H,_);return z&&pr(z)&&z.data==="]"?s(y.anchor=z):(kt=!0,a(y.anchor=c("]"),k,z),z)},w=(g,y,B,G,H,_)=>{if(kt=!0,y.el=null,_){const z=L(g);for(;;){const C=s(g);if(C&&C!==z)l(C);else break}}const O=s(g),k=i(g);return l(g),n(null,y,k,O,B,G,hr(k),H),O},L=(g,y="[",B="]")=>{let G=0;for(;g;)if(g=s(g),g&&pr(g)&&(g.data===y&&G++,g.data===B)){if(G===0)return s(g);G--}return g},A=(g,y,B)=>{const G=y.parentNode;G&&G.replaceChild(g,y);let H=B;for(;H;)H.vnode.el===y&&(H.vnode.el=H.subTree.el=g),H=H.parent},S=g=>g.nodeType===1&&g.tagName.toLowerCase()==="template";return[u,f]}const Ye=dl;function uu(e){return fu(e,cu)}function fu(e,t){const n=go();n.__VUE__=!0;const{insert:r,remove:o,patchProp:s,createElement:i,createText:l,createComment:a,setText:c,setElementText:u,parentNode:f,nextSibling:d,setScopeId:m=gt,insertStaticContent:b}=e,w=(h,p,v,E=null,x=null,P=null,U=!1,$=null,F=!!p.dynamicChildren)=>{if(h===p)return;h&&!Jt(h,p)&&(E=T(h),Oe(h,x,P,!0),h=null),p.patchFlag===-2&&(F=!1,p.dynamicChildren=null);const{type:D,ref:Z,shapeFlag:q}=p;switch(D){case _n:L(h,p,v,E);break;case tt:A(h,p,v,E);break;case Nn:h==null&&S(p,v,E,U);break;case Ce:C(h,p,v,E,x,P,U,$,F);break;default:q&1?B(h,p,v,E,x,P,U,$,F):q&6?M(h,p,v,E,x,P,U,$,F):(q&64||q&128)&&D.process(h,p,v,E,x,P,U,$,F,N)}Z!=null&&x&&Or(Z,h&&h.ref,P,p||h,!p)},L=(h,p,v,E)=>{if(h==null)r(p.el=l(p.children),v,E);else{const x=p.el=h.el;p.children!==h.children&&c(x,p.children)}},A=(h,p,v,E)=>{h==null?r(p.el=a(p.children||""),v,E):p.el=h.el},S=(h,p,v,E)=>{[h.el,h.anchor]=b(h.children,p,v,E,h.el,h.anchor)},g=({el:h,anchor:p},v,E)=>{let x;for(;h&&h!==p;)x=d(h),r(h,v,E),h=x;r(p,v,E)},y=({el:h,anchor:p})=>{let v;for(;h&&h!==p;)v=d(h),o(h),h=v;o(p)},B=(h,p,v,E,x,P,U,$,F)=>{U=U||p.type==="svg",h==null?G(p,v,E,x,P,U,$,F):O(h,p,x,P,U,$,F)},G=(h,p,v,E,x,P,U,$)=>{let F,D;const{type:Z,props:q,shapeFlag:X,transition:le,dirs:fe}=h;if(F=h.el=i(h.type,P,q&&q.is,q),X&8?u(F,h.children):X&16&&_(h.children,F,null,E,x,P&&Z!=="foreignObject",U,$),fe&&mt(h,null,E,"created"),H(F,h,h.scopeId,U,E),q){for(const be in q)be!=="value"&&!Mn(be)&&s(F,be,null,q[be],P,h.children,E,x,ke);"value"in q&&s(F,"value",null,q.value),(D=q.onVnodeBeforeMount)&&rt(D,E,h)}fe&&mt(h,null,E,"beforeMount");const Ee=Al(x,le);Ee&&le.beforeEnter(F),r(F,p,v),((D=q&&q.onVnodeMounted)||Ee||fe)&&Ye(()=>{D&&rt(D,E,h),Ee&&le.enter(F),fe&&mt(h,null,E,"mounted")},x)},H=(h,p,v,E,x)=>{if(v&&m(h,v),E)for(let P=0;P{for(let D=F;D{const $=p.el=h.el;let{patchFlag:F,dynamicChildren:D,dirs:Z}=p;F|=h.patchFlag&16;const q=h.props||Te,X=p.props||Te;let le;v&&Wt(v,!1),(le=X.onVnodeBeforeUpdate)&&rt(le,v,p,h),Z&&mt(p,h,v,"beforeUpdate"),v&&Wt(v,!0);const fe=x&&p.type!=="foreignObject";if(D?k(h.dynamicChildren,D,$,v,E,fe,P):U||K(h,p,$,null,v,E,fe,P,!1),F>0){if(F&16)z($,p,q,X,v,E,x);else if(F&2&&q.class!==X.class&&s($,"class",null,X.class,x),F&4&&s($,"style",q.style,X.style,x),F&8){const Ee=p.dynamicProps;for(let be=0;be{le&&rt(le,v,p,h),Z&&mt(p,h,v,"updated")},E)},k=(h,p,v,E,x,P,U)=>{for(let $=0;${if(v!==E){if(v!==Te)for(const $ in v)!Mn($)&&!($ in E)&&s(h,$,v[$],null,U,p.children,x,P,ke);for(const $ in E){if(Mn($))continue;const F=E[$],D=v[$];F!==D&&$!=="value"&&s(h,$,D,F,U,p.children,x,P,ke)}"value"in E&&s(h,"value",v.value,E.value)}},C=(h,p,v,E,x,P,U,$,F)=>{const D=p.el=h?h.el:l(""),Z=p.anchor=h?h.anchor:l("");let{patchFlag:q,dynamicChildren:X,slotScopeIds:le}=p;le&&($=$?$.concat(le):le),h==null?(r(D,v,E),r(Z,v,E),_(p.children,v,Z,x,P,U,$,F)):q>0&&q&64&&X&&h.dynamicChildren?(k(h.dynamicChildren,X,v,x,P,U,$),(p.key!=null||x&&p===x.subTree)&&Sl(h,p,!0)):K(h,p,v,Z,x,P,U,$,F)},M=(h,p,v,E,x,P,U,$,F)=>{p.slotScopeIds=$,h==null?p.shapeFlag&512?x.ctx.activate(p,v,E,U,F):re(p,v,E,x,P,U,F):ie(h,p,F)},re=(h,p,v,E,x,P,U)=>{const $=h.component=yu(h,E,x);if(tr(h)&&($.ctx.renderer=N),Eu($),$.asyncDep){if(x&&x.registerDep($,R),!h.el){const F=$.subTree=se(tt);A(null,F,p,v)}return}R($,h,p,v,x,P,U)},ie=(h,p,v)=>{const E=p.component=h.component;if(Rc(h,p,v))if(E.asyncDep&&!E.asyncResolved){Y(E,p,v);return}else E.next=p,Lc(E.update),E.update();else p.el=h.el,E.vnode=p},R=(h,p,v,E,x,P,U)=>{const $=()=>{if(h.isMounted){let{next:Z,bu:q,u:X,parent:le,vnode:fe}=h,Ee=Z,be;Wt(h,!1),Z?(Z.el=fe.el,Y(h,Z,U)):Z=fe,q&&Er(q),(be=Z.props&&Z.props.onVnodeBeforeUpdate)&&rt(be,le,Z,fe),Wt(h,!0);const Ie=Xr(h),at=h.subTree;h.subTree=Ie,w(at,Ie,f(at.el),T(at),h,x,P),Z.el=Ie.el,Ee===null&&Oc(h,Ie.el),X&&Ye(X,x),(be=Z.props&&Z.props.onVnodeUpdated)&&Ye(()=>rt(be,le,Z,fe),x)}else{let Z;const{el:q,props:X}=p,{bm:le,m:fe,parent:Ee}=h,be=vn(p);if(Wt(h,!1),le&&Er(le),!be&&(Z=X&&X.onVnodeBeforeMount)&&rt(Z,Ee,p),Wt(h,!0),q&&ue){const Ie=()=>{h.subTree=Xr(h),ue(q,h.subTree,h,x,null)};be?p.type.__asyncLoader().then(()=>!h.isUnmounted&&Ie()):Ie()}else{const Ie=h.subTree=Xr(h);w(null,Ie,v,E,h,x,P),p.el=Ie.el}if(fe&&Ye(fe,x),!be&&(Z=X&&X.onVnodeMounted)){const Ie=p;Ye(()=>rt(Z,Ee,Ie),x)}(p.shapeFlag&256||Ee&&vn(Ee.vnode)&&Ee.vnode.shapeFlag&256)&&h.a&&Ye(h.a,x),h.isMounted=!0,p=v=E=null}},F=h.effect=new zo($,()=>jr(D),h.scope),D=h.update=()=>F.run();D.id=h.uid,Wt(h,!0),D()},Y=(h,p,v)=>{p.component=h;const E=h.vnode.props;h.vnode=p,h.next=null,su(h,p.props,E,v),au(h,p.children,v),Cn(),ks(),Tn()},K=(h,p,v,E,x,P,U,$,F=!1)=>{const D=h&&h.children,Z=h?h.shapeFlag:0,q=p.children,{patchFlag:X,shapeFlag:le}=p;if(X>0){if(X&128){Me(D,q,v,E,x,P,U,$,F);return}else if(X&256){ye(D,q,v,E,x,P,U,$,F);return}}le&8?(Z&16&&ke(D,x,P),q!==D&&u(v,q)):Z&16?le&16?Me(D,q,v,E,x,P,U,$,F):ke(D,x,P,!0):(Z&8&&u(v,""),le&16&&_(q,v,E,x,P,U,$,F))},ye=(h,p,v,E,x,P,U,$,F)=>{h=h||dn,p=p||dn;const D=h.length,Z=p.length,q=Math.min(D,Z);let X;for(X=0;XZ?ke(h,x,P,!0,!1,q):_(p,v,E,x,P,U,$,F,q)},Me=(h,p,v,E,x,P,U,$,F)=>{let D=0;const Z=p.length;let q=h.length-1,X=Z-1;for(;D<=q&&D<=X;){const le=h[D],fe=p[D]=F?Dt(p[D]):ut(p[D]);if(Jt(le,fe))w(le,fe,v,null,x,P,U,$,F);else break;D++}for(;D<=q&&D<=X;){const le=h[q],fe=p[X]=F?Dt(p[X]):ut(p[X]);if(Jt(le,fe))w(le,fe,v,null,x,P,U,$,F);else break;q--,X--}if(D>q){if(D<=X){const le=X+1,fe=leX)for(;D<=q;)Oe(h[D],x,P,!0),D++;else{const le=D,fe=D,Ee=new Map;for(D=fe;D<=X;D++){const Xe=p[D]=F?Dt(p[D]):ut(p[D]);Xe.key!=null&&Ee.set(Xe.key,D)}let be,Ie=0;const at=X-fe+1;let on=!1,_s=0;const Sn=new Array(at);for(D=0;D=at){Oe(Xe,x,P,!0);continue}let pt;if(Xe.key!=null)pt=Ee.get(Xe.key);else for(be=fe;be<=X;be++)if(Sn[be-fe]===0&&Jt(Xe,p[be])){pt=be;break}pt===void 0?Oe(Xe,x,P,!0):(Sn[pt-fe]=D+1,pt>=_s?_s=pt:on=!0,w(Xe,p[pt],v,null,x,P,U,$,F),Ie++)}const bs=on?du(Sn):dn;for(be=bs.length-1,D=at-1;D>=0;D--){const Xe=fe+D,pt=p[Xe],ys=Xe+1{const{el:P,type:U,transition:$,children:F,shapeFlag:D}=h;if(D&6){Ve(h.component.subTree,p,v,E);return}if(D&128){h.suspense.move(p,v,E);return}if(D&64){U.move(h,p,v,N);return}if(U===Ce){r(P,p,v);for(let q=0;q$.enter(P),x);else{const{leave:q,delayLeave:X,afterLeave:le}=$,fe=()=>r(P,p,v),Ee=()=>{q(P,()=>{fe(),le&&le()})};X?X(P,fe,Ee):Ee()}else r(P,p,v)},Oe=(h,p,v,E=!1,x=!1)=>{const{type:P,props:U,ref:$,children:F,dynamicChildren:D,shapeFlag:Z,patchFlag:q,dirs:X}=h;if($!=null&&Or($,null,v,h,!0),Z&256){p.ctx.deactivate(h);return}const le=Z&1&&X,fe=!vn(h);let Ee;if(fe&&(Ee=U&&U.onVnodeBeforeUnmount)&&rt(Ee,p,h),Z&6)je(h.component,v,E);else{if(Z&128){h.suspense.unmount(v,E);return}le&&mt(h,null,p,"beforeUnmount"),Z&64?h.type.remove(h,p,v,x,N,E):D&&(P!==Ce||q>0&&q&64)?ke(D,p,v,!1,!0):(P===Ce&&q&384||!x&&Z&16)&&ke(F,p,v),E&&We(h)}(fe&&(Ee=U&&U.onVnodeUnmounted)||le)&&Ye(()=>{Ee&&rt(Ee,p,h),le&&mt(h,null,p,"unmounted")},v)},We=h=>{const{type:p,el:v,anchor:E,transition:x}=h;if(p===Ce){lt(v,E);return}if(p===Nn){y(h);return}const P=()=>{o(v),x&&!x.persisted&&x.afterLeave&&x.afterLeave()};if(h.shapeFlag&1&&x&&!x.persisted){const{leave:U,delayLeave:$}=x,F=()=>U(v,P);$?$(h.el,P,F):F()}else P()},lt=(h,p)=>{let v;for(;h!==p;)v=d(h),o(h),h=v;o(p)},je=(h,p,v)=>{const{bum:E,scope:x,update:P,subTree:U,um:$}=h;E&&Er(E),x.stop(),P&&(P.active=!1,Oe(U,h,p,v)),$&&Ye($,p),Ye(()=>{h.isUnmounted=!0},p),p&&p.pendingBranch&&!p.isUnmounted&&h.asyncDep&&!h.asyncResolved&&h.suspenseId===p.pendingId&&(p.deps--,p.deps===0&&p.resolve())},ke=(h,p,v,E=!1,x=!1,P=0)=>{for(let U=P;Uh.shapeFlag&6?T(h.component.subTree):h.shapeFlag&128?h.suspense.next():d(h.anchor||h.el),j=(h,p,v)=>{h==null?p._vnode&&Oe(p._vnode,null,null,!0):w(p._vnode||null,h,p,null,null,null,v),ks(),Ar(),p._vnode=h},N={p:w,um:Oe,m:Ve,r:We,mt:re,mc:_,pc:K,pbc:k,n:T,o:e};let J,ue;return t&&([J,ue]=t(N)),{render:j,hydrate:J,createApp:ru(j,J)}}function Wt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Al(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Sl(e,t,n=!1){const r=e.children,o=t.children;if(Q(r)&&Q(o))for(let s=0;s>1,e[n[l]]0&&(t[r]=n[s-1]),n[s]=r)}}for(s=n.length,i=n[s-1];s-- >0;)n[s]=i,i=t[i];return n}const hu=e=>e.__isTeleport,Ce=Symbol.for("v-fgt"),_n=Symbol.for("v-txt"),tt=Symbol.for("v-cmt"),Nn=Symbol.for("v-stc"),Hn=[];let dt=null;function W(e=!1){Hn.push(dt=e?null:[])}function pu(){Hn.pop(),dt=Hn[Hn.length-1]||null}let Wn=1;function zs(e){Wn+=e}function kl(e){return e.dynamicChildren=Wn>0?dt||dn:null,pu(),Wn>0&&dt&&dt.push(e),e}function ee(e,t,n,r,o,s){return kl(pe(e,t,n,r,o,s,!0))}function Re(e,t,n,r,o){return kl(se(e,t,n,r,o,!0))}function Ir(e){return e?e.__v_isVNode===!0:!1}function Jt(e,t){return e.type===t.type&&e.key===t.key}const qr="__vInternal",Pl=({key:e})=>e??null,wr=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ve(e)||Be(e)||ae(e)?{i:ze,r:e,k:t,f:!!n}:e:null);function pe(e,t=null,n=null,r=0,o=null,s=e===Ce?0:1,i=!1,l=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Pl(t),ref:t&&wr(t),scopeId:ul,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:r,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:ze};return l?(Xo(a,n),s&128&&e.normalize(a)):n&&(a.shapeFlag|=ve(n)?8:16),Wn>0&&!i&&dt&&(a.patchFlag>0||s&6)&&a.patchFlag!==32&&dt.push(a),a}const se=mu;function mu(e,t=null,n=null,r=0,o=null,s=!1){if((!e||e===Ic)&&(e=tt),Ir(e)){const l=Vt(e,t,!0);return n&&Xo(l,n),Wn>0&&!s&&dt&&(l.shapeFlag&6?dt[dt.indexOf(e)]=l:dt.push(l)),l.patchFlag|=-2,l}if(xu(e)&&(e=e.__vccOpts),t){t=vu(t);let{class:l,style:a}=t;l&&!ve(l)&&(t.class=Je(l)),xe(a)&&(nl(a)&&!Q(a)&&(a=He({},a)),t.style=Jn(a))}const i=ve(e)?1:Mc(e)?128:hu(e)?64:xe(e)?4:ae(e)?2:0;return pe(e,t,n,r,o,i,s,!0)}function vu(e){return e?nl(e)||qr in e?He({},e):e:null}function Vt(e,t,n=!1){const{props:r,ref:o,patchFlag:s,children:i}=e,l=t?So(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&Pl(l),ref:t&&t.ref?n&&o?Q(o)?o.concat(wr(t)):[o,wr(t)]:wr(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Ce?s===-1?16:s|16:s,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Vt(e.ssContent),ssFallback:e.ssFallback&&Vt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function jt(e=" ",t=0){return se(_n,null,e,t)}function gu(e,t){const n=se(Nn,null,e);return n.staticCount=t,n}function Pe(e="",t=!1){return t?(W(),Re(tt,null,e)):se(tt,null,e)}function ut(e){return e==null||typeof e=="boolean"?se(tt):Q(e)?se(Ce,null,e.slice()):typeof e=="object"?Dt(e):se(_n,null,String(e))}function Dt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Vt(e)}function Xo(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(Q(t))n=16;else if(typeof t=="object")if(r&65){const o=t.default;o&&(o._c&&(o._d=!1),Xo(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!(qr in t)?t._ctx=ze:o===3&&ze&&(ze.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else ae(t)?(t={default:t,_ctx:ze},n=32):(t=String(t),r&64?(n=16,t=[jt(t)]):n=8);e.children=t,e.shapeFlag|=n}function So(...e){const t={};for(let n=0;n$e||ze;let ts,sn,Vs="__VUE_INSTANCE_SETTERS__";(sn=go()[Vs])||(sn=go()[Vs]=[]),sn.push(e=>$e=e),ts=e=>{sn.length>1?sn.forEach(t=>t(e)):sn[0](e)};const bn=e=>{ts(e),e.scope.on()},en=()=>{$e&&$e.scope.off(),ts(null)};function Rl(e){return e.vnode.shapeFlag&4}let yn=!1;function Eu(e,t=!1){yn=t;const{props:n,children:r}=e.vnode,o=Rl(e);ou(e,n,o,t),lu(e,r);const s=o?wu(e,t):void 0;return yn=!1,s}function wu(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=rl(new Proxy(e.ctx,Jc));const{setup:r}=n;if(r){const o=e.setupContext=r.length>1?Tu(e):null;bn(e),Cn();const s=Nt(r,e,0,[e.props,o]);if(Tn(),en(),Fi(s)){if(s.then(en,en),t)return s.then(i=>{js(e,i,t)}).catch(i=>{Xn(i,e,0)});e.asyncDep=s}else js(e,s,t)}else Ol(e,t)}function js(e,t,n){ae(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:xe(t)&&(e.setupState=sl(t)),Ol(e,n)}let Us;function Ol(e,t,n){const r=e.type;if(!e.render){if(!t&&Us&&!r.render){const o=r.template||Qo(e).template;if(o){const{isCustomElement:s,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:a}=r,c=He(He({isCustomElement:s,delimiters:l},i),a);r.render=Us(o,c)}}e.render=r.render||gt}{bn(e),Cn();try{Qc(e)}finally{Tn(),en()}}}function Cu(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return Ze(e,"get","$attrs"),t[n]}}))}function Tu(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Cu(e)},slots:e.slots,emit:e.emit,expose:t}}function Gr(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(sl(rl(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in $n)return $n[n](e)},has(t,n){return n in t||n in $n}}))}function Lu(e,t=!0){return ae(e)?e.displayName||e.name:e.name||t&&e.__name}function xu(e){return ae(e)&&"__vccOpts"in e}const V=(e,t)=>wc(e,t,yn);function te(e,t,n){const r=arguments.length;return r===2?xe(t)&&!Q(t)?Ir(t)?se(e,null,[t]):se(e,t):se(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Ir(n)&&(n=[n]),se(e,t,n))}const Au=Symbol.for("v-scx"),Su=()=>Se(Au),ku="3.3.8",Pu="http://www.w3.org/2000/svg",Qt=typeof document<"u"?document:null,Ws=Qt&&Qt.createElement("template"),Ru={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o=t?Qt.createElementNS(Pu,e):Qt.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&o.setAttribute("multiple",r.multiple),o},createText:e=>Qt.createTextNode(e),createComment:e=>Qt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Qt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,s){const i=n?n.previousSibling:t.lastChild;if(o&&(o===s||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===s||!(o=o.nextSibling)););else{Ws.innerHTML=r?`${e}`:e;const l=Ws.content;if(r){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Pt="transition",kn="animation",Kn=Symbol("_vtc"),xn=(e,{slots:t})=>te(Fc,Ou(e),t);xn.displayName="Transition";const Il={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};xn.props=He({},ml,Il);const Kt=(e,t=[])=>{Q(e)?e.forEach(n=>n(...t)):e&&e(...t)},Ks=e=>e?Q(e)?e.some(t=>t.length>1):e.length>1:!1;function Ou(e){const t={};for(const C in e)C in Il||(t[C]=e[C]);if(e.css===!1)return t;const{name:n="v",type:r,duration:o,enterFromClass:s=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:a=s,appearActiveClass:c=i,appearToClass:u=l,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:d=`${n}-leave-active`,leaveToClass:m=`${n}-leave-to`}=e,b=Iu(o),w=b&&b[0],L=b&&b[1],{onBeforeEnter:A,onEnter:S,onEnterCancelled:g,onLeave:y,onLeaveCancelled:B,onBeforeAppear:G=A,onAppear:H=S,onAppearCancelled:_=g}=t,O=(C,M,re)=>{qt(C,M?u:l),qt(C,M?c:i),re&&re()},k=(C,M)=>{C._isLeaving=!1,qt(C,f),qt(C,m),qt(C,d),M&&M()},z=C=>(M,re)=>{const ie=C?H:S,R=()=>O(M,C,re);Kt(ie,[M,R]),qs(()=>{qt(M,C?a:s),Rt(M,C?u:l),Ks(ie)||Gs(M,r,w,R)})};return He(t,{onBeforeEnter(C){Kt(A,[C]),Rt(C,s),Rt(C,i)},onBeforeAppear(C){Kt(G,[C]),Rt(C,a),Rt(C,c)},onEnter:z(!1),onAppear:z(!0),onLeave(C,M){C._isLeaving=!0;const re=()=>k(C,M);Rt(C,f),$u(),Rt(C,d),qs(()=>{C._isLeaving&&(qt(C,f),Rt(C,m),Ks(y)||Gs(C,r,L,re))}),Kt(y,[C,re])},onEnterCancelled(C){O(C,!1),Kt(g,[C])},onAppearCancelled(C){O(C,!0),Kt(_,[C])},onLeaveCancelled(C){k(C),Kt(B,[C])}})}function Iu(e){if(e==null)return null;if(xe(e))return[ro(e.enter),ro(e.leave)];{const t=ro(e);return[t,t]}}function ro(e){return Ha(e)}function Rt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Kn]||(e[Kn]=new Set)).add(t)}function qt(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[Kn];n&&(n.delete(t),n.size||(e[Kn]=void 0))}function qs(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Du=0;function Gs(e,t,n,r){const o=e._endId=++Du,s=()=>{o===e._endId&&r()};if(n)return setTimeout(s,n);const{type:i,timeout:l,propCount:a}=Mu(e,t);if(!i)return r();const c=i+"end";let u=0;const f=()=>{e.removeEventListener(c,d),s()},d=m=>{m.target===e&&++u>=a&&f()};setTimeout(()=>{u(n[b]||"").split(", "),o=r(`${Pt}Delay`),s=r(`${Pt}Duration`),i=Ys(o,s),l=r(`${kn}Delay`),a=r(`${kn}Duration`),c=Ys(l,a);let u=null,f=0,d=0;t===Pt?i>0&&(u=Pt,f=i,d=s.length):t===kn?c>0&&(u=kn,f=c,d=a.length):(f=Math.max(i,c),u=f>0?i>c?Pt:kn:null,d=u?u===Pt?s.length:a.length:0);const m=u===Pt&&/\b(transform|all)(,|$)/.test(r(`${Pt}Property`).toString());return{type:u,timeout:f,propCount:d,hasTransform:m}}function Ys(e,t){for(;e.lengthJs(n)+Js(e[r])))}function Js(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function $u(){return document.body.offsetHeight}function Nu(e,t,n){const r=e[Kn];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const ns=Symbol("_vod"),Dr={beforeMount(e,{value:t},{transition:n}){e[ns]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):Pn(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),Pn(e,!0),r.enter(e)):r.leave(e,()=>{Pn(e,!1)}):Pn(e,t))},beforeUnmount(e,{value:t}){Pn(e,t)}};function Pn(e,t){e.style.display=t?e[ns]:"none"}function Hu(e,t,n){const r=e.style,o=ve(n);if(n&&!o){if(t&&!ve(t))for(const s in t)n[s]==null&&ko(r,s,"");for(const s in n)ko(r,s,n[s])}else{const s=r.display;o?t!==n&&(r.cssText=n):t&&e.removeAttribute("style"),ns in e&&(r.display=s)}}const Qs=/\s*!important$/;function ko(e,t,n){if(Q(n))n.forEach(r=>ko(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Fu(e,t);Qs.test(n)?e.setProperty(nn(r),n.replace(Qs,""),"important"):e[r]=n}}const Zs=["Webkit","Moz","ms"],oo={};function Fu(e,t){const n=oo[t];if(n)return n;let r=bt(t);if(r!=="filter"&&r in e)return oo[t]=r;r=zr(r);for(let o=0;oso||(Wu.then(()=>so=0),so=Date.now());function qu(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;st(Gu(r,n.value),t,5,[r])};return n.value=e,n.attached=Ku(),n}function Gu(e,t){if(Q(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>o=>!o._stopped&&r&&r(o))}else return t}const ni=/^on[a-z]/,Yu=(e,t,n,r,o=!1,s,i,l,a)=>{t==="class"?Nu(e,r,o):t==="style"?Hu(e,n,r):Yn(t)?No(t)||ju(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Ju(e,t,r,o))?zu(e,t,r,s,i,l,a):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Bu(e,t,r,o))};function Ju(e,t,n,r){return r?!!(t==="innerHTML"||t==="textContent"||t in e&&ni.test(t)&&ae(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||ni.test(t)&&ve(n)?!1:t in e}const ri=e=>{const t=e.props["onUpdate:modelValue"]||!1;return Q(t)?n=>Er(t,n):t};function Qu(e){e.target.composing=!0}function oi(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const io=Symbol("_assign"),Wv={created(e,{modifiers:{lazy:t,trim:n,number:r}},o){e[io]=ri(o);const s=r||o.props&&o.props.type==="number";an(e,t?"change":"input",i=>{if(i.target.composing)return;let l=e.value;n&&(l=l.trim()),s&&(l=vo(l)),e[io](l)}),n&&an(e,"change",()=>{e.value=e.value.trim()}),t||(an(e,"compositionstart",Qu),an(e,"compositionend",oi),an(e,"change",oi))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:o}},s){if(e[io]=ri(s),e.composing||document.activeElement===e&&e.type!=="range"&&(n||r&&e.value.trim()===t||(o||e.type==="number")&&vo(e.value)===t))return;const i=t??"";e.value!==i&&(e.value=i)}},Zu=["ctrl","shift","alt","meta"],Xu={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Zu.some(n=>e[`${n}Key`]&&!t.includes(n))},Kv=(e,t)=>(n,...r)=>{for(let o=0;on=>{if(!("key"in n))return;const r=nn(n.key);if(t.some(o=>o===r||ef[o]===r))return e(n)},nf=He({patchProp:Yu},Ru);let lo,si=!1;function rf(){return lo=si?lo:uu(nf),si=!0,lo}const of=(...e)=>{const t=rf().createApp(...e),{mount:n}=t;return t.mount=r=>{const o=sf(r);if(o)return n(o,!0,o instanceof SVGElement)},t};function sf(e){return ve(e)?document.querySelector(e):e}const lf="modulepreload",af=function(e){return"/MicroCityNotes/"+e},ii={},I=function(t,n,r){if(!n||n.length===0)return t();const o=document.getElementsByTagName("link");return Promise.all(n.map(s=>{if(s=af(s),s in ii)return;ii[s]=!0;const i=s.endsWith(".css"),l=i?'[rel="stylesheet"]':"";if(!!r)for(let u=o.length-1;u>=0;u--){const f=o[u];if(f.href===s&&(!i||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${l}`))return;const c=document.createElement("link");if(c.rel=i?"stylesheet":lf,i||(c.as="script",c.crossOrigin=""),c.href=s,document.head.appendChild(c),i)return new Promise((u,f)=>{c.addEventListener("load",u),c.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${s}`)))})})).then(()=>t()).catch(s=>{const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=s,window.dispatchEvent(i),!i.defaultPrevented)throw s})},cf={"v-8daa1a0e":()=>I(()=>import("./index.html-ijEhgMTC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4ee3d2cc":()=>I(()=>import("./1.1_what_microcity_can_do.html-XJqtRZkC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-498b1a32":()=>I(()=>import("./2.1_showing_a_world_map.html-nIk_uI4l.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0f6857b8":()=>I(()=>import("./2.2_searching_for_countries.html-eO0KcF_W.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-27daeef9":()=>I(()=>import("./3.1_ui_overview.html-9iOHDqCk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3c8d6dee":()=>I(()=>import("./3.2_vector_shapes.html-LHAJ_5Cg.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a2d64ac":()=>I(()=>import("./3.3_raster_grids.html-xKWq9pqo.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-26445025":()=>I(()=>import("./3.4_3d_scenes.html-SpQlhrPf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b2a5ca98":()=>I(()=>import("./3.5_tables.html-zF8D9g8c.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8532c374":()=>I(()=>import("./3.6_maps_and_layers.html-XuAmYobJ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-656b8bd0":()=>I(()=>import("./3.7_modules.html-heS1MNUm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4c59099a":()=>I(()=>import("./4.1_si_overview.html-umQYu3pM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-68871b76":()=>I(()=>import("./4.2_ui_control.html-P4QU671J.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3c0f83c0":()=>I(()=>import("./4.3_shapes_and_tables.html-ujzvaZYV.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c670a3a8":()=>I(()=>import("./4.4_grids.html-sbNpid1M.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-672fdfba":()=>I(()=>import("./4.5_3d_scenes.html-FkF6l2hE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-34511d54":()=>I(()=>import("./4.6_networks.html-O88jEbX0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6802fed2":()=>I(()=>import("./4.7_des_simulations.html-Ztj4rB4B.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-64fe0a3e":()=>I(()=>import("./4.8_mixed_integer_programming.html-bEUkQ8el.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-147825fb":()=>I(()=>import("./index.html-ps9YKXkA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-12c828e2":()=>I(()=>import("./3d-objects-en.html-rNfsYRE-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0be8554c":()=>I(()=>import("./3d-objects.html-0syC6c1Y.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d47089cc":()=>I(()=>import("./3d-scene-en.html-iUVl-UL0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41e82e22":()=>I(()=>import("./3d-scene.html-_tzv6BUx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e8b6c472":()=>I(()=>import("./index.html-nFm7KTWc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7fd381e2":()=>I(()=>import("./cy-simulation.html-YeLzi-Ut.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-44b81126":()=>I(()=>import("./debug.html-mpPtl8CL.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ae81571":()=>I(()=>import("./event-scheduling-en.html-gy_6i2Mu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0ceacb2b":()=>I(()=>import("./event-scheduling.html-o4tYPrMB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8138aba4":()=>I(()=>import("./lp.html-NKzjcq8T.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ed3d82b0":()=>I(()=>import("./lua.html-zCkaxI4j.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6eb109a0":()=>I(()=>import("./mip-en.html-23DYx6JR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-dfdf5468":()=>I(()=>import("./mip.html-B6IhijhB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-16cb829c":()=>I(()=>import("./network.html-td-Kb3D8.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c58fd9e0":()=>I(()=>import("./oop.html-azlXcYwP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f610fd24":()=>I(()=>import("./plots.html-JiB_VWcB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-19652be0":()=>I(()=>import("./timelapse.html-hdyuE7Lk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6bb8b8e5":()=>I(()=>import("./tools.html-zf97O5Kc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-77d2e8b7":()=>I(()=>import("./versions.html-HjNHjtrH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-385f9c3c":()=>I(()=>import("./visualization.html-xF8N-_EY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-187abc41":()=>I(()=>import("./warehouse-simulation.html-GfcmApNM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-51d74d37":()=>I(()=>import("./web-ui-en.html-FPAIksJ9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ae3cdb6":()=>I(()=>import("./web-ui.html-cjOV8UTz.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-67bbbff8":()=>I(()=>import("./index.html-hph7Dv3o.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3706649a":()=>I(()=>import("./404.html-O1A74s9P.js"),__vite__mapDeps([])).then(({data:e})=>e)},uf=JSON.parse('{"base":"/MicroCityNotes/","lang":"en-US","title":"MicroCity笔记","description":"记录MicroCity的学习过程并提供快捷的参考","head":[["meta",{"name":"keywords","content":"MicroCity,笔记,文档"}],["link",{"rel":"icon","href":"./images/icon_microcity.png"}],["link",{"rel":"manifest","href":"/MicroCityNotes/manifest.webmanifest","crossorigin":"use-credentials"}],["meta",{"name":"theme-color","content":"#46bd87"}],["meta",{"name":"viewport","content":"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"}]],"locales":{"/":{"lang":"zh-CN"}}}');var ff=([e,t,n])=>e==="meta"&&t.name?`${e}.${t.name}`:["title","base"].includes(e)?e:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,t,n]),df=e=>{const t=new Set,n=[];return e.forEach(r=>{const o=ff(r);t.has(o)||(t.add(o),n.push(r))}),n},rr=e=>/^(https?:)?\/\//.test(e),hf=e=>/^[a-z][a-z0-9+.-]*:/.test(e),rs=e=>Object.prototype.toString.call(e)==="[object Object]",Dl=e=>e[e.length-1]==="/"?e.slice(0,-1):e,Ml=e=>e[0]==="/"?e.slice(1):e,$l=(e,t)=>{const n=Object.keys(e).sort((r,o)=>{const s=o.split("/").length-r.split("/").length;return s!==0?s:o.length-r.length});for(const r of n)if(t.startsWith(r))return r;return"/"};const Nl={"v-8daa1a0e":oe(()=>I(()=>import("./index.html-lZExp6Yz.js"),__vite__mapDeps([0,1,2,3]))),"v-4ee3d2cc":oe(()=>I(()=>import("./1.1_what_microcity_can_do.html-FdnWldjW.js"),__vite__mapDeps([]))),"v-498b1a32":oe(()=>I(()=>import("./2.1_showing_a_world_map.html-MkZfvyzh.js"),__vite__mapDeps([4,2,5,6,7]))),"v-0f6857b8":oe(()=>I(()=>import("./2.2_searching_for_countries.html-JlV76Wlp.js"),__vite__mapDeps([8,1]))),"v-27daeef9":oe(()=>I(()=>import("./3.1_ui_overview.html-w-bvZnF-.js"),__vite__mapDeps([]))),"v-3c8d6dee":oe(()=>I(()=>import("./3.2_vector_shapes.html-Ifn-q5O4.js"),__vite__mapDeps([9,5,6,7]))),"v-6a2d64ac":oe(()=>I(()=>import("./3.3_raster_grids.html-RHwKcATS.js"),__vite__mapDeps([10,5,7,11]))),"v-26445025":oe(()=>I(()=>import("./3.4_3d_scenes.html-f5Qwa3ic.js"),__vite__mapDeps([12,5]))),"v-b2a5ca98":oe(()=>I(()=>import("./3.5_tables.html-p-Cvt07d.js"),__vite__mapDeps([13,5]))),"v-8532c374":oe(()=>I(()=>import("./3.6_maps_and_layers.html-0HlObXq2.js"),__vite__mapDeps([14,7,11]))),"v-656b8bd0":oe(()=>I(()=>import("./3.7_modules.html-q0PqEjdM.js"),__vite__mapDeps([15,1,5,3]))),"v-4c59099a":oe(()=>I(()=>import("./4.1_si_overview.html-iNqEh7u3.js"),__vite__mapDeps([16,1,2]))),"v-68871b76":oe(()=>I(()=>import("./4.2_ui_control.html-PXdKdANV.js"),__vite__mapDeps([17,1]))),"v-3c0f83c0":oe(()=>I(()=>import("./4.3_shapes_and_tables.html-kM2JYXcO.js"),__vite__mapDeps([18,1]))),"v-c670a3a8":oe(()=>I(()=>import("./4.4_grids.html-7i5R0Lmo.js"),__vite__mapDeps([19,1]))),"v-672fdfba":oe(()=>I(()=>import("./4.5_3d_scenes.html-2AMaq24g.js"),__vite__mapDeps([20,1]))),"v-34511d54":oe(()=>I(()=>import("./4.6_networks.html-PK_mfd9Y.js"),__vite__mapDeps([21,1]))),"v-6802fed2":oe(()=>I(()=>import("./4.7_des_simulations.html-8bSUiGUz.js"),__vite__mapDeps([22,1]))),"v-64fe0a3e":oe(()=>I(()=>import("./4.8_mixed_integer_programming.html-E59_LnJJ.js"),__vite__mapDeps([23,1]))),"v-147825fb":oe(()=>I(()=>import("./index.html-8_XflqQA.js"),__vite__mapDeps([]))),"v-12c828e2":oe(()=>I(()=>import("./3d-objects-en.html-7DC5k-lZ.js"),__vite__mapDeps([24,25]))),"v-0be8554c":oe(()=>I(()=>import("./3d-objects.html-lKAwFYq5.js"),__vite__mapDeps([26,25]))),"v-d47089cc":oe(()=>I(()=>import("./3d-scene-en.html-M1ONxEpk.js"),__vite__mapDeps([27,28]))),"v-41e82e22":oe(()=>I(()=>import("./3d-scene.html-A33RmZzw.js"),__vite__mapDeps([29,28]))),"v-e8b6c472":oe(()=>I(()=>import("./index.html-HwGLrUxL.js"),__vite__mapDeps([]))),"v-7fd381e2":oe(()=>I(()=>import("./cy-simulation.html-bcA0fx8Y.js"),__vite__mapDeps([]))),"v-44b81126":oe(()=>I(()=>import("./debug.html-yFg7dMCo.js"),__vite__mapDeps([]))),"v-1ae81571":oe(()=>I(()=>import("./event-scheduling-en.html-gRProVKn.js"),__vite__mapDeps([30,31]))),"v-0ceacb2b":oe(()=>I(()=>import("./event-scheduling.html-7ezvA1AX.js"),__vite__mapDeps([32,31]))),"v-8138aba4":oe(()=>I(()=>import("./lp.html-I7wRJlfF.js"),__vite__mapDeps([]))),"v-ed3d82b0":oe(()=>I(()=>import("./lua.html-x5twFLDp.js"),__vite__mapDeps([]))),"v-6eb109a0":oe(()=>I(()=>import("./mip-en.html-IS2AhQjv.js"),__vite__mapDeps([]))),"v-dfdf5468":oe(()=>I(()=>import("./mip.html-Jt_OOSuJ.js"),__vite__mapDeps([]))),"v-16cb829c":oe(()=>I(()=>import("./network.html-m23VzkXJ.js"),__vite__mapDeps([]))),"v-c58fd9e0":oe(()=>I(()=>import("./oop.html-3LUP3-Yz.js"),__vite__mapDeps([]))),"v-f610fd24":oe(()=>I(()=>import("./plots.html-ODP8nuzQ.js"),__vite__mapDeps([]))),"v-19652be0":oe(()=>I(()=>import("./timelapse.html-mpQRHhbv.js"),__vite__mapDeps([]))),"v-6bb8b8e5":oe(()=>I(()=>import("./tools.html-kWg64VtA.js"),__vite__mapDeps([]))),"v-77d2e8b7":oe(()=>I(()=>import("./versions.html-9uZsLBnu.js"),__vite__mapDeps([]))),"v-385f9c3c":oe(()=>I(()=>import("./visualization.html--w3hFG24.js"),__vite__mapDeps([]))),"v-187abc41":oe(()=>I(()=>import("./warehouse-simulation.html-3NwF3MxT.js"),__vite__mapDeps([]))),"v-51d74d37":oe(()=>I(()=>import("./web-ui-en.html-9hWYZBEN.js"),__vite__mapDeps([33,34,31]))),"v-1ae3cdb6":oe(()=>I(()=>import("./web-ui.html-zrAeLt4a.js"),__vite__mapDeps([35,34,31]))),"v-67bbbff8":oe(()=>I(()=>import("./index.html-ciQEBxId.js"),__vite__mapDeps([]))),"v-3706649a":oe(()=>I(()=>import("./404.html-G5wmh19c.js"),__vite__mapDeps([])))};var pf=Symbol(""),Hl=Symbol(""),mf=Zn({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),Ft=()=>{const e=Se(Hl);if(!e)throw new Error("pageData() is called without provider.");return e},Fl=Symbol(""),_t=()=>{const e=Se(Fl);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},Bl=Symbol(""),vf=()=>{const e=Se(Bl);if(!e)throw new Error("usePageHead() is called without provider.");return e},gf=Symbol(""),zl=Symbol(""),Vl=()=>{const e=Se(zl);if(!e)throw new Error("usePageLang() is called without provider.");return e},jl=Symbol(""),_f=()=>{const e=Se(jl);if(!e)throw new Error("usePageLayout() is called without provider.");return e},bf=_e(cf),os=Symbol(""),or=()=>{const e=Se(os);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},un=_e(uf),Ul=()=>un,Wl=Symbol(""),ss=()=>{const e=Se(Wl);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},yf=Symbol(""),Ef="Layout",wf="NotFound",wt=Qn({resolveLayouts:e=>e.reduce((t,n)=>({...t,...n.layouts}),{}),resolvePageData:async e=>{const t=bf.value[e];return await(t==null?void 0:t())??mf},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,n)=>{const r=ve(t.description)?t.description:n.description,o=[...Q(t.head)?t.head:[],...n.head,["title",{},e],["meta",{name:"description",content:r}]];return df(o)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(n=>!!n).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||"en-US",resolvePageLayout:(e,t)=>{let n;if(e.path){const r=e.frontmatter.layout;ve(r)?n=r:n=Ef}else n=wf;return t[n]},resolveRouteLocale:(e,t)=>$l(e,t),resolveSiteLocaleData:(e,t)=>({...e,...e.locales[t]})}),is=ce({name:"ClientOnly",setup(e,t){const n=_e(!1);return De(()=>{n.value=!0}),()=>{var r,o;return n.value?(o=(r=t.slots).default)==null?void 0:o.call(r):null}}}),Cf=ce({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=Ft(),n=V(()=>Nl[e.pageKey||t.value.key]);return()=>n.value?te(n.value):te("div","404 Not Found")}}),it=(e={})=>e,Yr=e=>rr(e)?e:`/MicroCityNotes/${Ml(e)}`;function Kl(e,t,n){var r,o,s;t===void 0&&(t=50),n===void 0&&(n={});var i=(r=n.isImmediate)!=null&&r,l=(o=n.callback)!=null&&o,a=n.maxWait,c=Date.now(),u=[];function f(){if(a!==void 0){var m=Date.now()-c;if(m+t>=a)return a-m}return t}var d=function(){var m=[].slice.call(arguments),b=this;return new Promise(function(w,L){var A=i&&s===void 0;if(s!==void 0&&clearTimeout(s),s=setTimeout(function(){if(s=void 0,c=Date.now(),!i){var g=e.apply(b,m);l&&l(g),u.forEach(function(y){return(0,y.resolve)(g)}),u=[]}},f()),A){var S=e.apply(b,m);return l&&l(S),w(S)}u.push({resolve:w,reject:L})})};return d.cancel=function(m){s!==void 0&&clearTimeout(s),u.forEach(function(b){return(0,b.reject)(m)}),u=[]},d}/*! - * vue-router v4.2.5 - * (c) 2023 Eduardo San Martin Morote - * @license MIT - */const cn=typeof window<"u";function Tf(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const ge=Object.assign;function ao(e,t){const n={};for(const r in t){const o=t[r];n[r]=ht(o)?o.map(e):e(o)}return n}const Fn=()=>{},ht=Array.isArray,Lf=/\/$/,xf=e=>e.replace(Lf,"");function co(e,t,n="/"){let r,o={},s="",i="";const l=t.indexOf("#");let a=t.indexOf("?");return l=0&&(a=-1),a>-1&&(r=t.slice(0,a),s=t.slice(a+1,l>-1?l:t.length),o=e(s)),l>-1&&(r=r||t.slice(0,l),i=t.slice(l,t.length)),r=Pf(r??t,n),{fullPath:r+(s&&"?")+s+i,path:r,query:o,hash:i}}function Af(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function li(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Sf(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&En(t.matched[r],n.matched[o])&&ql(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function En(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function ql(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!kf(e[n],t[n]))return!1;return!0}function kf(e,t){return ht(e)?ai(e,t):ht(t)?ai(t,e):e===t}function ai(e,t){return ht(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function Pf(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),o=r[r.length-1];(o===".."||o===".")&&r.push("");let s=n.length-1,i,l;for(i=0;i1&&s--;else break;return n.slice(0,s).join("/")+"/"+r.slice(i-(i===r.length?1:0)).join("/")}var qn;(function(e){e.pop="pop",e.push="push"})(qn||(qn={}));var Bn;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Bn||(Bn={}));function Rf(e){if(!e)if(cn){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),xf(e)}const Of=/^[^#]+#/;function If(e,t){return e.replace(Of,"#")+t}function Df(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const Jr=()=>({left:window.pageXOffset,top:window.pageYOffset});function Mf(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),o=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=Df(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function ci(e,t){return(history.state?history.state.position-t:-1)+e}const Po=new Map;function $f(e,t){Po.set(e,t)}function Nf(e){const t=Po.get(e);return Po.delete(e),t}let Hf=()=>location.protocol+"//"+location.host;function Gl(e,t){const{pathname:n,search:r,hash:o}=t,s=e.indexOf("#");if(s>-1){let l=o.includes(e.slice(s))?e.slice(s).length:1,a=o.slice(l);return a[0]!=="/"&&(a="/"+a),li(a,"")}return li(n,e)+r+o}function Ff(e,t,n,r){let o=[],s=[],i=null;const l=({state:d})=>{const m=Gl(e,location),b=n.value,w=t.value;let L=0;if(d){if(n.value=m,t.value=d,i&&i===b){i=null;return}L=w?d.position-w.position:0}else r(m);o.forEach(A=>{A(n.value,b,{delta:L,type:qn.pop,direction:L?L>0?Bn.forward:Bn.back:Bn.unknown})})};function a(){i=n.value}function c(d){o.push(d);const m=()=>{const b=o.indexOf(d);b>-1&&o.splice(b,1)};return s.push(m),m}function u(){const{history:d}=window;d.state&&d.replaceState(ge({},d.state,{scroll:Jr()}),"")}function f(){for(const d of s)d();s=[],window.removeEventListener("popstate",l),window.removeEventListener("beforeunload",u)}return window.addEventListener("popstate",l),window.addEventListener("beforeunload",u,{passive:!0}),{pauseListeners:a,listen:c,destroy:f}}function ui(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?Jr():null}}function Bf(e){const{history:t,location:n}=window,r={value:Gl(e,n)},o={value:t.state};o.value||s(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function s(a,c,u){const f=e.indexOf("#"),d=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+a:Hf()+e+a;try{t[u?"replaceState":"pushState"](c,"",d),o.value=c}catch(m){console.error(m),n[u?"replace":"assign"](d)}}function i(a,c){const u=ge({},t.state,ui(o.value.back,a,o.value.forward,!0),c,{position:o.value.position});s(a,u,!0),r.value=a}function l(a,c){const u=ge({},o.value,t.state,{forward:a,scroll:Jr()});s(u.current,u,!0);const f=ge({},ui(r.value,a,null),{position:u.position+1},c);s(a,f,!1),r.value=a}return{location:r,state:o,push:l,replace:i}}function zf(e){e=Rf(e);const t=Bf(e),n=Ff(e,t.state,t.location,t.replace);function r(s,i=!0){i||n.pauseListeners(),history.go(s)}const o=ge({location:"",base:e,go:r,createHref:If.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function Vf(e){return typeof e=="string"||e&&typeof e=="object"}function Yl(e){return typeof e=="string"||typeof e=="symbol"}const Ct={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},Jl=Symbol("");var fi;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(fi||(fi={}));function wn(e,t){return ge(new Error,{type:e,[Jl]:!0},t)}function Et(e,t){return e instanceof Error&&Jl in e&&(t==null||!!(e.type&t))}const di="[^/]+?",jf={sensitive:!1,strict:!1,start:!0,end:!0},Uf=/[.+*?^${}()[\]/\\]/g;function Wf(e,t){const n=ge({},jf,t),r=[];let o=n.start?"^":"";const s=[];for(const c of e){const u=c.length?[]:[90];n.strict&&!c.length&&(o+="/");for(let f=0;ft.length?t.length===1&&t[0]===80?1:-1:0}function qf(e,t){let n=0;const r=e.score,o=t.score;for(;n0&&t[t.length-1]<0}const Gf={type:0,value:""},Yf=/[a-zA-Z0-9_]/;function Jf(e){if(!e)return[[]];if(e==="/")return[[Gf]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(m){throw new Error(`ERR (${n})/"${c}": ${m}`)}let n=0,r=n;const o=[];let s;function i(){s&&o.push(s),s=[]}let l=0,a,c="",u="";function f(){c&&(n===0?s.push({type:0,value:c}):n===1||n===2||n===3?(s.length>1&&(a==="*"||a==="+")&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),s.push({type:1,value:c,regexp:u,repeatable:a==="*"||a==="+",optional:a==="*"||a==="?"})):t("Invalid state to consume buffer"),c="")}function d(){c+=a}for(;l{i(S)}:Fn}function i(u){if(Yl(u)){const f=r.get(u);f&&(r.delete(u),n.splice(n.indexOf(f),1),f.children.forEach(i),f.alias.forEach(i))}else{const f=n.indexOf(u);f>-1&&(n.splice(f,1),u.record.name&&r.delete(u.record.name),u.children.forEach(i),u.alias.forEach(i))}}function l(){return n}function a(u){let f=0;for(;f=0&&(u.record.path!==n[f].record.path||!Ql(u,n[f]));)f++;n.splice(f,0,u),u.record.name&&!mi(u)&&r.set(u.record.name,u)}function c(u,f){let d,m={},b,w;if("name"in u&&u.name){if(d=r.get(u.name),!d)throw wn(1,{location:u});w=d.record.name,m=ge(pi(f.params,d.keys.filter(S=>!S.optional).map(S=>S.name)),u.params&&pi(u.params,d.keys.map(S=>S.name))),b=d.stringify(m)}else if("path"in u)b=u.path,d=n.find(S=>S.re.test(b)),d&&(m=d.parse(b),w=d.record.name);else{if(d=f.name?r.get(f.name):n.find(S=>S.re.test(f.path)),!d)throw wn(1,{location:u,currentLocation:f});w=d.record.name,m=ge({},f.params,u.params),b=d.stringify(m)}const L=[];let A=d;for(;A;)L.unshift(A.record),A=A.parent;return{name:w,path:b,params:m,matched:L,meta:td(L)}}return e.forEach(u=>s(u)),{addRoute:s,resolve:c,removeRoute:i,getRoutes:l,getRecordMatcher:o}}function pi(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function Xf(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:ed(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function ed(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]=typeof n=="object"?n[r]:n;return t}function mi(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function td(e){return e.reduce((t,n)=>ge(t,n.meta),{})}function vi(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}function Ql(e,t){return t.children.some(n=>n===e||Ql(e,n))}const Zl=/#/g,nd=/&/g,rd=/\//g,od=/=/g,sd=/\?/g,Xl=/\+/g,id=/%5B/g,ld=/%5D/g,ea=/%5E/g,ad=/%60/g,ta=/%7B/g,cd=/%7C/g,na=/%7D/g,ud=/%20/g;function ls(e){return encodeURI(""+e).replace(cd,"|").replace(id,"[").replace(ld,"]")}function fd(e){return ls(e).replace(ta,"{").replace(na,"}").replace(ea,"^")}function Ro(e){return ls(e).replace(Xl,"%2B").replace(ud,"+").replace(Zl,"%23").replace(nd,"%26").replace(ad,"`").replace(ta,"{").replace(na,"}").replace(ea,"^")}function dd(e){return Ro(e).replace(od,"%3D")}function hd(e){return ls(e).replace(Zl,"%23").replace(sd,"%3F")}function pd(e){return e==null?"":hd(e).replace(rd,"%2F")}function Mr(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function md(e){const t={};if(e===""||e==="?")return t;const r=(e[0]==="?"?e.slice(1):e).split("&");for(let o=0;os&&Ro(s)):[r&&Ro(r)]).forEach(s=>{s!==void 0&&(t+=(t.length?"&":"")+n,s!=null&&(t+="="+s))})}return t}function vd(e){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=ht(r)?r.map(o=>o==null?null:""+o):r==null?r:""+r)}return t}const gd=Symbol(""),_i=Symbol(""),Qr=Symbol(""),as=Symbol(""),Oo=Symbol("");function Rn(){let e=[];function t(r){return e.push(r),()=>{const o=e.indexOf(r);o>-1&&e.splice(o,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Mt(e,t,n,r,o){const s=r&&(r.enterCallbacks[o]=r.enterCallbacks[o]||[]);return()=>new Promise((i,l)=>{const a=f=>{f===!1?l(wn(4,{from:n,to:t})):f instanceof Error?l(f):Vf(f)?l(wn(2,{from:t,to:f})):(s&&r.enterCallbacks[o]===s&&typeof f=="function"&&s.push(f),i())},c=e.call(r&&r.instances[o],t,n,a);let u=Promise.resolve(c);e.length<3&&(u=u.then(a)),u.catch(f=>l(f))})}function uo(e,t,n,r){const o=[];for(const s of e)for(const i in s.components){let l=s.components[i];if(!(t!=="beforeRouteEnter"&&!s.instances[i]))if(_d(l)){const c=(l.__vccOpts||l)[t];c&&o.push(Mt(c,n,r,s,i))}else{let a=l();o.push(()=>a.then(c=>{if(!c)return Promise.reject(new Error(`Couldn't resolve component "${i}" at "${s.path}"`));const u=Tf(c)?c.default:c;s.components[i]=u;const d=(u.__vccOpts||u)[t];return d&&Mt(d,n,r,s,i)()}))}}return o}function _d(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function bi(e){const t=Se(Qr),n=Se(as),r=V(()=>t.resolve(ne(e.to))),o=V(()=>{const{matched:a}=r.value,{length:c}=a,u=a[c-1],f=n.matched;if(!u||!f.length)return-1;const d=f.findIndex(En.bind(null,u));if(d>-1)return d;const m=yi(a[c-2]);return c>1&&yi(u)===m&&f[f.length-1].path!==m?f.findIndex(En.bind(null,a[c-2])):d}),s=V(()=>o.value>-1&&wd(n.params,r.value.params)),i=V(()=>o.value>-1&&o.value===n.matched.length-1&&ql(n.params,r.value.params));function l(a={}){return Ed(a)?t[ne(e.replace)?"replace":"push"](ne(e.to)).catch(Fn):Promise.resolve()}return{route:r,href:V(()=>r.value.href),isActive:s,isExactActive:i,navigate:l}}const bd=ce({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:bi,setup(e,{slots:t}){const n=Qn(bi(e)),{options:r}=Se(Qr),o=V(()=>({[Ei(e.activeClass,r.linkActiveClass,"router-link-active")]:n.isActive,[Ei(e.exactActiveClass,r.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const s=t.default&&t.default(n);return e.custom?s:te("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:o.value},s)}}}),yd=bd;function Ed(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function wd(e,t){for(const n in t){const r=t[n],o=e[n];if(typeof r=="string"){if(r!==o)return!1}else if(!ht(o)||o.length!==r.length||r.some((s,i)=>s!==o[i]))return!1}return!0}function yi(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Ei=(e,t,n)=>e??t??n,Cd=ce({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const r=Se(Oo),o=V(()=>e.route||r.value),s=Se(_i,0),i=V(()=>{let c=ne(s);const{matched:u}=o.value;let f;for(;(f=u[c])&&!f.components;)c++;return c}),l=V(()=>o.value.matched[i.value]);Ht(_i,V(()=>i.value+1)),Ht(gd,l),Ht(Oo,o);const a=_e();return Qe(()=>[a.value,l.value,e.name],([c,u,f],[d,m,b])=>{u&&(u.instances[f]=c,m&&m!==u&&c&&c===d&&(u.leaveGuards.size||(u.leaveGuards=m.leaveGuards),u.updateGuards.size||(u.updateGuards=m.updateGuards))),c&&u&&(!m||!En(u,m)||!d)&&(u.enterCallbacks[f]||[]).forEach(w=>w(c))},{flush:"post"}),()=>{const c=o.value,u=e.name,f=l.value,d=f&&f.components[u];if(!d)return wi(n.default,{Component:d,route:c});const m=f.props[u],b=m?m===!0?c.params:typeof m=="function"?m(c):m:null,L=te(d,ge({},b,t,{onVnodeUnmounted:A=>{A.component.isUnmounted&&(f.instances[u]=null)},ref:a}));return wi(n.default,{Component:L,route:c})||L}}});function wi(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const ra=Cd;function Td(e){const t=Zf(e.routes,e),n=e.parseQuery||md,r=e.stringifyQuery||gi,o=e.history,s=Rn(),i=Rn(),l=Rn(),a=Ln(Ct);let c=Ct;cn&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=ao.bind(null,T=>""+T),f=ao.bind(null,pd),d=ao.bind(null,Mr);function m(T,j){let N,J;return Yl(T)?(N=t.getRecordMatcher(T),J=j):J=T,t.addRoute(J,N)}function b(T){const j=t.getRecordMatcher(T);j&&t.removeRoute(j)}function w(){return t.getRoutes().map(T=>T.record)}function L(T){return!!t.getRecordMatcher(T)}function A(T,j){if(j=ge({},j||a.value),typeof T=="string"){const v=co(n,T,j.path),E=t.resolve({path:v.path},j),x=o.createHref(v.fullPath);return ge(v,E,{params:d(E.params),hash:Mr(v.hash),redirectedFrom:void 0,href:x})}let N;if("path"in T)N=ge({},T,{path:co(n,T.path,j.path).path});else{const v=ge({},T.params);for(const E in v)v[E]==null&&delete v[E];N=ge({},T,{params:f(v)}),j.params=f(j.params)}const J=t.resolve(N,j),ue=T.hash||"";J.params=u(d(J.params));const h=Af(r,ge({},T,{hash:fd(ue),path:J.path})),p=o.createHref(h);return ge({fullPath:h,hash:ue,query:r===gi?vd(T.query):T.query||{}},J,{redirectedFrom:void 0,href:p})}function S(T){return typeof T=="string"?co(n,T,a.value.path):ge({},T)}function g(T,j){if(c!==T)return wn(8,{from:j,to:T})}function y(T){return H(T)}function B(T){return y(ge(S(T),{replace:!0}))}function G(T){const j=T.matched[T.matched.length-1];if(j&&j.redirect){const{redirect:N}=j;let J=typeof N=="function"?N(T):N;return typeof J=="string"&&(J=J.includes("?")||J.includes("#")?J=S(J):{path:J},J.params={}),ge({query:T.query,hash:T.hash,params:"path"in J?{}:T.params},J)}}function H(T,j){const N=c=A(T),J=a.value,ue=T.state,h=T.force,p=T.replace===!0,v=G(N);if(v)return H(ge(S(v),{state:typeof v=="object"?ge({},ue,v.state):ue,force:h,replace:p}),j||N);const E=N;E.redirectedFrom=j;let x;return!h&&Sf(r,J,N)&&(x=wn(16,{to:E,from:J}),Ve(J,J,!0,!1)),(x?Promise.resolve(x):k(E,J)).catch(P=>Et(P)?Et(P,2)?P:Me(P):K(P,E,J)).then(P=>{if(P){if(Et(P,2))return H(ge({replace:p},S(P.to),{state:typeof P.to=="object"?ge({},ue,P.to.state):ue,force:h}),j||E)}else P=C(E,J,!0,p,ue);return z(E,J,P),P})}function _(T,j){const N=g(T,j);return N?Promise.reject(N):Promise.resolve()}function O(T){const j=lt.values().next().value;return j&&typeof j.runWithContext=="function"?j.runWithContext(T):T()}function k(T,j){let N;const[J,ue,h]=Ld(T,j);N=uo(J.reverse(),"beforeRouteLeave",T,j);for(const v of J)v.leaveGuards.forEach(E=>{N.push(Mt(E,T,j))});const p=_.bind(null,T,j);return N.push(p),ke(N).then(()=>{N=[];for(const v of s.list())N.push(Mt(v,T,j));return N.push(p),ke(N)}).then(()=>{N=uo(ue,"beforeRouteUpdate",T,j);for(const v of ue)v.updateGuards.forEach(E=>{N.push(Mt(E,T,j))});return N.push(p),ke(N)}).then(()=>{N=[];for(const v of h)if(v.beforeEnter)if(ht(v.beforeEnter))for(const E of v.beforeEnter)N.push(Mt(E,T,j));else N.push(Mt(v.beforeEnter,T,j));return N.push(p),ke(N)}).then(()=>(T.matched.forEach(v=>v.enterCallbacks={}),N=uo(h,"beforeRouteEnter",T,j),N.push(p),ke(N))).then(()=>{N=[];for(const v of i.list())N.push(Mt(v,T,j));return N.push(p),ke(N)}).catch(v=>Et(v,8)?v:Promise.reject(v))}function z(T,j,N){l.list().forEach(J=>O(()=>J(T,j,N)))}function C(T,j,N,J,ue){const h=g(T,j);if(h)return h;const p=j===Ct,v=cn?history.state:{};N&&(J||p?o.replace(T.fullPath,ge({scroll:p&&v&&v.scroll},ue)):o.push(T.fullPath,ue)),a.value=T,Ve(T,j,N,p),Me()}let M;function re(){M||(M=o.listen((T,j,N)=>{if(!je.listening)return;const J=A(T),ue=G(J);if(ue){H(ge(ue,{replace:!0}),J).catch(Fn);return}c=J;const h=a.value;cn&&$f(ci(h.fullPath,N.delta),Jr()),k(J,h).catch(p=>Et(p,12)?p:Et(p,2)?(H(p.to,J).then(v=>{Et(v,20)&&!N.delta&&N.type===qn.pop&&o.go(-1,!1)}).catch(Fn),Promise.reject()):(N.delta&&o.go(-N.delta,!1),K(p,J,h))).then(p=>{p=p||C(J,h,!1),p&&(N.delta&&!Et(p,8)?o.go(-N.delta,!1):N.type===qn.pop&&Et(p,20)&&o.go(-1,!1)),z(J,h,p)}).catch(Fn)}))}let ie=Rn(),R=Rn(),Y;function K(T,j,N){Me(T);const J=R.list();return J.length?J.forEach(ue=>ue(T,j,N)):console.error(T),Promise.reject(T)}function ye(){return Y&&a.value!==Ct?Promise.resolve():new Promise((T,j)=>{ie.add([T,j])})}function Me(T){return Y||(Y=!T,re(),ie.list().forEach(([j,N])=>T?N(T):j()),ie.reset()),T}function Ve(T,j,N,J){const{scrollBehavior:ue}=e;if(!cn||!ue)return Promise.resolve();const h=!N&&Nf(ci(T.fullPath,0))||(J||!N)&&history.state&&history.state.scroll||null;return er().then(()=>ue(T,j,h)).then(p=>p&&Mf(p)).catch(p=>K(p,T,j))}const Oe=T=>o.go(T);let We;const lt=new Set,je={currentRoute:a,listening:!0,addRoute:m,removeRoute:b,hasRoute:L,getRoutes:w,resolve:A,options:e,push:y,replace:B,go:Oe,back:()=>Oe(-1),forward:()=>Oe(1),beforeEach:s.add,beforeResolve:i.add,afterEach:l.add,onError:R.add,isReady:ye,install(T){const j=this;T.component("RouterLink",yd),T.component("RouterView",ra),T.config.globalProperties.$router=j,Object.defineProperty(T.config.globalProperties,"$route",{enumerable:!0,get:()=>ne(a)}),cn&&!We&&a.value===Ct&&(We=!0,y(o.location).catch(ue=>{}));const N={};for(const ue in Ct)Object.defineProperty(N,ue,{get:()=>a.value[ue],enumerable:!0});T.provide(Qr,j),T.provide(as,tl(N)),T.provide(Oo,a);const J=T.unmount;lt.add(T),T.unmount=function(){lt.delete(T),lt.size<1&&(c=Ct,M&&M(),M=null,a.value=Ct,We=!1,Y=!1),J()}}};function ke(T){return T.reduce((j,N)=>j.then(()=>O(N)),Promise.resolve())}return je}function Ld(e,t){const n=[],r=[],o=[],s=Math.max(t.matched.length,e.matched.length);for(let i=0;iEn(c,l))?r.push(l):n.push(l));const a=e.matched[i];a&&(t.matched.find(c=>En(c,a))||o.push(a))}return[n,r,o]}function An(){return Se(Qr)}function rn(){return Se(as)}const xd=({headerLinkSelector:e,headerAnchorSelector:t,delay:n,offset:r=5})=>{const o=An(),i=Kl(()=>{var w,L;const l=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(l-0)d.some(S=>S.hash===A.hash));for(let A=0;A=(((w=S.parentElement)==null?void 0:w.offsetTop)??0)-r,B=!g||l<(((L=g.parentElement)==null?void 0:L.offsetTop)??0)-r;if(!(y&&B))continue;const H=decodeURIComponent(o.currentRoute.value.hash),_=decodeURIComponent(S.hash);if(H===_)return;if(f){for(let O=A+1;O{window.addEventListener("scroll",i)}),Kr(()=>{window.removeEventListener("scroll",i)})},Ci=async(e,t)=>{const{scrollBehavior:n}=e.options;e.options.scrollBehavior=void 0,await e.replace({query:e.currentRoute.value.query,hash:t}).finally(()=>e.options.scrollBehavior=n)},Ad="a.sidebar-item",Sd=".header-anchor",kd=300,Pd=5,Rd=it({setup(){xd({headerLinkSelector:Ad,headerAnchorSelector:Sd,delay:kd,offset:Pd})}}),Ti=()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,Od=()=>window.scrollTo({top:0,behavior:"smooth"}),Id=ce({name:"BackToTop",setup(){const e=_e(0),t=V(()=>e.value>300),n=Kl(()=>{e.value=Ti()},100);De(()=>{e.value=Ti(),window.addEventListener("scroll",()=>n())});const r=te("div",{class:"back-to-top",onClick:Od});return()=>te(xn,{name:"back-to-top"},()=>t.value?r:null)}}),Dd=it({rootComponents:[Id]}),Md=te("svg",{class:"external-link-icon",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"},[te("path",{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}),te("polygon",{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"})]),$d=ce({name:"ExternalLinkIcon",props:{locales:{type:Object,required:!1,default:()=>({})}},setup(e){const t=or(),n=V(()=>e.locales[t.value]??{openInNewWindow:"open in new window"});return()=>te("span",[Md,te("span",{class:"external-link-icon-sr-only"},n.value.openInNewWindow)])}});var Nd={"/":{openInNewWindow:"open in new window"}};const Hd=Nd,Fd=it({enhance({app:e}){e.component("ExternalLinkIcon",te($d,{locales:Hd}))}});/*! medium-zoom 1.1.0 | MIT License | https://github.com/francoischalifour/medium-zoom */var Gt=Object.assign||function(e){for(var t=1;t1&&arguments[1]!==void 0?arguments[1]:{},r=window.Promise||function(C){function M(){}C(M,M)},o=function(C){var M=C.target;if(M===O){b();return}g.indexOf(M)!==-1&&w({target:M})},s=function(){if(!(B||!_.original)){var C=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(G-C)>H.scrollOffset&&setTimeout(b,150)}},i=function(C){var M=C.key||C.keyCode;(M==="Escape"||M==="Esc"||M===27)&&b()},l=function(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=C;if(C.background&&(O.style.background=C.background),C.container&&C.container instanceof Object&&(M.container=Gt({},H.container,C.container)),C.template){var re=Cr(C.template)?C.template:document.querySelector(C.template);M.template=re}return H=Gt({},H,M),g.forEach(function(ie){ie.dispatchEvent(ln("medium-zoom:update",{detail:{zoom:k}}))}),k},a=function(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return e(Gt({},H,C))},c=function(){for(var C=arguments.length,M=Array(C),re=0;re0?M.reduce(function(R,Y){return[].concat(R,xi(Y))},[]):g;return ie.forEach(function(R){R.classList.remove("medium-zoom-image"),R.dispatchEvent(ln("medium-zoom:detach",{detail:{zoom:k}}))}),g=g.filter(function(R){return ie.indexOf(R)===-1}),k},f=function(C,M){var re=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return g.forEach(function(ie){ie.addEventListener("medium-zoom:"+C,M,re)}),y.push({type:"medium-zoom:"+C,listener:M,options:re}),k},d=function(C,M){var re=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return g.forEach(function(ie){ie.removeEventListener("medium-zoom:"+C,M,re)}),y=y.filter(function(ie){return!(ie.type==="medium-zoom:"+C&&ie.listener.toString()===M.toString())}),k},m=function(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=C.target,re=function(){var R={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},Y=void 0,K=void 0;if(H.container)if(H.container instanceof Object)R=Gt({},R,H.container),Y=R.width-R.left-R.right-H.margin*2,K=R.height-R.top-R.bottom-H.margin*2;else{var ye=Cr(H.container)?H.container:document.querySelector(H.container),Me=ye.getBoundingClientRect(),Ve=Me.width,Oe=Me.height,We=Me.left,lt=Me.top;R=Gt({},R,{width:Ve,height:Oe,left:We,top:lt})}Y=Y||R.width-H.margin*2,K=K||R.height-H.margin*2;var je=_.zoomedHd||_.original,ke=Li(je)?Y:je.naturalWidth||Y,T=Li(je)?K:je.naturalHeight||K,j=je.getBoundingClientRect(),N=j.top,J=j.left,ue=j.width,h=j.height,p=Math.min(Math.max(ue,ke),Y)/ue,v=Math.min(Math.max(h,T),K)/h,E=Math.min(p,v),x=(-J+(Y-ue)/2+H.margin+R.left)/E,P=(-N+(K-h)/2+H.margin+R.top)/E,U="scale("+E+") translate3d("+x+"px, "+P+"px, 0)";_.zoomed.style.transform=U,_.zoomedHd&&(_.zoomedHd.style.transform=U)};return new r(function(ie){if(M&&g.indexOf(M)===-1){ie(k);return}var R=function Ve(){B=!1,_.zoomed.removeEventListener("transitionend",Ve),_.original.dispatchEvent(ln("medium-zoom:opened",{detail:{zoom:k}})),ie(k)};if(_.zoomed){ie(k);return}if(M)_.original=M;else if(g.length>0){var Y=g;_.original=Y[0]}else{ie(k);return}if(_.original.dispatchEvent(ln("medium-zoom:open",{detail:{zoom:k}})),G=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,B=!0,_.zoomed=Vd(_.original),document.body.appendChild(O),H.template){var K=Cr(H.template)?H.template:document.querySelector(H.template);_.template=document.createElement("div"),_.template.appendChild(K.content.cloneNode(!0)),document.body.appendChild(_.template)}if(_.original.parentElement&&_.original.parentElement.tagName==="PICTURE"&&_.original.currentSrc&&(_.zoomed.src=_.original.currentSrc),document.body.appendChild(_.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),_.original.classList.add("medium-zoom-image--hidden"),_.zoomed.classList.add("medium-zoom-image--opened"),_.zoomed.addEventListener("click",b),_.zoomed.addEventListener("transitionend",R),_.original.getAttribute("data-zoom-src")){_.zoomedHd=_.zoomed.cloneNode(),_.zoomedHd.removeAttribute("srcset"),_.zoomedHd.removeAttribute("sizes"),_.zoomedHd.removeAttribute("loading"),_.zoomedHd.src=_.zoomed.getAttribute("data-zoom-src"),_.zoomedHd.onerror=function(){clearInterval(ye),console.warn("Unable to reach the zoom image target "+_.zoomedHd.src),_.zoomedHd=null,re()};var ye=setInterval(function(){_.zoomedHd.complete&&(clearInterval(ye),_.zoomedHd.classList.add("medium-zoom-image--opened"),_.zoomedHd.addEventListener("click",b),document.body.appendChild(_.zoomedHd),re())},10)}else if(_.original.hasAttribute("srcset")){_.zoomedHd=_.zoomed.cloneNode(),_.zoomedHd.removeAttribute("sizes"),_.zoomedHd.removeAttribute("loading");var Me=_.zoomedHd.addEventListener("load",function(){_.zoomedHd.removeEventListener("load",Me),_.zoomedHd.classList.add("medium-zoom-image--opened"),_.zoomedHd.addEventListener("click",b),document.body.appendChild(_.zoomedHd),re()})}else re()})},b=function(){return new r(function(C){if(B||!_.original){C(k);return}var M=function re(){_.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(_.zoomed),_.zoomedHd&&document.body.removeChild(_.zoomedHd),document.body.removeChild(O),_.zoomed.classList.remove("medium-zoom-image--opened"),_.template&&document.body.removeChild(_.template),B=!1,_.zoomed.removeEventListener("transitionend",re),_.original.dispatchEvent(ln("medium-zoom:closed",{detail:{zoom:k}})),_.original=null,_.zoomed=null,_.zoomedHd=null,_.template=null,C(k)};B=!0,document.body.classList.remove("medium-zoom--opened"),_.zoomed.style.transform="",_.zoomedHd&&(_.zoomedHd.style.transform=""),_.template&&(_.template.style.transition="opacity 150ms",_.template.style.opacity=0),_.original.dispatchEvent(ln("medium-zoom:close",{detail:{zoom:k}})),_.zoomed.addEventListener("transitionend",M)})},w=function(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=C.target;return _.original?b():m({target:M})},L=function(){return H},A=function(){return g},S=function(){return _.original},g=[],y=[],B=!1,G=0,H=n,_={original:null,zoomed:null,zoomedHd:null,template:null};Object.prototype.toString.call(t)==="[object Object]"?H=t:(t||typeof t=="string")&&c(t),H=Gt({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},H);var O=zd(H.background);document.addEventListener("click",o),document.addEventListener("keyup",i),document.addEventListener("scroll",s),window.addEventListener("resize",b);var k={open:m,close:b,toggle:w,update:l,clone:a,attach:c,detach:u,on:f,off:d,getOptions:L,getImages:A,getZoomedImage:S};return k};function Ud(e,t){t===void 0&&(t={});var n=t.insertAt;if(!(!e||typeof document>"u")){var r=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css",n==="top"&&r.firstChild?r.insertBefore(o,r.firstChild):r.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}var Wd=".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";Ud(Wd);const Kd=jd,qd=Symbol("mediumZoom");var Gd={};const Yd=".theme-default-content > img, .theme-default-content :not(a) > img",Jd=Gd,Qd=300,Zd=it({enhance({app:e,router:t}){const n=Kd(Jd);n.refresh=(r=Yd)=>{n.detach(),n.attach(r)},e.provide(qd,n),t.afterEach(()=>{setTimeout(()=>n.refresh(),Qd)})}});/** - * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress - * @license MIT - */const de={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},status:null,set:e=>{const t=de.isStarted();e=fo(e,de.settings.minimum,1),de.status=e===1?null:e;const n=de.render(!t),r=n.querySelector(de.settings.barSelector),o=de.settings.speed,s=de.settings.easing;return n.offsetWidth,Xd(i=>{vr(r,{transform:"translate3d("+Ai(e)+"%,0,0)",transition:"all "+o+"ms "+s}),e===1?(vr(n,{transition:"none",opacity:"1"}),n.offsetWidth,setTimeout(function(){vr(n,{transition:"all "+o+"ms linear",opacity:"0"}),setTimeout(function(){de.remove(),i()},o)},o)):setTimeout(()=>i(),o)}),de},isStarted:()=>typeof de.status=="number",start:()=>{de.status||de.set(0);const e=()=>{setTimeout(()=>{de.status&&(de.trickle(),e())},de.settings.trickleSpeed)};return de.settings.trickle&&e(),de},done:e=>!e&&!de.status?de:de.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=de.status;return t?(typeof e!="number"&&(e=(1-t)*fo(Math.random()*t,.1,.95)),t=fo(t+e,0,.994),de.set(t)):de.start()},trickle:()=>de.inc(Math.random()*de.settings.trickleRate),render:e=>{if(de.isRendered())return document.getElementById("nprogress");Si(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=de.settings.template;const n=t.querySelector(de.settings.barSelector),r=e?"-100":Ai(de.status||0),o=document.querySelector(de.settings.parent);return vr(n,{transition:"all 0 linear",transform:"translate3d("+r+"%,0,0)"}),o!==document.body&&Si(o,"nprogress-custom-parent"),o==null||o.appendChild(t),t},remove:()=>{ki(document.documentElement,"nprogress-busy"),ki(document.querySelector(de.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&eh(e)},isRendered:()=>!!document.getElementById("nprogress")},fo=(e,t,n)=>en?n:e,Ai=e=>(-1+e)*100,Xd=function(){const e=[];function t(){const n=e.shift();n&&n(t)}return function(n){e.push(n),e.length===1&&t()}}(),vr=function(){const e=["Webkit","O","Moz","ms"],t={};function n(i){return i.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(l,a){return a.toUpperCase()})}function r(i){const l=document.body.style;if(i in l)return i;let a=e.length;const c=i.charAt(0).toUpperCase()+i.slice(1);let u;for(;a--;)if(u=e[a]+c,u in l)return u;return i}function o(i){return i=n(i),t[i]??(t[i]=r(i))}function s(i,l,a){l=o(l),i.style[l]=a}return function(i,l){for(const a in l){const c=l[a];c!==void 0&&Object.prototype.hasOwnProperty.call(l,a)&&s(i,a,c)}}}(),oa=(e,t)=>(typeof e=="string"?e:cs(e)).indexOf(" "+t+" ")>=0,Si=(e,t)=>{const n=cs(e),r=n+t;oa(n,t)||(e.className=r.substring(1))},ki=(e,t)=>{const n=cs(e);if(!oa(e,t))return;const r=n.replace(" "+t+" "," ");e.className=r.substring(1,r.length-1)},cs=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),eh=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},th=()=>{De(()=>{const e=An(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(n=>{t.has(n.path)||de.start()}),e.afterEach(n=>{t.add(n.path),de.done()})})},nh=it({setup(){th()}}),rh=JSON.parse(`{"logo":"/images/icon_microcitynotes.png","navbar":[{"text":"首页","link":"/"},{"text":"笔记","link":"/notes/"},{"text":"文档","children":[{"text":"Desktop版文档","link":"/docs/","children":[{"text":"1.MicroCity介绍","link":"/docs/1.1_what_microcity_can_do"},{"text":"2.开始使用MicroCity","link":"/docs/2.1_showing_a_world_map"},{"text":"3.用户界面","link":"/docs/3.1_ui_overview"},{"text":"4.脚本编写","link":"/docs/4.1_si_overview"}]}]},{"text":"MicroCity项目仓库","children":[{"text":"github","children":[{"text":"MicroCity Desktop","link":"https://github.com/microcity/Desktop"},{"text":"MicroCity Web","link":"https://github.com/microcity/microcity.github.io"}]},{"text":"gitee","children":[{"text":"MicroCity Web","link":"https://gitee.com/microcity/microcity"},{"text":"MicroCity Desktop","link":"https://gitee.com/microcity/desktop"}]}]},{"text":"MicroCity Web","link":"https://microcity.gitee.io/"}],"sidebar":{"/":[{"text":"MicroCity文档","link":"/docs/","collapsible":true},{"text":"笔记","link":"/notes/","collapsible":true}],"/docs/":[{"text":"MicroCity文档","children":[{"text":"目录","link":"/docs/","children":[]},{"text":"1.MicroCity介绍","collapsible":true,"children":["/docs/1.1_what_microcity_can_do"]},{"text":"2.开始使用MicroCity","collapsible":true,"children":["/docs/2.1_showing_a_world_map","/docs/2.2_searching_for_countries"]},{"text":"3.用户界面","collapsible":true,"children":["/docs/3.1_ui_overview","/docs/3.2_vector_shapes","/docs/3.3_raster_grids","/docs/3.4_3d_scenes","/docs/3.5_tables","/docs/3.6_maps_and_layers","/docs/3.7_modules"]},{"text":"4.脚本编写","collapsible":true,"children":["/docs/4.1_si_overview","/docs/4.2_ui_control","/docs/4.3_shapes_and_tables","/docs/4.4_grids","/docs/4.5_3d_scenes","/docs/4.6_networks","/docs/4.7_des_simulations","/docs/4.8_mixed_integer_programming"]}]}],"/notes/":[{"text":"目录","link":"/notes/","children":[]},{"text":"通用知识","collapsible":true,"children":["/notes/lua","/notes/versions","/notes/timelapse","/notes/oop"]},{"text":"MicroCity","collapsible":true,"children":["/notes/visualization","/notes/network","/notes/lp"]},{"text":"MicroCityWeb","collapsible":true,"children":["/notes/web-ui","/notes/3d-scene","/notes/3d-objects","/notes/event-scheduling","/notes/mip","/notes/debug"]},{"text":"思路","collapsible":true,"children":["/notes/warehouse-simulation","/notes/plots","/notes/cy-simulation"]}]},"locales":{"/":{"selectLanguageName":"English"}},"colorMode":"auto","colorModeSwitch":true,"repo":null,"selectLanguageText":"Languages","selectLanguageAriaLabel":"Select language","sidebarDepth":2,"editLink":true,"editLinkText":"Edit this page","lastUpdated":true,"lastUpdatedText":"Last Updated","contributors":true,"contributorsText":"Contributors","notFound":["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],"backToHome":"Take me home","openInNewWindow":"open in new window","toggleColorMode":"toggle color mode","toggleSidebar":"toggle sidebar"}`),oh=_e(rh),sa=()=>oh,ia=Symbol(""),sh=()=>{const e=Se(ia);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},ih=(e,t)=>{const{locales:n,...r}=e;return{...r,...n==null?void 0:n[t]}},lh=it({enhance({app:e}){const t=sa(),n=e._context.provides[os],r=V(()=>ih(t.value,n.value));e.provide(ia,r),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return r.value}}})}}),ah=ce({__name:"Badge",props:{type:{type:String,required:!1,default:"tip"},text:{type:String,required:!1,default:""},vertical:{type:String,required:!1,default:void 0}},setup(e){return(t,n)=>(W(),ee("span",{class:Je(["badge",e.type]),style:Jn({verticalAlign:e.vertical})},[we(t.$slots,"default",{},()=>[jt(Ne(e.text),1)])],6))}}),Ae=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},ch=Ae(ah,[["__file","Badge.vue"]]);function Pi(e,t){var n;const r=Ln();return hl(()=>{r.value=e()},{...t,flush:(n=t==null?void 0:t.flush)!=null?n:"sync"}),Zn(r)}function uh(e,t){let n,r,o;const s=_e(!0),i=()=>{s.value=!0,o()};Qe(e,i,{flush:"sync"});const l=typeof t=="function"?t:t.get,a=typeof t=="function"?void 0:t.set,c=_c((u,f)=>(r=u,o=f,{get(){return s.value&&(n=l(),s.value=!1),r(),n},set(d){a==null||a(d)}}));return Object.isExtensible(c)&&(c.trigger=i),c}function la(e){return Ui()?(qa(e),!0):!1}function Ut(e){return typeof e=="function"?e():ne(e)}const fh=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const dh=Object.prototype.toString,hh=e=>dh.call(e)==="[object Object]",Io=()=>{};function aa(e,t){function n(...r){return new Promise((o,s)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(o).catch(s)})}return n}const ca=e=>e();function ph(e,t={}){let n,r,o=Io;const s=l=>{clearTimeout(l),o(),o=Io};return l=>{const a=Ut(e),c=Ut(t.maxWait);return n&&s(n),a<=0||c!==void 0&&c<=0?(r&&(s(r),r=null),Promise.resolve(l())):new Promise((u,f)=>{o=t.rejectOnCancel?f:u,c&&!r&&(r=setTimeout(()=>{n&&s(n),r=null,u(l())},c)),n=setTimeout(()=>{r&&s(r),r=null,u(l())},a)})}}function mh(e=ca){const t=_e(!0);function n(){t.value=!1}function r(){t.value=!0}const o=(...s)=>{t.value&&e(...s)};return{isActive:Zn(t),pause:n,resume:r,eventFilter:o}}function vh(e,t=200,n={}){return aa(ph(t,n),e)}function gh(e,t,n={}){const{eventFilter:r=ca,...o}=n;return Qe(e,aa(r,t),o)}function _h(e,t,n={}){const{eventFilter:r,...o}=n,{eventFilter:s,pause:i,resume:l,isActive:a}=mh(r);return{stop:gh(e,t,{...o,eventFilter:s}),pause:i,resume:l,isActive:a}}function bh(e,t=!0){es()?De(e):t?e():er(e)}function yh(e=!1,t={}){const{truthyValue:n=!0,falsyValue:r=!1}=t,o=Be(e),s=_e(e);function i(l){if(arguments.length)return s.value=l,s.value;{const a=Ut(n);return s.value=s.value===a?Ut(r):a,s.value}}return o?i:[s,i]}function Eh(e){var t;const n=Ut(e);return(t=n==null?void 0:n.$el)!=null?t:n}const $r=fh?window:void 0;function Nr(...e){let t,n,r,o;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,o]=e,t=$r):[t,n,r,o]=e,!t)return Io;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const s=[],i=()=>{s.forEach(u=>u()),s.length=0},l=(u,f,d,m)=>(u.addEventListener(f,d,m),()=>u.removeEventListener(f,d,m)),a=Qe(()=>[Eh(t),Ut(o)],([u,f])=>{if(i(),!u)return;const d=hh(f)?{...f}:f;s.push(...n.flatMap(m=>r.map(b=>l(u,m,b,d))))},{immediate:!0,flush:"post"}),c=()=>{a(),i()};return la(c),c}function wh(){const e=_e(!1);return es()&&De(()=>{e.value=!0}),e}function Ch(e){const t=wh();return V(()=>(t.value,!!e()))}function Th(e,t={}){const{window:n=$r}=t,r=Ch(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let o;const s=_e(!1),i=c=>{s.value=c.matches},l=()=>{o&&("removeEventListener"in o?o.removeEventListener("change",i):o.removeListener(i))},a=hl(()=>{r.value&&(l(),o=n.matchMedia(Ut(e)),"addEventListener"in o?o.addEventListener("change",i):o.addListener(i),s.value=o.matches)});return la(()=>{a(),l(),o=void 0}),s}const gr=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},_r="__vueuse_ssr_handlers__",Lh=xh();function xh(){return _r in gr||(gr[_r]=gr[_r]||{}),gr[_r]}function Ah(e,t){return Lh[e]||t}function Sh(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const kh={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Ri="vueuse-storage";function us(e,t,n,r={}){var o;const{flush:s="pre",deep:i=!0,listenToStorageChanges:l=!0,writeDefaults:a=!0,mergeDefaults:c=!1,shallow:u,window:f=$r,eventFilter:d,onError:m=O=>{console.error(O)},initOnMounted:b}=r,w=(u?Ln:_e)(typeof t=="function"?t():t);if(!n)try{n=Ah("getDefaultStorage",()=>{var O;return(O=$r)==null?void 0:O.localStorage})()}catch(O){m(O)}if(!n)return w;const L=Ut(t),A=Sh(L),S=(o=r.serializer)!=null?o:kh[A],{pause:g,resume:y}=_h(w,()=>B(w.value),{flush:s,deep:i,eventFilter:d});return f&&l&&bh(()=>{Nr(f,"storage",_),Nr(f,Ri,H),b&&_()}),b||_(),w;function B(O){try{if(O==null)n.removeItem(e);else{const k=S.write(O),z=n.getItem(e);z!==k&&(n.setItem(e,k),f&&f.dispatchEvent(new CustomEvent(Ri,{detail:{key:e,oldValue:z,newValue:k,storageArea:n}})))}}catch(k){m(k)}}function G(O){const k=O?O.newValue:n.getItem(e);if(k==null)return a&&L!==null&&n.setItem(e,S.write(L)),L;if(!O&&c){const z=S.read(k);return typeof c=="function"?c(z,L):A==="object"&&!Array.isArray(z)?{...L,...z}:z}else return typeof k!="string"?k:S.read(k)}function H(O){_(O.detail)}function _(O){if(!(O&&O.storageArea!==n)){if(O&&O.key==null){w.value=L;return}if(!(O&&O.key!==e)){g();try{(O==null?void 0:O.newValue)!==S.write(w.value)&&(w.value=G(O))}catch(k){m(k)}finally{O?er(y):y()}}}}}function Ph(e){return Th("(prefers-color-scheme: dark)",e)}const Rh=ce({name:"CodeGroup",slots:Object,setup(e,{slots:t}){const n=_e([]),r=_e(-1),o=us("vuepress-code-group",{}),s=V(()=>n.value.map(c=>c.innerText).join(","));De(()=>{Qe(()=>o.value[s.value],(c=-1)=>{r.value!==c&&(r.value=c)},{immediate:!0}),Qe(r,c=>{o.value[s.value]!==c&&(o.value[s.value]=c)})});const i=(c=r.value)=>{c{c>0?r.value=c-1:r.value=n.value.length-1,n.value[r.value].focus()},a=(c,u)=>{c.key===" "||c.key==="Enter"?(c.preventDefault(),r.value=u):c.key==="ArrowRight"?(c.preventDefault(),i(u)):c.key==="ArrowLeft"&&(c.preventDefault(),l(u))};return()=>{var u;const c=(((u=t.default)==null?void 0:u.call(t))||[]).filter(f=>f.type.name==="CodeGroupItem").map(f=>(f.props===null&&(f.props={}),f));return c.length===0?null:(r.value<0||r.value>c.length-1?(r.value=c.findIndex(f=>f.props.active===""||f.props.active===!0),r.value===-1&&(r.value=0)):c.forEach((f,d)=>{f.props.active=d===r.value}),te("div",{class:"code-group"},[te("div",{class:"code-group__nav"},te("ul",{class:"code-group__ul"},c.map((f,d)=>{const m=d===r.value;return te("li",{class:"code-group__li"},te("button",{ref:b=>{b&&(n.value[d]=b)},class:{"code-group__nav-tab":!0,"code-group__nav-tab-active":m},ariaPressed:m,ariaExpanded:m,onClick:()=>r.value=d,onKeydown:b=>a(b,d)},f.props.title))}))),c]))}}}),Oh=["aria-selected"],Ih=ce({name:"CodeGroupItem"}),Dh=ce({...Ih,props:{title:{type:String,required:!0},active:{type:Boolean,required:!1,default:!1}},setup(e){return(t,n)=>(W(),ee("div",{class:Je(["code-group-item",{"code-group-item__active":e.active}]),"aria-selected":e.active},[we(t.$slots,"default")],10,Oh))}}),Mh=Ae(Dh,[["__file","CodeGroupItem.vue"]]),$h=()=>sa(),Ge=()=>sh(),ua=Symbol(""),fs=()=>{const e=Se(ua);if(!e)throw new Error("useDarkMode() is called without provider.");return e},Nh=()=>{const e=Ge(),t=Ph(),n=us("vuepress-color-scheme",e.value.colorMode),r=V({get(){return e.value.colorModeSwitch?n.value==="auto"?t.value:n.value==="dark":e.value.colorMode==="dark"},set(o){o===t.value?n.value="auto":n.value=o?"dark":"light"}});Ht(ua,r),Hh(r)},Hh=e=>{const t=(n=e.value)=>{const r=window==null?void 0:window.document.querySelector("html");r==null||r.classList.toggle("dark",n)};De(()=>{Qe(e,t,{immediate:!0})}),nr(()=>t())},fa=(...e)=>{const n=An().resolve(...e),r=n.matched[n.matched.length-1];if(!(r!=null&&r.redirect))return n;const{redirect:o}=r,s=ae(o)?o(n):o,i=ve(s)?{path:s}:s;return fa({hash:n.hash,query:n.query,params:n.params,...i})},ds=e=>{const t=fa(encodeURI(e));return{text:t.meta.title||e,link:t.name==="404"?e:t.fullPath}};let ho=null,On=null;const Fh={wait:()=>ho,pending:()=>{ho=new Promise(e=>On=e)},resolve:()=>{On==null||On(),ho=null,On=null}},da=()=>Fh,ha=Symbol("sidebarItems"),hs=()=>{const e=Se(ha);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},Bh=()=>{const e=Ge(),t=_t(),n=V(()=>zh(t.value,e.value));Ht(ha,n)},zh=(e,t)=>{const n=e.sidebar??t.sidebar??"auto",r=e.sidebarDepth??t.sidebarDepth??2;return e.home||n===!1?[]:n==="auto"?jh(r):Q(n)?pa(n,r):rs(n)?Uh(n,r):[]},Vh=(e,t)=>({text:e.title,link:e.link,children:ps(e.children,t)}),ps=(e,t)=>t>0?e.map(n=>Vh(n,t-1)):[],jh=e=>{const t=Ft();return[{text:t.value.title,children:ps(t.value.headers,e)}]},pa=(e,t)=>{const n=rn(),r=Ft(),o=s=>{var l;let i;if(ve(s)?i=ds(s):i=s,i.children)return{...i,children:i.children.map(a=>o(a))};if(i.link===n.path){const a=((l=r.value.headers[0])==null?void 0:l.level)===1?r.value.headers[0].children:r.value.headers;return{...i,children:ps(a,t)}}return i};return e.map(s=>o(s))},Uh=(e,t)=>{const n=rn(),r=$l(e,n.path),o=e[r]??[];return pa(o,t)},Wh="719px",Kh={mobile:Wh};var Gn;(function(e){e.MOBILE="mobile"})(Gn||(Gn={}));var Ni;const qh={[Gn.MOBILE]:Number.parseInt((Ni=Kh.mobile)==null?void 0:Ni.replace("px",""),10)},ma=(e,t)=>{const n=qh[e];Number.isInteger(n)&&De(()=>{t(n),window.addEventListener("resize",()=>t(n),!1),window.addEventListener("orientationchange",()=>t(n),!1)})},Gh={},Yh={class:"theme-default-content"};function Jh(e,t){const n=yt("Content");return W(),ee("div",Yh,[se(n)])}const Qh=Ae(Gh,[["render",Jh],["__file","HomeContent.vue"]]),Zh={key:0,class:"features"},Xh=ce({__name:"HomeFeatures",setup(e){const t=_t(),n=V(()=>Q(t.value.features)?t.value.features:[]);return(r,o)=>n.value.length?(W(),ee("div",Zh,[(W(!0),ee(Ce,null,zt(n.value,s=>(W(),ee("div",{key:s.title,class:"feature"},[pe("h2",null,Ne(s.title),1),pe("p",null,Ne(s.details),1)]))),128))])):Pe("v-if",!0)}}),ep=Ae(Xh,[["__file","HomeFeatures.vue"]]),tp=["innerHTML"],np=["textContent"],rp=ce({__name:"HomeFooter",setup(e){const t=_t(),n=V(()=>t.value.footer),r=V(()=>t.value.footerHtml);return(o,s)=>n.value?(W(),ee(Ce,{key:0},[Pe(" eslint-disable-next-line vue/no-v-html "),r.value?(W(),ee("div",{key:0,class:"footer",innerHTML:n.value},null,8,tp)):(W(),ee("div",{key:1,class:"footer",textContent:Ne(n.value)},null,8,np))],64)):Pe("v-if",!0)}}),op=Ae(rp,[["__file","HomeFooter.vue"]]),sp=["href","rel","target","aria-label"],ip=ce({inheritAttrs:!1}),lp=ce({...ip,__name:"AutoLink",props:{item:{type:Object,required:!0}},setup(e){const t=e,n=rn(),r=Ul(),{item:o}=Go(t),s=V(()=>rr(o.value.link)),i=V(()=>!s.value&&hf(o.value.link)),l=V(()=>{if(!i.value){if(o.value.target)return o.value.target;if(s.value)return"_blank"}}),a=V(()=>l.value==="_blank"),c=V(()=>!s.value&&!i.value&&!a.value),u=V(()=>{if(!i.value){if(o.value.rel)return o.value.rel;if(a.value)return"noopener noreferrer"}}),f=V(()=>o.value.ariaLabel||o.value.text),d=V(()=>{const w=Object.keys(r.value.locales);return w.length?!w.some(L=>L===o.value.link):o.value.link!=="/"}),m=V(()=>d.value?n.path.startsWith(o.value.link):!1),b=V(()=>c.value?o.value.activeMatch?new RegExp(o.value.activeMatch).test(n.path):m.value:!1);return(w,L)=>{const A=yt("RouterLink"),S=yt("AutoLinkExternalIcon");return c.value?(W(),Re(A,So({key:0,class:{"router-link-active":b.value},to:ne(o).link,"aria-label":f.value},w.$attrs),{default:Fe(()=>[we(w.$slots,"before"),jt(" "+Ne(ne(o).text)+" ",1),we(w.$slots,"after")]),_:3},16,["class","to","aria-label"])):(W(),ee("a",So({key:1,class:"external-link",href:ne(o).link,rel:u.value,target:l.value,"aria-label":f.value},w.$attrs),[we(w.$slots,"before"),jt(" "+Ne(ne(o).text)+" ",1),a.value?(W(),Re(S,{key:0})):Pe("v-if",!0),we(w.$slots,"after")],16,sp))}}}),xt=Ae(lp,[["__file","AutoLink.vue"]]),ap={class:"hero"},cp={key:0,id:"main-title"},up={key:1,class:"description"},fp={key:2,class:"actions"},dp=ce({__name:"HomeHero",setup(e){const t=_t(),n=ss(),r=fs(),o=V(()=>r.value&&t.value.heroImageDark!==void 0?t.value.heroImageDark:t.value.heroImage),s=V(()=>t.value.heroAlt||l.value||"hero"),i=V(()=>t.value.heroHeight||280),l=V(()=>t.value.heroText===null?null:t.value.heroText||n.value.title||"Hello"),a=V(()=>t.value.tagline===null?null:t.value.tagline||n.value.description||"Welcome to your VuePress site"),c=V(()=>Q(t.value.actions)?t.value.actions.map(({text:f,link:d,type:m="primary"})=>({text:f,link:d,type:m})):[]),u=()=>{if(!o.value)return null;const f=te("img",{src:Yr(o.value),alt:s.value,height:i.value});return t.value.heroImageDark===void 0?f:te(is,()=>f)};return(f,d)=>(W(),ee("header",ap,[se(u),l.value?(W(),ee("h1",cp,Ne(l.value),1)):Pe("v-if",!0),a.value?(W(),ee("p",up,Ne(a.value),1)):Pe("v-if",!0),c.value.length?(W(),ee("p",fp,[(W(!0),ee(Ce,null,zt(c.value,m=>(W(),Re(xt,{key:m.text,class:Je(["action-button",[m.type]]),item:m},null,8,["class","item"]))),128))])):Pe("v-if",!0)]))}}),hp=Ae(dp,[["__file","HomeHero.vue"]]),pp={class:"home"},mp=ce({__name:"Home",setup(e){return(t,n)=>(W(),ee("main",pp,[se(hp),se(ep),se(Qh),se(op)]))}}),vp=Ae(mp,[["__file","Home.vue"]]),gp=ce({__name:"NavbarBrand",setup(e){const t=or(),n=ss(),r=Ge(),o=fs(),s=V(()=>r.value.home||t.value),i=V(()=>n.value.title),l=V(()=>o.value&&r.value.logoDark!==void 0?r.value.logoDark:r.value.logo),a=()=>{if(!l.value)return null;const c=te("img",{class:"logo",src:Yr(l.value),alt:i.value});return r.value.logoDark===void 0?c:te(is,()=>c)};return(c,u)=>{const f=yt("RouterLink");return W(),Re(f,{to:s.value},{default:Fe(()=>[se(a),i.value?(W(),ee("span",{key:0,class:Je(["site-name",{"can-hide":l.value}])},Ne(i.value),3)):Pe("v-if",!0)]),_:1},8,["to"])}}}),_p=Ae(gp,[["__file","NavbarBrand.vue"]]),bp=ce({__name:"DropdownTransition",setup(e){const t=r=>{r.style.height=r.scrollHeight+"px"},n=r=>{r.style.height=""};return(r,o)=>(W(),Re(xn,{name:"dropdown",onEnter:t,onAfterEnter:n,onBeforeLeave:t},{default:Fe(()=>[we(r.$slots,"default")]),_:3}))}}),va=Ae(bp,[["__file","DropdownTransition.vue"]]),yp=["aria-label"],Ep={class:"title"},wp=pe("span",{class:"arrow down"},null,-1),Cp=["aria-label"],Tp={class:"title"},Lp={class:"navbar-dropdown"},xp={class:"navbar-dropdown-subtitle"},Ap={key:1},Sp={class:"navbar-dropdown-subitem-wrapper"},kp=ce({__name:"NavbarDropdown",props:{item:{type:Object,required:!0}},setup(e){const t=e,{item:n}=Go(t),r=V(()=>n.value.ariaLabel||n.value.text),o=_e(!1),s=rn();Qe(()=>s.path,()=>{o.value=!1});const i=a=>{a.detail===0?o.value=!o.value:o.value=!1},l=(a,c)=>c[c.length-1]===a;return(a,c)=>(W(),ee("div",{class:Je(["navbar-dropdown-wrapper",{open:o.value}])},[pe("button",{class:"navbar-dropdown-title",type:"button","aria-label":r.value,onClick:i},[pe("span",Ep,Ne(ne(n).text),1),wp],8,yp),pe("button",{class:"navbar-dropdown-title-mobile",type:"button","aria-label":r.value,onClick:c[0]||(c[0]=u=>o.value=!o.value)},[pe("span",Tp,Ne(ne(n).text),1),pe("span",{class:Je(["arrow",o.value?"down":"right"])},null,2)],8,Cp),se(va,null,{default:Fe(()=>[kr(pe("ul",Lp,[(W(!0),ee(Ce,null,zt(ne(n).children,u=>(W(),ee("li",{key:u.text,class:"navbar-dropdown-item"},[u.children?(W(),ee(Ce,{key:0},[pe("h4",xp,[u.link?(W(),Re(xt,{key:0,item:u,onFocusout:f=>l(u,ne(n).children)&&u.children.length===0&&(o.value=!1)},null,8,["item","onFocusout"])):(W(),ee("span",Ap,Ne(u.text),1))]),pe("ul",Sp,[(W(!0),ee(Ce,null,zt(u.children,f=>(W(),ee("li",{key:f.link,class:"navbar-dropdown-subitem"},[se(xt,{item:f,onFocusout:d=>l(f,u.children)&&l(u,ne(n).children)&&(o.value=!1)},null,8,["item","onFocusout"])]))),128))])],64)):(W(),Re(xt,{key:1,item:u,onFocusout:f=>l(u,ne(n).children)&&(o.value=!1)},null,8,["item","onFocusout"]))]))),128))],512),[[Dr,o.value]])]),_:1})],2))}}),Pp=Ae(kp,[["__file","NavbarDropdown.vue"]]),Oi=e=>decodeURI(e).replace(/#.*$/,"").replace(/(index)?\.(md|html)$/,""),Rp=(e,t)=>{if(t.hash===e)return!0;const n=Oi(t.path),r=Oi(e);return n===r},ga=(e,t)=>e.link&&Rp(e.link,t)?!0:e.children?e.children.some(n=>ga(n,t)):!1,_a=e=>!rr(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,Op={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},Ip=({docsRepo:e,editLinkPattern:t})=>{if(t)return t;const n=_a(e);return n!==null?Op[n]:null},Dp=({docsRepo:e,docsBranch:t,docsDir:n,filePathRelative:r,editLinkPattern:o})=>{if(!r)return null;const s=Ip({docsRepo:e,editLinkPattern:o});return s?s.replace(/:repo/,rr(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,Ml(`${Dl(n)}/${r}`)):null},Mp={key:0,class:"navbar-items"},$p=ce({__name:"NavbarItems",setup(e){const t=()=>{const u=An(),f=or(),d=Ul(),m=ss(),b=$h(),w=Ge();return V(()=>{const L=Object.keys(d.value.locales);if(L.length<2)return[];const A=u.currentRoute.value.path,S=u.currentRoute.value.fullPath;return[{text:`${w.value.selectLanguageText}`,ariaLabel:`${w.value.selectLanguageAriaLabel??w.value.selectLanguageText}`,children:L.map(y=>{var k,z;const B=((k=d.value.locales)==null?void 0:k[y])??{},G=((z=b.value.locales)==null?void 0:z[y])??{},H=`${B.lang}`,_=G.selectLanguageName??H;let O;if(H===m.value.lang)O=S;else{const C=A.replace(f.value,y);u.getRoutes().some(M=>M.path===C)?O=S.replace(A,C):O=G.home??y}return{text:_,link:O}})}]})},n=()=>{const u=Ge(),f=V(()=>u.value.repo),d=V(()=>f.value?_a(f.value):null),m=V(()=>f.value&&!rr(f.value)?`https://github.com/${f.value}`:f.value),b=V(()=>m.value?u.value.repoLabel?u.value.repoLabel:d.value===null?"Source":d.value:null);return V(()=>!m.value||!b.value?[]:[{text:b.value,link:m.value}])},r=u=>ve(u)?ds(u):u.children?{...u,children:u.children.map(r)}:u,o=()=>{const u=Ge();return V(()=>(u.value.navbar||[]).map(r))},s=_e(!1),i=o(),l=t(),a=n(),c=V(()=>[...i.value,...l.value,...a.value]);return ma(Gn.MOBILE,u=>{window.innerWidthc.value.length?(W(),ee("nav",Mp,[(W(!0),ee(Ce,null,zt(c.value,d=>(W(),ee("div",{key:d.text,class:"navbar-item"},[d.children?(W(),Re(Pp,{key:0,item:d,class:Je(s.value?"mobile":"")},null,8,["item","class"])):(W(),Re(xt,{key:1,item:d},null,8,["item"]))]))),128))])):Pe("v-if",!0)}}),ba=Ae($p,[["__file","NavbarItems.vue"]]),Np=["title"],Hp={class:"icon",focusable:"false",viewBox:"0 0 32 32"},Fp=gu('',9),Bp=[Fp],zp={class:"icon",focusable:"false",viewBox:"0 0 32 32"},Vp=pe("path",{d:"M13.502 5.414a15.075 15.075 0 0 0 11.594 18.194a11.113 11.113 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1.002 1.002 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.072 13.072 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3z",fill:"currentColor"},null,-1),jp=[Vp],Up=ce({__name:"ToggleColorModeButton",setup(e){const t=Ge(),n=fs(),r=()=>{n.value=!n.value};return(o,s)=>(W(),ee("button",{class:"toggle-color-mode-button",title:ne(t).toggleColorMode,onClick:r},[kr((W(),ee("svg",Hp,Bp,512)),[[Dr,!ne(n)]]),kr((W(),ee("svg",zp,jp,512)),[[Dr,ne(n)]])],8,Np))}}),Wp=Ae(Up,[["__file","ToggleColorModeButton.vue"]]),Kp=["title"],qp=pe("div",{class:"icon","aria-hidden":"true"},[pe("span"),pe("span"),pe("span")],-1),Gp=[qp],Yp=ce({__name:"ToggleSidebarButton",emits:["toggle"],setup(e){const t=Ge();return(n,r)=>(W(),ee("div",{class:"toggle-sidebar-button",title:ne(t).toggleSidebar,"aria-expanded":"false",role:"button",tabindex:"0",onClick:r[0]||(r[0]=o=>n.$emit("toggle"))},Gp,8,Kp))}}),Jp=Ae(Yp,[["__file","ToggleSidebarButton.vue"]]),Qp=ce({__name:"Navbar",emits:["toggle-sidebar"],setup(e){const t=Ge(),n=_e(null),r=_e(null),o=_e(0),s=V(()=>o.value?{maxWidth:o.value+"px"}:{});ma(Gn.MOBILE,l=>{var c;const a=i(n.value,"paddingLeft")+i(n.value,"paddingRight");window.innerWidth{const c=yt("NavbarSearch");return W(),ee("header",{ref_key:"navbar",ref:n,class:"navbar"},[se(Jp,{onToggle:a[0]||(a[0]=u=>l.$emit("toggle-sidebar"))}),pe("span",{ref_key:"navbarBrand",ref:r},[se(_p)],512),pe("div",{class:"navbar-items-wrapper",style:Jn(s.value)},[we(l.$slots,"before"),se(ba,{class:"can-hide"}),we(l.$slots,"after"),ne(t).colorModeSwitch?(W(),Re(Wp,{key:0})):Pe("v-if",!0),se(c)],4)],512)}}}),Zp=Ae(Qp,[["__file","Navbar.vue"]]),Xp={class:"page-meta"},em={key:0,class:"meta-item edit-link"},tm={key:1,class:"meta-item last-updated"},nm={class:"meta-item-label"},rm={class:"meta-item-info"},om={key:2,class:"meta-item contributors"},sm={class:"meta-item-label"},im={class:"meta-item-info"},lm=["title"],am=ce({__name:"PageMeta",setup(e){const t=()=>{const a=Ge(),c=Ft(),u=_t();return V(()=>{if(!(u.value.editLink??a.value.editLink??!0))return null;const{repo:d,docsRepo:m=d,docsBranch:b="main",docsDir:w="",editLinkText:L}=a.value;if(!m)return null;const A=Dp({docsRepo:m,docsBranch:b,docsDir:w,filePathRelative:c.value.filePathRelative,editLinkPattern:u.value.editLinkPattern??a.value.editLinkPattern});return A?{text:L??"Edit this page",link:A}:null})},n=()=>{const a=Ge(),c=Ft(),u=_t();return V(()=>{var m,b;return!(u.value.lastUpdated??a.value.lastUpdated??!0)||!((m=c.value.git)!=null&&m.updatedTime)?null:new Date((b=c.value.git)==null?void 0:b.updatedTime).toLocaleString()})},r=()=>{const a=Ge(),c=Ft(),u=_t();return V(()=>{var d;return u.value.contributors??a.value.contributors??!0?((d=c.value.git)==null?void 0:d.contributors)??null:null})},o=Ge(),s=t(),i=n(),l=r();return(a,c)=>{const u=yt("ClientOnly");return W(),ee("footer",Xp,[ne(s)?(W(),ee("div",em,[se(xt,{class:"meta-item-label",item:ne(s)},null,8,["item"])])):Pe("v-if",!0),ne(i)?(W(),ee("div",tm,[pe("span",nm,Ne(ne(o).lastUpdatedText)+": ",1),se(u,null,{default:Fe(()=>[pe("span",rm,Ne(ne(i)),1)]),_:1})])):Pe("v-if",!0),ne(l)&&ne(l).length?(W(),ee("div",om,[pe("span",sm,Ne(ne(o).contributorsText)+": ",1),pe("span",im,[(W(!0),ee(Ce,null,zt(ne(l),(f,d)=>(W(),ee(Ce,{key:d},[pe("span",{class:"contributor",title:`email: ${f.email}`},Ne(f.name),9,lm),d!==ne(l).length-1?(W(),ee(Ce,{key:0},[jt(", ")],64)):Pe("v-if",!0)],64))),128))])])):Pe("v-if",!0)])}}}),cm=Ae(am,[["__file","PageMeta.vue"]]),um={key:0,class:"page-nav"},fm={class:"inner"},dm={key:0,class:"prev"},hm={key:1,class:"next"},pm=ce({__name:"PageNav",setup(e){const t=a=>a===!1?null:ve(a)?ds(a):rs(a)?a:!1,n=(a,c,u)=>{const f=a.findIndex(d=>d.link===c);if(f!==-1){const d=a[f+u];return d!=null&&d.link?d:null}for(const d of a)if(d.children){const m=n(d.children,c,u);if(m)return m}return null},r=_t(),o=hs(),s=rn(),i=V(()=>{const a=t(r.value.prev);return a!==!1?a:n(o.value,s.path,-1)}),l=V(()=>{const a=t(r.value.next);return a!==!1?a:n(o.value,s.path,1)});return(a,c)=>i.value||l.value?(W(),ee("nav",um,[pe("p",fm,[i.value?(W(),ee("span",dm,[se(xt,{item:i.value},null,8,["item"])])):Pe("v-if",!0),l.value?(W(),ee("span",hm,[se(xt,{item:l.value},null,8,["item"])])):Pe("v-if",!0)])])):Pe("v-if",!0)}}),mm=Ae(pm,[["__file","PageNav.vue"]]),vm={class:"page"},gm={class:"theme-default-content"},_m=ce({__name:"Page",setup(e){return(t,n)=>{const r=yt("Content");return W(),ee("main",vm,[we(t.$slots,"top"),pe("div",gm,[we(t.$slots,"content-top"),se(r),we(t.$slots,"content-bottom")]),se(cm),se(mm),we(t.$slots,"bottom")])}}}),bm=Ae(_m,[["__file","Page.vue"]]),ym=["onKeydown"],Em={class:"sidebar-item-children"},wm=ce({__name:"SidebarItem",props:{item:{type:Object,required:!0},depth:{type:Number,required:!1,default:0}},setup(e){const t=e,{item:n,depth:r}=Go(t),o=rn(),s=An(),i=V(()=>ga(n.value,o)),l=V(()=>({"sidebar-item":!0,"sidebar-heading":r.value===0,active:i.value,collapsible:n.value.collapsible})),a=V(()=>n.value.collapsible?i.value:!0),[c,u]=yh(a.value),f=m=>{n.value.collapsible&&(m.preventDefault(),u())},d=s.afterEach(m=>{er(()=>{c.value=a.value})});return Kr(()=>{d()}),(m,b)=>{var L;const w=yt("SidebarItem",!0);return W(),ee("li",null,[ne(n).link?(W(),Re(xt,{key:0,class:Je(l.value),item:ne(n)},null,8,["class","item"])):(W(),ee("p",{key:1,tabindex:"0",class:Je(l.value),onClick:f,onKeydown:tf(f,["enter"])},[jt(Ne(ne(n).text)+" ",1),ne(n).collapsible?(W(),ee("span",{key:0,class:Je(["arrow",ne(c)?"down":"right"])},null,2)):Pe("v-if",!0)],42,ym)),(L=ne(n).children)!=null&&L.length?(W(),Re(va,{key:2},{default:Fe(()=>[kr(pe("ul",Em,[(W(!0),ee(Ce,null,zt(ne(n).children,A=>(W(),Re(w,{key:`${ne(r)}${A.text}${A.link}`,item:A,depth:ne(r)+1},null,8,["item","depth"]))),128))],512),[[Dr,ne(c)]])]),_:1})):Pe("v-if",!0)])}}}),Cm=Ae(wm,[["__file","SidebarItem.vue"]]),Tm={key:0,class:"sidebar-items"},Lm=ce({__name:"SidebarItems",setup(e){const t=rn(),n=hs();return De(()=>{Qe(()=>t.hash,r=>{const o=document.querySelector(".sidebar");if(!o)return;const s=document.querySelector(`.sidebar a.sidebar-item[href="${t.path}${r}"]`);if(!s)return;const{top:i,height:l}=o.getBoundingClientRect(),{top:a,height:c}=s.getBoundingClientRect();ai+l&&s.scrollIntoView(!1)})}),(r,o)=>ne(n).length?(W(),ee("ul",Tm,[(W(!0),ee(Ce,null,zt(ne(n),s=>(W(),Re(Cm,{key:`${s.text}${s.link}`,item:s},null,8,["item"]))),128))])):Pe("v-if",!0)}}),xm=Ae(Lm,[["__file","SidebarItems.vue"]]),Am={class:"sidebar"},Sm=ce({__name:"Sidebar",setup(e){return(t,n)=>(W(),ee("aside",Am,[se(ba),we(t.$slots,"top"),se(xm),we(t.$slots,"bottom")]))}}),km=Ae(Sm,[["__file","Sidebar.vue"]]),Pm=ce({__name:"Layout",setup(e){const t=Ft(),n=_t(),r=Ge(),o=V(()=>n.value.navbar!==!1&&r.value.navbar!==!1),s=hs(),i=_e(!1),l=L=>{i.value=typeof L=="boolean"?L:!i.value},a={x:0,y:0},c=L=>{a.x=L.changedTouches[0].clientX,a.y=L.changedTouches[0].clientY},u=L=>{const A=L.changedTouches[0].clientX-a.x,S=L.changedTouches[0].clientY-a.y;Math.abs(A)>Math.abs(S)&&Math.abs(A)>40&&(A>0&&a.x<=80?l(!0):l(!1))},f=V(()=>[{"no-navbar":!o.value,"no-sidebar":!s.value.length,"sidebar-open":i.value},n.value.pageClass]);let d;De(()=>{d=An().afterEach(()=>{l(!1)})}),nr(()=>{d()});const m=da(),b=m.resolve,w=m.pending;return(L,A)=>(W(),ee("div",{class:Je(["theme-container",f.value]),onTouchstart:c,onTouchend:u},[we(L.$slots,"navbar",{},()=>[o.value?(W(),Re(Zp,{key:0,onToggleSidebar:l},{before:Fe(()=>[we(L.$slots,"navbar-before")]),after:Fe(()=>[we(L.$slots,"navbar-after")]),_:3})):Pe("v-if",!0)]),pe("div",{class:"sidebar-mask",onClick:A[0]||(A[0]=S=>l(!1))}),we(L.$slots,"sidebar",{},()=>[se(km,null,{top:Fe(()=>[we(L.$slots,"sidebar-top")]),bottom:Fe(()=>[we(L.$slots,"sidebar-bottom")]),_:3})]),we(L.$slots,"page",{},()=>[ne(n).home?(W(),Re(vp,{key:0})):(W(),Re(xn,{key:1,name:"fade-slide-y",mode:"out-in",onBeforeEnter:ne(b),onBeforeLeave:ne(w)},{default:Fe(()=>[(W(),Re(bm,{key:ne(t).path},{top:Fe(()=>[we(L.$slots,"page-top")]),"content-top":Fe(()=>[we(L.$slots,"page-content-top")]),"content-bottom":Fe(()=>[we(L.$slots,"page-content-bottom")]),bottom:Fe(()=>[we(L.$slots,"page-bottom")]),_:3}))]),_:3},8,["onBeforeEnter","onBeforeLeave"]))])],34))}}),ya=Ae(Pm,[["__file","Layout.vue"]]),Rm={class:"theme-container"},Om={class:"page"},Im={class:"theme-default-content"},Dm=pe("h1",null,"404",-1),Mm=ce({__name:"NotFound",setup(e){const t=or(),n=Ge(),r=n.value.notFound??["Not Found"],o=()=>r[Math.floor(Math.random()*r.length)],s=n.value.home??t.value,i=n.value.backToHome??"Back to home";return(l,a)=>{const c=yt("RouterLink");return W(),ee("div",Rm,[pe("main",Om,[pe("div",Im,[Dm,pe("blockquote",null,Ne(o()),1),se(c,{to:ne(s)},{default:Fe(()=>[jt(Ne(ne(i)),1)]),_:1},8,["to"])])])])}}}),$m=Ae(Mm,[["__file","NotFound.vue"]]),Nm=it({enhance({app:e,router:t}){e.component("Badge",ch),e.component("CodeGroup",Rh),e.component("CodeGroupItem",Mh),e.component("AutoLinkExternalIcon",()=>{const r=e.component("ExternalLinkIcon");return r?te(r):null}),e.component("NavbarSearch",()=>{const r=e.component("Docsearch")||e.component("SearchBox");return r?te(r):null});const n=t.options.scrollBehavior;t.options.scrollBehavior=async(...r)=>(await da().wait(),n(...r))},setup(){Nh(),Bh()},layouts:{Layout:ya,NotFound:$m}});var Hm=it({enhance({app:e}){const t=oe(()=>I(()=>import("./SearchBox-cTU2Stp4.js"),__vite__mapDeps([])));e.component("SearchBox",t)}});const Fm={},br=us("VUEPRESS_CODE_TAB_STORE",{});var Bm=ce({name:"CodeTabs",props:{active:{type:Number,default:0},data:{type:Array,required:!0},id:{type:String,required:!0},tabId:{type:String,default:""}},slots:Object,setup(e,{slots:t}){const n=_e(e.active),r=Ln([]),o=()=>{e.tabId&&(br.value[e.tabId]=e.data[n.value].id)},s=(c=n.value)=>{n.value=c{n.value=c>0?c-1:r.value.length-1,r.value[n.value].focus()},l=(c,u)=>{c.key===" "||c.key==="Enter"?(c.preventDefault(),n.value=u):c.key==="ArrowRight"?(c.preventDefault(),s()):c.key==="ArrowLeft"&&(c.preventDefault(),i()),e.tabId&&(br.value[e.tabId]=e.data[n.value].id)},a=()=>{if(e.tabId){const c=e.data.findIndex(({id:u})=>br.value[e.tabId]===u);if(c!==-1)return c}return e.active};return De(()=>{n.value=a(),Qe(()=>br.value[e.tabId],(c,u)=>{if(e.tabId&&c!==u){const f=e.data.findIndex(({id:d})=>d===c);f!==-1&&(n.value=f)}})}),()=>e.data.length?te("div",{class:"vp-code-tabs"},[te("div",{class:"vp-code-tabs-nav",role:"tablist"},e.data.map(({id:c},u)=>{const f=u===n.value;return te("button",{type:"button",ref:d=>{d&&(r.value[u]=d)},class:["vp-code-tab-nav",{active:f}],role:"tab","aria-controls":`codetab-${e.id}-${u}`,"aria-selected":f,onClick:()=>{n.value=u,o()},onKeydown:d=>l(d,u)},t[`title${u}`]({value:c,isActive:f}))})),e.data.map(({id:c},u)=>{const f=u===n.value;return te("div",{class:["vp-code-tab",{active:f}],id:`codetab-${e.id}-${u}`,role:"tabpanel","aria-expanded":f},[te("div",{class:"vp-code-tab-title"},t[`title${u}`]({value:c,isActive:f})),t[`tab${u}`]({value:c,isActive:f})])})]):null}});const zm=()=>{Nr("beforeprint",()=>{document.querySelectorAll("details").forEach(e=>{e.open=!0})})};var qe=Uint8Array,fn=Uint16Array,Vm=Int32Array,Ea=new qe([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),wa=new qe([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),jm=new qe([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ca=function(e,t){for(var n=new fn(31),r=0;r<31;++r)n[r]=t+=1<>1|(Le&21845)<<1;Ot=(Ot&52428)>>2|(Ot&13107)<<2,Ot=(Ot&61680)>>4|(Ot&3855)<<4,Do[Le]=((Ot&65280)>>8|(Ot&255)<<8)>>1}var zn=function(e,t,n){for(var r=e.length,o=0,s=new fn(t);o>a]=c}else for(l=new fn(r),o=0;o>15-e[o]);return l},sr=new qe(288);for(var Le=0;Le<144;++Le)sr[Le]=8;for(var Le=144;Le<256;++Le)sr[Le]=9;for(var Le=256;Le<280;++Le)sr[Le]=7;for(var Le=280;Le<288;++Le)sr[Le]=8;var xa=new qe(32);for(var Le=0;Le<32;++Le)xa[Le]=5;var qm=zn(sr,9,1),Gm=zn(xa,5,1),po=function(e){for(var t=e[0],n=1;nt&&(t=e[n]);return t},ct=function(e,t,n){var r=t/8|0;return(e[r]|e[r+1]<<8)>>(t&7)&n},mo=function(e,t){var n=t/8|0;return(e[n]|e[n+1]<<8|e[n+2]<<16)>>(t&7)},Ym=function(e){return(e+7)/8|0},ms=function(e,t,n){return(t==null||t<0)&&(t=0),(n==null||n>e.length)&&(n=e.length),new qe(e.subarray(t,n))},Jm=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],ot=function(e,t,n){var r=new Error(t||Jm[e]);if(r.code=e,Error.captureStackTrace&&Error.captureStackTrace(r,ot),!n)throw r;return r},Qm=function(e,t,n,r){var o=e.length,s=r?r.length:0;if(!o||t.f&&!t.l)return n||new qe(0);var i=!n,l=i||t.i!=2,a=t.i;i&&(n=new qe(o*3));var c=function(ue){var h=n.length;if(ue>h){var p=new qe(Math.max(h*2,ue));p.set(n),n=p}},u=t.f||0,f=t.p||0,d=t.b||0,m=t.l,b=t.d,w=t.m,L=t.n,A=o*8;do{if(!m){u=ct(e,f,1);var S=ct(e,f+1,3);if(f+=3,S)if(S==1)m=qm,b=Gm,w=9,L=5;else if(S==2){var G=ct(e,f,31)+257,H=ct(e,f+10,15)+4,_=G+ct(e,f+5,31)+1;f+=14;for(var O=new qe(_),k=new qe(19),z=0;z>4;if(g<16)O[z++]=g;else{var R=0,Y=0;for(g==16?(Y=3+ct(e,f,3),f+=2,R=O[z-1]):g==17?(Y=3+ct(e,f,7),f+=3):g==18&&(Y=11+ct(e,f,127),f+=7);Y--;)O[z++]=R}}var K=O.subarray(0,G),ye=O.subarray(G);w=po(K),L=po(ye),m=zn(K,w,1),b=zn(ye,L,1)}else ot(1);else{var g=Ym(f)+4,y=e[g-4]|e[g-3]<<8,B=g+y;if(B>o){a&&ot(0);break}l&&c(d+y),n.set(e.subarray(g,B),d),t.b=d+=y,t.p=f=B*8,t.f=u;continue}if(f>A){a&&ot(0);break}}l&&c(d+131072);for(var Me=(1<>4;if(f+=R&15,f>A){a&&ot(0);break}if(R||ot(2),We<256)n[d++]=We;else if(We==256){Oe=f,m=null;break}else{var lt=We-254;if(We>264){var z=We-257,je=Ea[z];lt=ct(e,f,(1<>4;ke||ot(3),f+=ke&15;var ye=Km[T];if(T>3){var je=wa[T];ye+=mo(e,f)&(1<A){a&&ot(0);break}l&&c(d+131072);var j=d+lt;if(d>4>7||(e[0]<<8|e[1])%31)&&ot(6,"invalid zlib data"),(e[1]>>5&1)==+!t&&ot(6,"invalid zlib data: "+(e[1]&32?"need":"unexpected")+" dictionary"),(e[1]>>3&4)+2};function ev(e,t){return Qm(e.subarray(Xm(e,t&&t.dictionary),-4),{i:2},t&&t.out,t&&t.dictionary)}var Ii=typeof TextEncoder<"u"&&new TextEncoder,Mo=typeof TextDecoder<"u"&&new TextDecoder,tv=0;try{Mo.decode(Zm,{stream:!0}),tv=1}catch{}var nv=function(e){for(var t="",n=0;;){var r=e[n++],o=(r>127)+(r>223)+(r>239);if(n+o>e.length)return{s:t,r:ms(e,n-1)};o?o==3?(r=((r&15)<<18|(e[n++]&63)<<12|(e[n++]&63)<<6|e[n++]&63)-65536,t+=String.fromCharCode(55296|r>>10,56320|r&1023)):o&1?t+=String.fromCharCode((r&31)<<6|e[n++]&63):t+=String.fromCharCode((r&15)<<12|(e[n++]&63)<<6|e[n++]&63):t+=String.fromCharCode(r)}};function rv(e,t){if(t){for(var n=new qe(e.length),r=0;r>1)),i=0,l=function(u){s[i++]=u},r=0;rs.length){var a=new qe(i+8+(o-r<<1));a.set(s),s=a}var c=e.charCodeAt(r);c<128||t?l(c):c<2048?(l(192|c>>6),l(128|c&63)):c>55295&&c<57344?(c=65536+(c&1047552)|e.charCodeAt(++r)&1023,l(240|c>>18),l(128|c>>12&63),l(128|c>>6&63),l(128|c&63)):(l(224|c>>12),l(128|c>>6&63),l(128|c&63))}return ms(s,0,i)}function ov(e,t){if(t){for(var n="",r=0;r{var r;return te("svg",{xmlns:"http://www.w3.org/2000/svg",class:["icon",`${e}-icon`],viewBox:"0 0 1024 1024",fill:t,"aria-label":`${e} icon`},(r=n.default)==null?void 0:r.call(n))};Aa.displayName="IconBase";const vs=({size:e=48,stroke:t=4,wrapper:n=!0,height:r=2*e})=>{const o=te("svg",{xmlns:"http://www.w3.org/2000/svg",width:e,height:e,preserveAspectRatio:"xMidYMid",viewBox:"25 25 50 50"},[te("animateTransform",{attributeName:"transform",type:"rotate",dur:"2s",keyTimes:"0;1",repeatCount:"indefinite",values:"0;360"}),te("circle",{cx:"50",cy:"50",r:"20",fill:"none",stroke:"currentColor","stroke-width":t,"stroke-linecap":"round"},[te("animate",{attributeName:"stroke-dasharray",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"1,200;90,200;1,200"}),te("animate",{attributeName:"stroke-dashoffset",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"0;-35px;-125px"})])]);return n?te("div",{class:"loading-icon-wrapper",style:`display:flex;align-items:center;justify-content:center;height:${r}px`},o):o};vs.displayName="LoadingIcon";const sv=e=>{const t=atob(e);return ov(ev(rv(t,!0)))},iv=e=>{const t=or();return V(()=>e[t.value])};var gs={x:0,y:0,"line-width":2,"line-length":40,"text-margin":8,"font-size":14,"font-color":"#8DA1AC","line-color":"#8DA1AC","element-color":"black",fill:"white","yes-text":"Yes","no-text":"No","arrow-end":"block",scale:1},lv={...gs,symbols:{start:{class:"start-element","font-color":"#fff",fill:"#595959","line-width":"0px"},end:{class:"end-element","font-color":"#fff",fill:"#595959","line-width":"0px"},operation:{class:"operation-element","font-color":"#fff",fill:"#1890ff","line-width":"0px"},inputoutput:{class:"inputoutput-element","font-color":"#fff",fill:"#1890ff","line-width":"0px"},subroutine:{class:"subroutine-element","font-color":"#fff",fill:"#FF485E","element-color":"#fff","line-color":"red"},condition:{class:"condition-element","font-color":"#fff",fill:"#FF485E","line-width":"0px"},parallel:{class:"parallel-element","font-color":"#fff",fill:"#1890ff","line-width":"0px"}}},av={...gs,"line-width":1,symbols:{start:{class:"start-element",fill:"#ccc","line-color":"#5c6ac4","font-color":"#000"},end:{class:"end-element",fill:"#ccc","line-color":"#5c6ac4","font-color":"#000"},operation:{class:"operation-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},inputoutput:{class:"inputoutput-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},subroutine:{class:"subroutine-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},condition:{class:"condition-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},parallel:{class:"parallel-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"}}},cv={...gs,symbols:{start:{class:"start-element","font-color":"#fff",fill:"#2F495F","line-width":"0px"},end:{class:"end-element","font-color":"#fff",fill:"#2F495F","line-width":"0px"},operation:{class:"operation-element","font-color":"#fff",fill:"#00BC7D","line-width":"0px"},inputoutput:{class:"inputoutput-element","font-color":"#fff",fill:"#EB4D5D","line-width":"0px"},subroutine:{class:"subroutine-element","font-color":"#fff",fill:"#937AC4","element-color":"#fff","line-color":"red"},condition:{class:"condition-element","font-color":"#fff",fill:"#FFB500","line-width":"0px"},parallel:{class:"parallel-element","font-color":"#fff",fill:"#2F495F","line-width":"0px"}}};const Di={ant:lv,vue:cv,pie:av};var uv=ce({name:"FlowChart",props:{code:{type:String,required:!0},id:{type:String,required:!0},preset:{type:String,default:"vue"}},setup(e){let t=null;const n=Ln(),r=_e(!0),o=_e(1),s=V(()=>Di[e.preset]||(console.warn(`[md-enhance:flowchart] Unknown preset: ${e.preset}`),Di.vue)),i=l=>l<419?.8:l>1280?1:.9;return De(()=>{Promise.all([I(()=>import("./flowchart-loQwkp6e.js"),__vite__mapDeps([])),new Promise(l=>setTimeout(l,800))]).then(([{parse:l}])=>{t=l(sv(e.code)),o.value=i(window.innerWidth),r.value=!1,t.draw(e.id,{...s.value,scale:o.value})}),Nr("resize",vh(()=>{if(t){const l=i(window.innerWidth);o.value!==l&&(o.value=l,t.draw(e.id,{...s.value,scale:l}))}},100))}),()=>[r.value?te(vs,{class:"flowchart-loading",height:192}):null,te("div",{ref:n,class:["flowchart-wrapper",e.preset],id:e.id,style:{display:r.value?"none":"block"}})]}});const fv=it({enhance:({app:e})=>{e.component("CodeTabs",Bm),e.component("FlowChart",uv)},setup:()=>{zm()}});function dv(e){return{all:e=e||new Map,on:function(t,n){var r=e.get(t);r?r.push(n):e.set(t,[n])},off:function(t,n){var r=e.get(t);r&&(n?r.splice(r.indexOf(n)>>>0,1):e.set(t,[]))},emit:function(t,n){var r=e.get(t);r&&r.slice().map(function(o){o(n)}),(r=e.get("*"))&&r.slice().map(function(o){o(t,n)})}}}const Sa=Symbol(""),hv=()=>{const e=Se(Sa);if(!e)throw new Error("usePWAEvent() is called without provider.");return e},pv=async(e,t={},n=!0)=>{const{register:r}=await I(()=>import("./index-7SG8bi1h.js"),__vite__mapDeps([]));r(e,{ready(o){var s;n&&console.info("[Service Worker]: active"),(s=t.ready)==null||s.call(t,o)},registered(o){var s;n&&console.log("[Service Worker]: registered"),(s=t.registered)==null||s.call(t,o)},cached(o){var s;n&&console.log("[Service Worker]: cached"),(s=t.cached)==null||s.call(t,o)},async updatefound(o){var s;await navigator.serviceWorker.getRegistration()&&(n&&console.log("[Service Worker]: update found"),(s=t.updatefound)==null||s.call(t,o))},updated(o){var s;n&&console.log("[Service Worker]: updated"),(s=t.updated)==null||s.call(t,o)},offline(){var o;n&&console.log("[Service Worker]: offline"),(o=t.offline)==null||o.call(t)},error(o){var s;n&&console.error("[Service Worker]: ",o),(s=t.error)==null||s.call(t,o)}})},mv=async e=>pv(Yr("service-worker.js"),{ready(t){e.emit("ready",t)},registered(t){e.emit("registered",t)},cached(t){e.emit("cached",t)},updatefound(t){e.emit("updatefound",t)},updated(t){const n="service-worker-version",r=Number(localStorage.getItem(n)||0);localStorage.setItem(n,(r+1).toString()),localStorage.removeItem("manifest"),e.emit("updated",t)},offline(){e.emit("offline")},error(t){e.emit("error",t)}}),vv=()=>{const e=dv();Ht(Sa,e),De(async()=>{var n;let t=!1;(n=navigator.serviceWorker)!=null&&n.controller&&navigator.serviceWorker.addEventListener("controllerchange",()=>{t||(t=!0,window.location.reload())}),await mv(e)})};var gv={"/":{install:"安装",iOSInstall:"点击分享按钮然后点击“添加到主屏幕”",cancel:"取消",close:"关闭",prevImage:"上一张图片",nextImage:"下一张图片",desc:"详情",feature:"主要特色",explain:"该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。",hint:"发现新内容可用",update:"新内容已就绪"}};const ka=()=>te(Aa,{name:"update"},()=>te("path",{d:"M949.949 146.25v255.826c0 21.981-13.989 35.97-35.97 35.97H658.154c-13.988 0-25.983-7.992-33.973-21.981-5.997-13.989-4-27.977 7.991-39.97l79.942-77.946c-55.954-51.973-121.918-77.955-199.863-77.955-37.975 0-75.95 8.002-113.924 21.99-37.975 15.985-67.948 37.976-91.934 63.957-25.982 23.987-47.973 53.96-63.957 91.934-29.983 73.955-29.983 153.895 0 227.85 15.984 37.976 37.975 67.947 63.957 91.934 23.986 25.982 53.959 47.973 91.934 63.956 37.974 13.989 75.95 21.991 113.924 21.991 45.967 0 87.942-9.998 127.913-29.982 41.976-17.99 75.951-45.967 101.931-83.943 7.993-4 11.994-5.995 13.989-5.995 5.997 0 9.998 1.994 13.988 5.995l77.958 77.946c3.989 4 5.986 7.993 5.986 11.994 0 1.994-1.996 5.995-3.99 11.994-43.973 51.962-93.941 91.934-151.9 117.914-53.958 25.983-115.92 39.972-185.874 39.972-61.961 0-119.921-11.984-169.89-33.973-57.96-25.985-105.923-57.963-139.896-93.943-35.98-33.972-67.958-81.936-93.94-139.897-45.967-101.93-45.967-237.846 0-339.777 25.982-57.96 57.96-105.923 93.94-139.896 33.973-35.98 81.936-67.958 139.896-93.94 49.968-21.99 107.928-33.974 169.89-33.974 55.963 0 109.923 9.988 161.885 29.973 53.97 21.99 101.933 51.963 139.908 89.938l73.954-73.944c9.987-9.998 23.987-13.988 39.971-8.002 13.988 8.002 21.98 19.995 21.98 33.984z"}));ka.displayName="UpdateIcon";const _v=gv,bv=e=>{const t=e.waiting;if(!t)return;const n=new MessageChannel;t.postMessage({type:"SKIP_WAITING"},[n.port2])};var yv=ce({name:"SWUpdatePopup",slots:Object,setup(e,{slots:t}){const n=iv(_v),r=Ln(),o=V(()=>!!r.value),s=()=>{r.value&&(bv(r.value),r.value=void 0)};return De(()=>{hv().on("updated",i=>{i&&(r.value=i)})}),()=>te(xn,{name:"popup"},()=>{var i;return((i=t.default)==null?void 0:i.call(t,{enabled:o.value,reload:s}))||(o.value?te("button",{type:"button",class:"sw-update-popup",tabindex:0,onClick:()=>s()},[n.value.update,te("span",{class:"icon-wrapper"},te(ka))]):null)})}});const Ev=it({setup:()=>{vv()},rootComponents:[yv]}),wv={enhance:({app:e})=>{e.component("A2hs",oe(()=>I(()=>import("./A2hs-xakqhU9I.js"),__vite__mapDeps([]))))}};var Cv={provider:"Giscus",comment:!0,repo:"huuhghhgyg/MicroCityNotes",repoId:"R_kgDOIf-Z0Q",category:"讨论",categoryId:"DIC_kwDOIf-Z0c4CTl1f"};const Tv=Cv;let Lv=Tv;const Pa=Symbol(""),Ra=()=>Se(Pa),xv=Ra,Av=e=>{e.provide(Pa,Lv)},Mi=["ar","ca","de","en","eo","es","fa","fr","he","id","it","ja","ko","nl","pl","pt","ro","ru","th","tr","uk","vi","zh-CN","zh-TW"];var Sv=ce({name:"GiscusComment",props:{identifier:{type:String,required:!0},darkmode:Boolean},setup(e){const t=xv(),n=!!(t.repo&&t.repoId&&t.category&&t.categoryId),{repo:r,repoId:o,category:s,categoryId:i}=t,l=_e(!1),a=V(()=>{const u=Vl().value;if(Mi.includes(u))return u;const f=u.split("-")[0];return Mi.includes(f)?f:"en"}),c=V(()=>({repo:r,repoId:o,category:s,categoryId:i,lang:a.value,theme:e.darkmode?t.darkTheme||"dark":t.lightTheme||"light",mapping:t.mapping||"pathname",term:e.identifier,inputPosition:t.inputPosition||"top",reactionsEnabled:t.reactionsEnabled===!1?"0":"1",strict:t.strict===!1?"0":"1",loading:t.lazyLoading===!1?"eager":"lazy",emitMetadata:"0"}));return De(async()=>{await I(()=>import("./giscus-unEZQsJ0.js"),__vite__mapDeps([])),l.value=!0}),()=>n?te("div",{id:"comment",class:["giscus-wrapper",{"input-top":t.inputPosition!=="bottom"}]},l.value?te("giscus-widget",c.value):te(vs)):null}}),kv=ce({name:"CommentService",props:{darkmode:Boolean},setup(e){const t=Ra(),n=Ft(),r=_t(),o=t.comment!==!1,s=V(()=>r.value.comment||o&&r.value.comment!==!1);return()=>te(Sv,{identifier:r.value.commentID||n.value.path,darkmode:e.darkmode,style:{display:s.value?"block":"none"}})}}),Pv=it({enhance:({app:e})=>{Av(e),e.component("CommentService",kv)}});const Rv=ce({__name:"Layout",setup(e){const t=_e(!1);return De(()=>{const n=document.querySelector("html");t.value=n.classList.contains("dark");const r=new MutationObserver(()=>{t.value=n.classList.contains("dark")});r.observe(n,{attributeFilter:["class"],attributes:!0}),nr(()=>{r.disconnect()})}),(n,r)=>{const o=yt("CommentService");return W(),Re(ya,null,{"page-bottom":Fe(()=>[Pe(" 评论 "),se(o,{darkmode:t.value},null,8,["darkmode"])]),_:1})}}}),Ov=Ae(Rv,[["__file","Layout.vue"]]),Iv=it({layouts:{Layout:Ov}}),yr=[Rd,Dd,Fd,Zd,nh,lh,Nm,Hm,Fm,fv,Ev,wv,Pv,Iv],Dv=[["v-8daa1a0e","/",{title:"首页"},["/README.md"]],["v-4ee3d2cc","/docs/1.1_what_microcity_can_do.html",{title:"1.1 MicroCity能做什么"},[":md"]],["v-498b1a32","/docs/2.1_showing_a_world_map.html",{title:"2.1 展示世界地图"},[":md"]],["v-0f6857b8","/docs/2.2_searching_for_countries.html",{title:"2.2 寻找国家"},[":md"]],["v-27daeef9","/docs/3.1_ui_overview.html",{title:"3.1 用户界面概览"},[":md"]],["v-3c8d6dee","/docs/3.2_vector_shapes.html",{title:"3.2 矢量图"},[":md"]],["v-6a2d64ac","/docs/3.3_raster_grids.html",{title:"3.3 栅格图"},[":md"]],["v-26445025","/docs/3.4_3d_scenes.html",{title:"3.4 3D场景"},[":md"]],["v-b2a5ca98","/docs/3.5_tables.html",{title:"3.5 表格"},[":md"]],["v-8532c374","/docs/3.6_maps_and_layers.html",{title:"3.6 地图和图层"},[":md"]],["v-656b8bd0","/docs/3.7_modules.html",{title:"3.7 拓展模块"},[":md"]],["v-4c59099a","/docs/4.1_si_overview.html",{title:"4.1 脚本概览"},[":md"]],["v-68871b76","/docs/4.2_ui_control.html",{title:"4.2 控制用户界面"},[":md"]],["v-3c0f83c0","/docs/4.3_shapes_and_tables.html",{title:"4.3 矢量图形和表格"},[":md"]],["v-c670a3a8","/docs/4.4_grids.html",{title:"4.4 栅格图形"},[":md"]],["v-672fdfba","/docs/4.5_3d_scenes.html",{title:"4.5 3D场景"},[":md"]],["v-34511d54","/docs/4.6_networks.html",{title:"4.6 网络"},[":md"]],["v-6802fed2","/docs/4.7_des_simulations.html",{title:"4.7 离散事件模拟"},[":md"]],["v-64fe0a3e","/docs/4.8_mixed_integer_programming.html",{title:"4.8 混合整数线性规划"},[":md"]],["v-147825fb","/docs/",{title:"MicroCity文档"},["/docs/readme.md"]],["v-12c828e2","/notes/3d-objects-en.html",{title:"3D Objects"},[":md"]],["v-0be8554c","/notes/3d-objects.html",{title:"3D 对象"},[":md"]],["v-d47089cc","/notes/3d-scene-en.html",{title:"3D Scene"},[":md"]],["v-41e82e22","/notes/3d-scene.html",{title:"3D 场景"},[":md"]],["v-e8b6c472","/notes/",{title:"笔记"},["/notes/README.md"]],["v-7fd381e2","/notes/cy-simulation.html",{title:"港口AGV服务流程三维仿真思路"},[":md"]],["v-44b81126","/notes/debug.html",{title:"调试相关"},[":md"]],["v-1ae81571","/notes/event-scheduling-en.html",{title:"Discrete Event Simulation and Program Control"},[":md"]],["v-0ceacb2b","/notes/event-scheduling.html",{title:"离散事件模拟和程序控制"},[":md"]],["v-8138aba4","/notes/lp.html",{title:"模型求解"},[":md"]],["v-ed3d82b0","/notes/lua.html",{title:"Lua语言快速上手"},[":md"]],["v-6eb109a0","/notes/mip-en.html",{title:"Mixed integer programming"},[":md"]],["v-dfdf5468","/notes/mip.html",{title:"混合整数规划"},[":md"]],["v-16cb829c","/notes/network.html",{title:"操作网络"},[":md"]],["v-c58fd9e0","/notes/oop.html",{title:"面向对象编程"},[":md"]],["v-f610fd24","/notes/plots.html",{title:"通用绘图代码"},[":md"]],["v-19652be0","/notes/timelapse.html",{title:"时间推进法"},[":md"]],["v-6bb8b8e5","/notes/tools.html",{title:"有关工具"},[":md"]],["v-77d2e8b7","/notes/versions.html",{title:"MicroCity的版本"},[":md"]],["v-385f9c3c","/notes/visualization.html",{title:"结果可视化"},[":md"]],["v-187abc41","/notes/warehouse-simulation.html",{title:"自动化仓库仿真思路"},[":md"]],["v-51d74d37","/notes/web-ui-en.html",{title:"Introduction to the User Interface"},[":md"]],["v-1ae3cdb6","/notes/web-ui.html",{title:"用户界面简介"},[":md"]],["v-67bbbff8","/docs/imgs/",{title:""},["/docs/imgs/readme.md"]],["v-3706649a","/404.html",{title:""},[]]];var $i=ce({name:"Vuepress",setup(){const e=_f();return()=>te(e.value)}}),Mv=()=>Dv.reduce((e,[t,n,r,o])=>(e.push({name:t,path:n,component:$i,meta:r},{path:n.endsWith("/")?n+"index.html":n.substring(0,n.length-5),redirect:n},...o.map(s=>({path:s===":md"?n.substring(0,n.length-5)+".md":s,redirect:n}))),e),[{name:"404",path:"/:catchAll(.*)",component:$i}]),$v=zf,Nv=()=>{const e=Td({history:$v(Dl("/MicroCityNotes/")),routes:Mv(),scrollBehavior:(t,n,r)=>r||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,n)=>{var r;(t.path!==n.path||n===Ct)&&([t.meta._data]=await Promise.all([wt.resolvePageData(t.name),(r=Nl[t.name])==null?void 0:r.__asyncLoader()]))}),e},Hv=e=>{e.component("ClientOnly",is),e.component("Content",Cf)},Fv=(e,t,n)=>{const r=Pi(()=>t.currentRoute.value.path),o=Pi(()=>wt.resolveRouteLocale(un.value.locales,r.value)),s=uh(r,()=>t.currentRoute.value.meta._data),i=V(()=>wt.resolveLayouts(n)),l=V(()=>wt.resolveSiteLocaleData(un.value,o.value)),a=V(()=>wt.resolvePageFrontmatter(s.value)),c=V(()=>wt.resolvePageHeadTitle(s.value,l.value)),u=V(()=>wt.resolvePageHead(c.value,a.value,l.value)),f=V(()=>wt.resolvePageLang(s.value,l.value)),d=V(()=>wt.resolvePageLayout(s.value,i.value));return e.provide(pf,i),e.provide(Hl,s),e.provide(Fl,a),e.provide(gf,c),e.provide(Bl,u),e.provide(zl,f),e.provide(jl,d),e.provide(os,o),e.provide(Wl,l),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>a.value},$head:{get:()=>u.value},$headTitle:{get:()=>c.value},$lang:{get:()=>f.value},$page:{get:()=>s.value},$routeLocale:{get:()=>o.value},$site:{get:()=>un.value},$siteLocale:{get:()=>l.value},$withBase:{get:()=>Yr}}),{layouts:i,pageData:s,pageFrontmatter:a,pageHead:u,pageHeadTitle:c,pageLang:f,pageLayout:d,routeLocale:o,siteData:un,siteLocaleData:l}},Bv=()=>{const e=vf(),t=Vl(),n=_e([]),r=()=>{e.value.forEach(s=>{const i=zv(s);i&&n.value.push(i)})},o=()=>{document.documentElement.lang=t.value,n.value.forEach(s=>{s.parentNode===document.head&&document.head.removeChild(s)}),n.value.splice(0,n.value.length),e.value.forEach(s=>{const i=Vv(s);i!==null&&(document.head.appendChild(i),n.value.push(i))})};Ht(yf,o),De(()=>{r(),o(),Qe(()=>e.value,o)})},zv=([e,t,n=""])=>{const r=Object.entries(t).map(([l,a])=>ve(a)?`[${l}=${JSON.stringify(a)}]`:a===!0?`[${l}]`:"").join(""),o=`head > ${e}${r}`;return Array.from(document.querySelectorAll(o)).find(l=>l.innerText===n)||null},Vv=([e,t,n])=>{if(!ve(e))return null;const r=document.createElement(e);return rs(t)&&Object.entries(t).forEach(([o,s])=>{ve(s)?r.setAttribute(o,s):s===!0&&r.setAttribute(o,"")}),ve(n)&&r.appendChild(document.createTextNode(n)),r},jv=of,Uv=async()=>{var n;const e=jv({name:"VuepressApp",setup(){var r;Bv();for(const o of yr)(r=o.setup)==null||r.call(o);return()=>[te(ra),...yr.flatMap(({rootComponents:o=[]})=>o.map(s=>te(s)))]}}),t=Nv();Hv(e),Fv(e,t,yr);for(const r of yr)await((n=r.enhance)==null?void 0:n.call(r,{app:e,router:t,siteData:un}));return e.use(t),{app:e,router:t}};Uv().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{Ce as F,Ae as _,pe as a,jt as b,ee as c,Uv as createVueApp,se as d,gu as e,Pe as f,_e as g,V as h,Qe as i,ce as j,or as k,kr as l,tf as m,Je as n,W as o,zt as p,Ne as q,yt as r,Kv as s,Go as t,An as u,Wv as v,Fe as w}; -function __vite__mapDeps(indexes) { - if (!__vite__mapDeps.viteFileDeps) { - __vite__mapDeps.viteFileDeps = ["assets/index.html-lZExp6Yz.js","assets/icon_script_editor-ibm_2NsU.js","assets/icon_microcity-Je85-7MO.js","assets/icon_module-AxwvBQMt.js","assets/2.1_showing_a_world_map.html-MkZfvyzh.js","assets/button_load-GOP3K2yO.js","assets/icon_shapes_polygon-5WS2EZQN.js","assets/button_action-tmG_4IgV.js","assets/2.2_searching_for_countries.html-JlV76Wlp.js","assets/3.2_vector_shapes.html-Ifn-q5O4.js","assets/3.3_raster_grids.html-RHwKcATS.js","assets/button_3d-coWyniAs.js","assets/3.4_3d_scenes.html-f5Qwa3ic.js","assets/3.5_tables.html-p-Cvt07d.js","assets/3.6_maps_and_layers.html-0HlObXq2.js","assets/3.7_modules.html-q0PqEjdM.js","assets/4.1_si_overview.html-iNqEh7u3.js","assets/4.2_ui_control.html-PXdKdANV.js","assets/4.3_shapes_and_tables.html-kM2JYXcO.js","assets/4.4_grids.html-7i5R0Lmo.js","assets/4.5_3d_scenes.html-2AMaq24g.js","assets/4.6_networks.html-PK_mfd9Y.js","assets/4.7_des_simulations.html-8bSUiGUz.js","assets/4.8_mixed_integer_programming.html-E59_LnJJ.js","assets/3d-objects-en.html-7DC5k-lZ.js","assets/polygon_sizes-bVJYQmiT.js","assets/3d-objects.html-lKAwFYq5.js","assets/3d-scene-en.html-M1ONxEpk.js","assets/coordinate-R7ZKfirG.js","assets/3d-scene.html-A33RmZzw.js","assets/event-scheduling-en.html-gRProVKn.js","assets/CommandBar-jgj8yIQP.js","assets/event-scheduling.html-7ezvA1AX.js","assets/web-ui-en.html-9hWYZBEN.js","assets/AutoTranslate-DxMBsWAh.js","assets/web-ui.html-zrAeLt4a.js"] - } - return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) -} \ No newline at end of file diff --git a/assets/app-LOf__QKq.js b/assets/app-LOf__QKq.js new file mode 100644 index 00000000..b2b68a4e --- /dev/null +++ b/assets/app-LOf__QKq.js @@ -0,0 +1,16 @@ +function $o(e,t){const n=Object.create(null),r=e.split(",");for(let o=0;o!!n[o.toLowerCase()]:o=>!!n[o]}const Le={},dn=[],_t=()=>{},ka=()=>!1,Sa=/^on[^a-z]/,Yn=e=>Sa.test(e),No=e=>e.startsWith("onUpdate:"),Ve=Object.assign,Vo=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Da=Object.prototype.hasOwnProperty,he=(e,t)=>Da.call(e,t),Z=Array.isArray,hn=e=>Hr(e)==="[object Map]",Vi=e=>Hr(e)==="[object Set]",ae=e=>typeof e=="function",ve=e=>typeof e=="string",Vr=e=>typeof e=="symbol",Ae=e=>e!==null&&typeof e=="object",Hi=e=>(Ae(e)||ae(e))&&ae(e.then)&&ae(e.catch),Fi=Object.prototype.toString,Hr=e=>Fi.call(e),Ma=e=>Hr(e).slice(8,-1),zi=e=>Hr(e)==="[object Object]",Ho=e=>ve(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Mn=$o(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Fr=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},$a=/-(\w)/g,bt=Fr(e=>e.replace($a,(t,n)=>n?n.toUpperCase():"")),Na=/\B([A-Z])/g,nn=Fr(e=>e.replace(Na,"-$1").toLowerCase()),zr=Fr(e=>e.charAt(0).toUpperCase()+e.slice(1)),Zr=Fr(e=>e?`on${zr(e)}`:""),tn=(e,t)=>!Object.is(e,t),Er=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},vo=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Va=e=>{const t=ve(e)?Number(e):NaN;return isNaN(t)?e:t};let Es;const _o=()=>Es||(Es=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Jn(e){if(Z(e)){const t={};for(let n=0;n{if(n){const r=n.split(Fa);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Je(e){let t="";if(ve(e))t=e;else if(Z(e))for(let n=0;nve(e)?e:e==null?"":Z(e)||Ae(e)&&(e.toString===Fi||!ae(e.toString))?JSON.stringify(e,ji,2):String(e),ji=(e,t)=>t&&t.__v_isRef?ji(e,t.value):hn(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,o])=>(n[`${r} =>`]=o,n),{})}:Vi(t)?{[`Set(${t.size})`]:[...t.values()]}:Ae(t)&&!Z(t)&&!zi(t)?String(t):t;let et;class Ua{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=et,!t&&et&&(this.index=(et.scopes||(et.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=et;try{return et=this,t()}finally{et=n}}}on(){et=this}off(){et=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},Ui=e=>(e.w&Ft)>0,Ki=e=>(e.n&Ft)>0,Ga=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let r=0;r{(u==="length"||!Vr(u)&&u>=a)&&l.push(c)})}else switch(n!==void 0&&l.push(i.get(n)),t){case"add":Z(e)?Ho(n)&&l.push(i.get("length")):(l.push(i.get(Xt)),hn(e)&&l.push(i.get(bo)));break;case"delete":Z(e)||(l.push(i.get(Xt)),hn(e)&&l.push(i.get(bo)));break;case"set":hn(e)&&l.push(i.get(Xt));break}if(l.length===1)l[0]&&yo(l[0]);else{const a=[];for(const c of l)c&&a.push(...c);yo(Fo(a))}}function yo(e,t){const n=Z(e)?e:[...e];for(const r of n)r.computed&&Ts(r);for(const r of n)r.computed||Ts(r)}function Ts(e,t){(e!==ft||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}function Ja(e,t){var n;return(n=Cr.get(e))==null?void 0:n.get(t)}const Qa=$o("__proto__,__v_isRef,__isVue"),Yi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Vr)),Ls=Za();function Za(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=me(this);for(let s=0,i=this.length;s{e[t]=function(...n){Tn();const r=me(this)[t].apply(this,n);return Ln(),r}}),e}function Xa(e){const t=me(this);return Ze(t,"has",e),t.hasOwnProperty(e)}class Ji{constructor(t=!1,n=!1){this._isReadonly=t,this._shallow=n}get(t,n,r){const o=this._isReadonly,s=this._shallow;if(n==="__v_isReactive")return!o;if(n==="__v_isReadonly")return o;if(n==="__v_isShallow")return s;if(n==="__v_raw"&&r===(o?s?dc:el:s?Xi:Zi).get(t))return t;const i=Z(t);if(!o){if(i&&he(Ls,n))return Reflect.get(Ls,n,r);if(n==="hasOwnProperty")return Xa}const l=Reflect.get(t,n,r);return(Vr(n)?Yi.has(n):Qa(n))||(o||Ze(t,"get",n),s)?l:Fe(l)?i&&Ho(n)?l:l.value:Ae(l)?o?Zn(l):Qn(l):l}}class Qi extends Ji{constructor(t=!1){super(!1,t)}set(t,n,r,o){let s=t[n];if(_n(s)&&Fe(s)&&!Fe(r))return!1;if(!this._shallow&&(!Ar(r)&&!_n(r)&&(s=me(s),r=me(r)),!Z(t)&&Fe(s)&&!Fe(r)))return s.value=r,!0;const i=Z(t)&&Ho(n)?Number(n)e,Br=e=>Reflect.getPrototypeOf(e);function ir(e,t,n=!1,r=!1){e=e.__v_raw;const o=me(e),s=me(t);n||(tn(t,s)&&Ze(o,"get",t),Ze(o,"get",s));const{has:i}=Br(o),l=r?Bo:n?Uo:Bn;if(i.call(o,t))return l(e.get(t));if(i.call(o,s))return l(e.get(s));e!==o&&e.get(t)}function lr(e,t=!1){const n=this.__v_raw,r=me(n),o=me(e);return t||(tn(e,o)&&Ze(r,"has",e),Ze(r,"has",o)),e===o?n.has(e):n.has(e)||n.has(o)}function ar(e,t=!1){return e=e.__v_raw,!t&&Ze(me(e),"iterate",Xt),Reflect.get(e,"size",e)}function Cs(e){e=me(e);const t=me(this);return Br(t).has.call(t,e)||(t.add(e),Ct(t,"add",e,e)),this}function As(e,t){t=me(t);const n=me(this),{has:r,get:o}=Br(n);let s=r.call(n,e);s||(e=me(e),s=r.call(n,e));const i=o.call(n,e);return n.set(e,t),s?tn(t,i)&&Ct(n,"set",e,t):Ct(n,"add",e,t),this}function xs(e){const t=me(this),{has:n,get:r}=Br(t);let o=n.call(t,e);o||(e=me(e),o=n.call(t,e)),r&&r.call(t,e);const s=t.delete(e);return o&&Ct(t,"delete",e,void 0),s}function Ps(){const e=me(this),t=e.size!==0,n=e.clear();return t&&Ct(e,"clear",void 0,void 0),n}function cr(e,t){return function(r,o){const s=this,i=s.__v_raw,l=me(i),a=t?Bo:e?Uo:Bn;return!e&&Ze(l,"iterate",Xt),i.forEach((c,u)=>r.call(o,a(c),a(u),s))}}function ur(e,t,n){return function(...r){const o=this.__v_raw,s=me(o),i=hn(s),l=e==="entries"||e===Symbol.iterator&&i,a=e==="keys"&&i,c=o[e](...r),u=n?Bo:t?Uo:Bn;return!t&&Ze(s,"iterate",a?bo:Xt),{next(){const{value:f,done:d}=c.next();return d?{value:f,done:d}:{value:l?[u(f[0]),u(f[1])]:u(f),done:d}},[Symbol.iterator](){return this}}}}function Pt(e){return function(...t){return e==="delete"?!1:this}}function oc(){const e={get(s){return ir(this,s)},get size(){return ar(this)},has:lr,add:Cs,set:As,delete:xs,clear:Ps,forEach:cr(!1,!1)},t={get(s){return ir(this,s,!1,!0)},get size(){return ar(this)},has:lr,add:Cs,set:As,delete:xs,clear:Ps,forEach:cr(!1,!0)},n={get(s){return ir(this,s,!0)},get size(){return ar(this,!0)},has(s){return lr.call(this,s,!0)},add:Pt("add"),set:Pt("set"),delete:Pt("delete"),clear:Pt("clear"),forEach:cr(!0,!1)},r={get(s){return ir(this,s,!0,!0)},get size(){return ar(this,!0)},has(s){return lr.call(this,s,!0)},add:Pt("add"),set:Pt("set"),delete:Pt("delete"),clear:Pt("clear"),forEach:cr(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(s=>{e[s]=ur(s,!1,!1),n[s]=ur(s,!0,!1),t[s]=ur(s,!1,!0),r[s]=ur(s,!0,!0)}),[e,n,t,r]}const[sc,ic,lc,ac]=oc();function jo(e,t){const n=t?e?ac:lc:e?ic:sc;return(r,o,s)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?r:Reflect.get(he(n,o)&&o in r?n:r,o,s)}const cc={get:jo(!1,!1)},uc={get:jo(!1,!0)},fc={get:jo(!0,!1)},Zi=new WeakMap,Xi=new WeakMap,el=new WeakMap,dc=new WeakMap;function hc(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function pc(e){return e.__v_skip||!Object.isExtensible(e)?0:hc(Ma(e))}function Qn(e){return _n(e)?e:Wo(e,!1,tc,cc,Zi)}function tl(e){return Wo(e,!1,rc,uc,Xi)}function Zn(e){return Wo(e,!0,nc,fc,el)}function Wo(e,t,n,r,o){if(!Ae(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const s=o.get(e);if(s)return s;const i=pc(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return o.set(e,l),l}function pn(e){return _n(e)?pn(e.__v_raw):!!(e&&e.__v_isReactive)}function _n(e){return!!(e&&e.__v_isReadonly)}function Ar(e){return!!(e&&e.__v_isShallow)}function nl(e){return pn(e)||_n(e)}function me(e){const t=e&&e.__v_raw;return t?me(t):e}function rl(e){return Lr(e,"__v_skip",!0),e}const Bn=e=>Ae(e)?Qn(e):e,Uo=e=>Ae(e)?Zn(e):e;function Ko(e){$t&&ft&&(e=me(e),Gi(e.dep||(e.dep=Fo())))}function qo(e,t){e=me(e);const n=e.dep;n&&yo(n)}function Fe(e){return!!(e&&e.__v_isRef===!0)}function ge(e){return ol(e,!1)}function Cn(e){return ol(e,!0)}function ol(e,t){return Fe(e)?e:new mc(e,t)}class mc{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:me(t),this._value=n?t:Bn(t)}get value(){return Ko(this),this._value}set value(t){const n=this.__v_isShallow||Ar(t)||_n(t);t=n?t:me(t),tn(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Bn(t),qo(this))}}function re(e){return Fe(e)?e.value:e}const vc={get:(e,t,n)=>re(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return Fe(o)&&!Fe(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function sl(e){return pn(e)?e:new Proxy(e,vc)}class _c{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>Ko(this),()=>qo(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function gc(e){return new _c(e)}function Go(e){const t=Z(e)?new Array(e.length):{};for(const n in e)t[n]=yc(e,n);return t}class bc{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Ja(me(this._object),this._key)}}function yc(e,t,n){const r=e[t];return Fe(r)?r:new bc(e,t,n)}class Ec{constructor(t,n,r,o){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new zo(t,()=>{this._dirty||(this._dirty=!0,qo(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!o,this.__v_isReadonly=r}get value(){const t=me(this);return Ko(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function wc(e,t,n=!1){let r,o;const s=ae(e);return s?(r=e,o=_t):(r=e.get,o=e.set),new Ec(r,o,s||!o,n)}function Nt(e,t,n,r){let o;try{o=r?e(...r):e()}catch(s){Xn(s,t,n)}return o}function st(e,t,n,r){if(ae(e)){const s=Nt(e,t,n,r);return s&&Hi(s)&&s.catch(i=>{Xn(i,t,n)}),s}const o=[];for(let s=0;s>>1,o=We[r],s=Wn(o);svt&&We.splice(t,1)}function Ac(e){Z(e)?mn.push(...e):(!Lt||!Lt.includes(e,e.allowRecurse?Yt+1:Yt))&&mn.push(e),ll()}function Rs(e,t=jn?vt+1:0){for(;tWn(n)-Wn(r)),Yt=0;Yte.id==null?1/0:e.id,xc=(e,t)=>{const n=Wn(e)-Wn(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function al(e){Eo=!1,jn=!0,We.sort(xc);try{for(vt=0;vtve(m)?m.trim():m)),f&&(o=n.map(vo))}let l,a=r[l=Zr(t)]||r[l=Zr(bt(t))];!a&&s&&(a=r[l=Zr(nn(t))]),a&&st(a,e,6,o);const c=r[l+"Once"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,st(c,e,6,o)}}function cl(e,t,n=!1){const r=t.emitsCache,o=r.get(e);if(o!==void 0)return o;const s=e.emits;let i={},l=!1;if(!ae(e)){const a=c=>{const u=cl(c,t,!0);u&&(l=!0,Ve(i,u))};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!s&&!l?(Ae(e)&&r.set(e,null),null):(Z(s)?s.forEach(a=>i[a]=null):Ve(i,s),Ae(e)&&r.set(e,i),i)}function Wr(e,t){return!e||!Yn(t)?!1:(t=t.slice(2).replace(/Once$/,""),he(e,t[0].toLowerCase()+t.slice(1))||he(e,nn(t))||he(e,t))}let ze=null,ul=null;function Pr(e){const t=ze;return ze=e,ul=e&&e.type.__scopeId||null,t}function He(e,t=ze,n){if(!t||e._n)return e;const r=(...o)=>{r._d&&zs(-1);const s=Pr(t);let i;try{i=e(...o)}finally{Pr(s),r._d&&zs(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function Xr(e){const{type:t,vnode:n,proxy:r,withProxy:o,props:s,propsOptions:[i],slots:l,attrs:a,emit:c,render:u,renderCache:f,data:d,setupState:m,ctx:y,inheritAttrs:T}=e;let A,P;const R=Pr(e);try{if(n.shapeFlag&4){const E=o||r;A=ut(u.call(E,E,f,s,m,d,y)),P=a}else{const E=t;A=ut(E.length>1?E(s,{attrs:a,slots:l,emit:c}):E(s,null)),P=t.props?a:Rc(a)}}catch(E){Vn.length=0,Xn(E,e,1),A=se(tt)}let g=A;if(P&&T!==!1){const E=Object.keys(P),{shapeFlag:z}=g;E.length&&z&7&&(i&&E.some(No)&&(P=Ic(P,i)),g=Bt(g,P))}return n.dirs&&(g=Bt(g),g.dirs=g.dirs?g.dirs.concat(n.dirs):n.dirs),n.transition&&(g.transition=n.transition),A=g,Pr(R),A}const Rc=e=>{let t;for(const n in e)(n==="class"||n==="style"||Yn(n))&&((t||(t={}))[n]=e[n]);return t},Ic=(e,t)=>{const n={};for(const r in e)(!No(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function Oc(e,t,n){const{props:r,children:o,component:s}=e,{props:i,children:l,patchFlag:a}=t,c=s.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&a>=0){if(a&1024)return!0;if(a&16)return r?Is(r,i,c):!!i;if(a&8){const u=t.dynamicProps;for(let f=0;fe.__isSuspense;function dl(e,t){t&&t.pendingBranch?Z(e)?t.effects.push(...e):t.effects.push(e):Ac(e)}function hl(e,t){return Jo(e,null,t)}const fr={};function Qe(e,t,n){return Jo(e,t,n)}function Jo(e,t,{immediate:n,deep:r,flush:o,onTrack:s,onTrigger:i}=Le){var l;const a=Wi()===((l=$e)==null?void 0:l.scope)?$e:null;let c,u=!1,f=!1;if(Fe(e)?(c=()=>e.value,u=Ar(e)):pn(e)?(c=()=>e,r=!0):Z(e)?(f=!0,u=e.some(E=>pn(E)||Ar(E)),c=()=>e.map(E=>{if(Fe(E))return E.value;if(pn(E))return Zt(E);if(ae(E))return Nt(E,a,2)})):ae(e)?t?c=()=>Nt(e,a,2):c=()=>{if(!(a&&a.isUnmounted))return d&&d(),st(e,a,3,[m])}:c=_t,t&&r){const E=c;c=()=>Zt(E())}let d,m=E=>{d=R.onStop=()=>{Nt(E,a,4)}},y;if(yn)if(m=_t,t?n&&st(t,a,3,[c(),f?[]:void 0,m]):c(),o==="sync"){const E=Pu();y=E.__watcherHandles||(E.__watcherHandles=[])}else return _t;let T=f?new Array(e.length).fill(fr):fr;const A=()=>{if(R.active)if(t){const E=R.run();(r||u||(f?E.some((z,Y)=>tn(z,T[Y])):tn(E,T)))&&(d&&d(),st(t,a,3,[E,T===fr?void 0:f&&T[0]===fr?[]:T,m]),T=E)}else R.run()};A.allowRecurse=!!t;let P;o==="sync"?P=A:o==="post"?P=()=>Ye(A,a&&a.suspense):(A.pre=!0,a&&(A.id=a.uid),P=()=>jr(A));const R=new zo(c,P);t?n?A():T=R.run():o==="post"?Ye(R.run.bind(R),a&&a.suspense):R.run();const g=()=>{R.stop(),a&&a.scope&&Vo(a.scope.effects,R)};return y&&y.push(g),g}function $c(e,t,n){const r=this.proxy,o=ve(e)?e.includes(".")?pl(r,e):()=>r[e]:e.bind(r,r);let s;ae(t)?s=t:(s=t.handler,n=t);const i=$e;bn(this);const l=Jo(o,s.bind(r),n);return i?bn(i):en(),l}function pl(e,t){const n=t.split(".");return()=>{let r=e;for(let o=0;o{Zt(n,t)});else if(zi(e))for(const n in e)Zt(e[n],t);return e}function Rr(e,t){const n=ze;if(n===null)return e;const r=Gr(n)||n.proxy,o=e.dirs||(e.dirs=[]);for(let s=0;s{e.isMounted=!0}),Kr(()=>{e.isUnmounting=!0}),e}const nt=[Function,Array],ml={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:nt,onEnter:nt,onAfterEnter:nt,onEnterCancelled:nt,onBeforeLeave:nt,onLeave:nt,onAfterLeave:nt,onLeaveCancelled:nt,onBeforeAppear:nt,onAppear:nt,onAfterAppear:nt,onAppearCancelled:nt},Vc={name:"BaseTransition",props:ml,setup(e,{slots:t}){const n=es(),r=Nc();let o;return()=>{const s=t.default&&_l(t.default(),!0);if(!s||!s.length)return;let i=s[0];if(s.length>1){for(const T of s)if(T.type!==tt){i=T;break}}const l=me(e),{mode:a}=l;if(r.isLeaving)return eo(i);const c=ks(i);if(!c)return eo(i);const u=wo(c,l,r,n);To(c,u);const f=n.subTree,d=f&&ks(f);let m=!1;const{getTransitionKey:y}=c.type;if(y){const T=y();o===void 0?o=T:T!==o&&(o=T,m=!0)}if(d&&d.type!==tt&&(!Jt(c,d)||m)){const T=wo(d,l,r,n);if(To(d,T),a==="out-in")return r.isLeaving=!0,T.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&n.update()},eo(i);a==="in-out"&&c.type!==tt&&(T.delayLeave=(A,P,R)=>{const g=vl(r,d);g[String(d.key)]=d,A[St]=()=>{P(),A[St]=void 0,delete u.delayedLeave},u.delayedLeave=R})}return i}}},Hc=Vc;function vl(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function wo(e,t,n,r){const{appear:o,mode:s,persisted:i=!1,onBeforeEnter:l,onEnter:a,onAfterEnter:c,onEnterCancelled:u,onBeforeLeave:f,onLeave:d,onAfterLeave:m,onLeaveCancelled:y,onBeforeAppear:T,onAppear:A,onAfterAppear:P,onAppearCancelled:R}=t,g=String(e.key),E=vl(n,e),z=(b,S)=>{b&&st(b,r,9,S)},Y=(b,S)=>{const I=S[1];z(b,S),Z(b)?b.every(B=>B.length<=1)&&I():b.length<=1&&I()},H={mode:s,persisted:i,beforeEnter(b){let S=l;if(!n.isMounted)if(o)S=T||l;else return;b[St]&&b[St](!0);const I=E[g];I&&Jt(e,I)&&I.el[St]&&I.el[St](),z(S,[b])},enter(b){let S=a,I=c,B=u;if(!n.isMounted)if(o)S=A||a,I=P||c,B=R||u;else return;let L=!1;const M=b[dr]=oe=>{L||(L=!0,oe?z(B,[b]):z(I,[b]),H.delayedLeave&&H.delayedLeave(),b[dr]=void 0)};S?Y(S,[b,M]):M()},leave(b,S){const I=String(e.key);if(b[dr]&&b[dr](!0),n.isUnmounting)return S();z(f,[b]);let B=!1;const L=b[St]=M=>{B||(B=!0,S(),M?z(y,[b]):z(m,[b]),b[St]=void 0,E[I]===e&&delete E[I])};E[I]=e,d?Y(d,[b,L]):L()},clone(b){return wo(b,t,n,r)}};return H}function eo(e){if(tr(e))return e=Bt(e),e.children=null,e}function ks(e){return tr(e)?e.children?e.children[0]:void 0:e}function To(e,t){e.shapeFlag&6&&e.component?To(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function _l(e,t=!1,n){let r=[],o=0;for(let s=0;s1)for(let s=0;s!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function V(e){ae(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:o=200,timeout:s,suspensible:i=!0,onError:l}=e;let a=null,c,u=0;const f=()=>(u++,a=null,d()),d=()=>{let m;return a||(m=a=t().catch(y=>{if(y=y instanceof Error?y:new Error(String(y)),l)return new Promise((T,A)=>{l(y,()=>T(f()),()=>A(y),u+1)});throw y}).then(y=>m!==a&&a?a:(y&&(y.__esModule||y[Symbol.toStringTag]==="Module")&&(y=y.default),c=y,y)))};return ce({name:"AsyncComponentWrapper",__asyncLoader:d,get __asyncResolved(){return c},setup(){const m=$e;if(c)return()=>to(c,m);const y=R=>{a=null,Xn(R,m,13,!r)};if(i&&m.suspense||yn)return d().then(R=>()=>to(R,m)).catch(R=>(y(R),()=>r?se(r,{error:R}):null));const T=ge(!1),A=ge(),P=ge(!!o);return o&&setTimeout(()=>{P.value=!1},o),s!=null&&setTimeout(()=>{if(!T.value&&!A.value){const R=new Error(`Async component timed out after ${s}ms.`);y(R),A.value=R}},s),d().then(()=>{T.value=!0,m.parent&&tr(m.parent.vnode)&&jr(m.parent.update)}).catch(R=>{y(R),A.value=R}),()=>{if(T.value&&c)return to(c,m);if(A.value&&r)return se(r,{error:A.value});if(n&&!P.value)return se(n)}}})}function to(e,t){const{ref:n,props:r,children:o,ce:s}=t.vnode,i=se(e,r,o);return i.ref=n,i.ce=s,delete t.vnode.ce,i}const tr=e=>e.type.__isKeepAlive;function Fc(e,t){gl(e,"a",t)}function zc(e,t){gl(e,"da",t)}function gl(e,t,n=$e){const r=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Ur(t,r,n),n){let o=n.parent;for(;o&&o.parent;)tr(o.parent.vnode)&&Bc(r,t,n,o),o=o.parent}}function Bc(e,t,n,r){const o=Ur(t,e,r,!0);nr(()=>{Vo(r[t],o)},n)}function Ur(e,t,n=$e,r=!1){if(n){const o=n[e]||(n[e]=[]),s=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;Tn(),bn(n);const l=st(t,n,e,i);return en(),Ln(),l});return r?o.unshift(s):o.push(s),s}}const xt=e=>(t,n=$e)=>(!yn||e==="sp")&&Ur(e,(...r)=>t(...r),n),jc=xt("bm"),De=xt("m"),Wc=xt("bu"),Uc=xt("u"),Kr=xt("bum"),nr=xt("um"),Kc=xt("sp"),qc=xt("rtg"),Gc=xt("rtc");function Yc(e,t=$e){Ur("ec",e,t)}function zt(e,t,n,r){let o;const s=n&&n[r];if(Z(e)||ve(e)){o=new Array(e.length);for(let i=0,l=e.length;it(i,l,void 0,s&&s[l]));else{const i=Object.keys(e);o=new Array(i.length);for(let l=0,a=i.length;lSr(t)?!(t.type===tt||t.type===Te&&!bl(t.children)):!0)?e:null}const Lo=e=>e?Ol(e)?Gr(e)||e.proxy:Lo(e.parent):null,$n=Ve(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Lo(e.parent),$root:e=>Lo(e.root),$emit:e=>e.emit,$options:e=>Qo(e),$forceUpdate:e=>e.f||(e.f=()=>jr(e.update)),$nextTick:e=>e.n||(e.n=er.bind(e.proxy)),$watch:e=>$c.bind(e)}),no=(e,t)=>e!==Le&&!e.__isScriptSetup&&he(e,t),Jc={get({_:e},t){const{ctx:n,setupState:r,data:o,props:s,accessCache:i,type:l,appContext:a}=e;let c;if(t[0]!=="$"){const m=i[t];if(m!==void 0)switch(m){case 1:return r[t];case 2:return o[t];case 4:return n[t];case 3:return s[t]}else{if(no(r,t))return i[t]=1,r[t];if(o!==Le&&he(o,t))return i[t]=2,o[t];if((c=e.propsOptions[0])&&he(c,t))return i[t]=3,s[t];if(n!==Le&&he(n,t))return i[t]=4,n[t];Co&&(i[t]=0)}}const u=$n[t];let f,d;if(u)return t==="$attrs"&&Ze(e,"get",t),u(e);if((f=l.__cssModules)&&(f=f[t]))return f;if(n!==Le&&he(n,t))return i[t]=4,n[t];if(d=a.config.globalProperties,he(d,t))return d[t]},set({_:e},t,n){const{data:r,setupState:o,ctx:s}=e;return no(o,t)?(o[t]=n,!0):r!==Le&&he(r,t)?(r[t]=n,!0):he(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(s[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:o,propsOptions:s}},i){let l;return!!n[i]||e!==Le&&he(e,i)||no(t,i)||(l=s[0])&&he(l,i)||he(r,i)||he($n,i)||he(o.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:he(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Ss(e){return Z(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Co=!0;function Qc(e){const t=Qo(e),n=e.proxy,r=e.ctx;Co=!1,t.beforeCreate&&Ds(t.beforeCreate,e,"bc");const{data:o,computed:s,methods:i,watch:l,provide:a,inject:c,created:u,beforeMount:f,mounted:d,beforeUpdate:m,updated:y,activated:T,deactivated:A,beforeDestroy:P,beforeUnmount:R,destroyed:g,unmounted:E,render:z,renderTracked:Y,renderTriggered:H,errorCaptured:b,serverPrefetch:S,expose:I,inheritAttrs:B,components:L,directives:M,filters:oe}=t;if(c&&Zc(c,r,null),i)for(const J in i){const q=i[J];ae(q)&&(r[J]=q.bind(n))}if(o){const J=o.call(n,n);Ae(J)&&(e.data=Qn(J))}if(Co=!0,s)for(const J in s){const q=s[J],ye=ae(q)?q.bind(n,n):ae(q.get)?q.get.bind(n,n):_t,Me=!ae(q)&&ae(q.set)?q.set.bind(n):_t,Be=j({get:ye,set:Me});Object.defineProperty(r,J,{enumerable:!0,configurable:!0,get:()=>Be.value,set:ke=>Be.value=ke})}if(l)for(const J in l)yl(l[J],r,n,J);if(a){const J=ae(a)?a.call(n):a;Reflect.ownKeys(J).forEach(q=>{Vt(q,J[q])})}u&&Ds(u,e,"c");function k(J,q){Z(q)?q.forEach(ye=>J(ye.bind(n))):q&&J(q.bind(n))}if(k(jc,f),k(De,d),k(Wc,m),k(Uc,y),k(Fc,T),k(zc,A),k(Yc,b),k(Gc,Y),k(qc,H),k(Kr,R),k(nr,E),k(Kc,S),Z(I))if(I.length){const J=e.exposed||(e.exposed={});I.forEach(q=>{Object.defineProperty(J,q,{get:()=>n[q],set:ye=>n[q]=ye})})}else e.exposed||(e.exposed={});z&&e.render===_t&&(e.render=z),B!=null&&(e.inheritAttrs=B),L&&(e.components=L),M&&(e.directives=M)}function Zc(e,t,n=_t){Z(e)&&(e=Ao(e));for(const r in e){const o=e[r];let s;Ae(o)?"default"in o?s=Pe(o.from||r,o.default,!0):s=Pe(o.from||r):s=Pe(o),Fe(s)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>s.value,set:i=>s.value=i}):t[r]=s}}function Ds(e,t,n){st(Z(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function yl(e,t,n,r){const o=r.includes(".")?pl(n,r):()=>n[r];if(ve(e)){const s=t[e];ae(s)&&Qe(o,s)}else if(ae(e))Qe(o,e.bind(n));else if(Ae(e))if(Z(e))e.forEach(s=>yl(s,t,n,r));else{const s=ae(e.handler)?e.handler.bind(n):t[e.handler];ae(s)&&Qe(o,s,e)}}function Qo(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:o,optionsCache:s,config:{optionMergeStrategies:i}}=e.appContext,l=s.get(t);let a;return l?a=l:!o.length&&!n&&!r?a=t:(a={},o.length&&o.forEach(c=>Ir(a,c,i,!0)),Ir(a,t,i)),Ae(t)&&s.set(t,a),a}function Ir(e,t,n,r=!1){const{mixins:o,extends:s}=t;s&&Ir(e,s,n,!0),o&&o.forEach(i=>Ir(e,i,n,!0));for(const i in t)if(!(r&&i==="expose")){const l=Xc[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const Xc={data:Ms,props:$s,emits:$s,methods:Dn,computed:Dn,beforeCreate:Ke,created:Ke,beforeMount:Ke,mounted:Ke,beforeUpdate:Ke,updated:Ke,beforeDestroy:Ke,beforeUnmount:Ke,destroyed:Ke,unmounted:Ke,activated:Ke,deactivated:Ke,errorCaptured:Ke,serverPrefetch:Ke,components:Dn,directives:Dn,watch:tu,provide:Ms,inject:eu};function Ms(e,t){return t?e?function(){return Ve(ae(e)?e.call(this,this):e,ae(t)?t.call(this,this):t)}:t:e}function eu(e,t){return Dn(Ao(e),Ao(t))}function Ao(e){if(Z(e)){const t={};for(let n=0;n1)return n&&ae(t)?t.call(r&&r.proxy):t}}function ou(e,t,n,r=!1){const o={},s={};Lr(s,qr,1),e.propsDefaults=Object.create(null),wl(e,t,o,s);for(const i in e.propsOptions[0])i in o||(o[i]=void 0);n?e.props=r?o:tl(o):e.type.props?e.props=o:e.props=s,e.attrs=s}function su(e,t,n,r){const{props:o,attrs:s,vnode:{patchFlag:i}}=e,l=me(o),[a]=e.propsOptions;let c=!1;if((r||i>0)&&!(i&16)){if(i&8){const u=e.vnode.dynamicProps;for(let f=0;f{a=!0;const[d,m]=Tl(f,t,!0);Ve(i,d),m&&l.push(...m)};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!s&&!a)return Ae(e)&&r.set(e,dn),dn;if(Z(s))for(let u=0;u-1,m[1]=T<0||y-1||he(m,"default"))&&l.push(f)}}}const c=[i,l];return Ae(e)&&r.set(e,c),c}function Ns(e){return e[0]!=="$"}function Vs(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function Hs(e,t){return Vs(e)===Vs(t)}function Fs(e,t){return Z(t)?t.findIndex(n=>Hs(n,e)):ae(t)&&Hs(t,e)?0:-1}const Ll=e=>e[0]==="_"||e==="$stable",Zo=e=>Z(e)?e.map(ut):[ut(e)],iu=(e,t,n)=>{if(t._n)return t;const r=He((...o)=>Zo(t(...o)),n);return r._c=!1,r},Cl=(e,t,n)=>{const r=e._ctx;for(const o in e){if(Ll(o))continue;const s=e[o];if(ae(s))t[o]=iu(o,s,r);else if(s!=null){const i=Zo(s);t[o]=()=>i}}},Al=(e,t)=>{const n=Zo(t);e.slots.default=()=>n},lu=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=me(t),Lr(t,"_",n)):Cl(t,e.slots={})}else e.slots={},t&&Al(e,t);Lr(e.slots,qr,1)},au=(e,t,n)=>{const{vnode:r,slots:o}=e;let s=!0,i=Le;if(r.shapeFlag&32){const l=t._;l?n&&l===1?s=!1:(Ve(o,t),!n&&l===1&&delete o._):(s=!t.$stable,Cl(t,o)),i=t}else t&&(Al(e,t),i={default:1});if(s)for(const l in o)!Ll(l)&&i[l]==null&&delete o[l]};function kr(e,t,n,r,o=!1){if(Z(e)){e.forEach((d,m)=>kr(d,t&&(Z(t)?t[m]:t),n,r,o));return}if(vn(r)&&!o)return;const s=r.shapeFlag&4?Gr(r.component)||r.component.proxy:r.el,i=o?null:s,{i:l,r:a}=e,c=t&&t.r,u=l.refs===Le?l.refs={}:l.refs,f=l.setupState;if(c!=null&&c!==a&&(ve(c)?(u[c]=null,he(f,c)&&(f[c]=null)):Fe(c)&&(c.value=null)),ae(a))Nt(a,l,12,[i,u]);else{const d=ve(a),m=Fe(a);if(d||m){const y=()=>{if(e.f){const T=d?he(f,a)?f[a]:u[a]:a.value;o?Z(T)&&Vo(T,s):Z(T)?T.includes(s)||T.push(s):d?(u[a]=[s],he(f,a)&&(f[a]=u[a])):(a.value=[s],e.k&&(u[e.k]=a.value))}else d?(u[a]=i,he(f,a)&&(f[a]=i)):m&&(a.value=i,e.k&&(u[e.k]=i))};i?(y.id=-1,Ye(y,n)):y()}}}let Rt=!1;const hr=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",pr=e=>e.nodeType===8;function cu(e){const{mt:t,p:n,o:{patchProp:r,createText:o,nextSibling:s,parentNode:i,remove:l,insert:a,createComment:c}}=e,u=(g,E)=>{if(!E.hasChildNodes()){n(null,g,E),xr(),E._vnode=g;return}Rt=!1,f(E.firstChild,g,null,null,null),xr(),E._vnode=g,Rt&&console.error("Hydration completed but contains mismatches.")},f=(g,E,z,Y,H,b=!1)=>{const S=pr(g)&&g.data==="[",I=()=>T(g,E,z,Y,H,S),{type:B,ref:L,shapeFlag:M,patchFlag:oe}=E;let ie=g.nodeType;E.el=g,oe===-2&&(b=!1,E.dynamicChildren=null);let k=null;switch(B){case gn:ie!==3?E.children===""?(a(E.el=o(""),i(g),g),k=g):k=I():(g.data!==E.children&&(Rt=!0,g.data=E.children),k=s(g));break;case tt:R(g)?(k=s(g),P(E.el=g.content.firstChild,g,z)):ie!==8||S?k=I():k=s(g);break;case Nn:if(S&&(g=s(g),ie=g.nodeType),ie===1||ie===3){k=g;const J=!E.children.length;for(let q=0;q{b=b||!!E.dynamicChildren;const{type:S,props:I,patchFlag:B,shapeFlag:L,dirs:M,transition:oe}=E,ie=S==="input"&&M||S==="option";if(ie||B!==-1){if(M&&mt(E,null,z,"created"),I)if(ie||!b||B&48)for(const q in I)(ie&&q.endsWith("value")||Yn(q)&&!Mn(q))&&r(g,q,null,I[q],!1,void 0,z);else I.onClick&&r(g,"onClick",null,I.onClick,!1,void 0,z);let k;(k=I&&I.onVnodeBeforeMount)&&rt(k,z,E);let J=!1;if(R(g)){J=xl(Y,oe)&&z&&z.vnode.props&&z.vnode.props.appear;const q=g.content.firstChild;J&&oe.beforeEnter(q),P(q,g,z),E.el=g=q}if(M&&mt(E,null,z,"beforeMount"),((k=I&&I.onVnodeMounted)||M||J)&&dl(()=>{k&&rt(k,z,E),J&&oe.enter(g),M&&mt(E,null,z,"mounted")},Y),L&16&&!(I&&(I.innerHTML||I.textContent))){let q=m(g.firstChild,E,g,z,Y,H,b);for(;q;){Rt=!0;const ye=q;q=q.nextSibling,l(ye)}}else L&8&&g.textContent!==E.children&&(Rt=!0,g.textContent=E.children)}return g.nextSibling},m=(g,E,z,Y,H,b,S)=>{S=S||!!E.dynamicChildren;const I=E.children,B=I.length;for(let L=0;L{const{slotScopeIds:S}=E;S&&(H=H?H.concat(S):S);const I=i(g),B=m(s(g),E,I,z,Y,H,b);return B&&pr(B)&&B.data==="]"?s(E.anchor=B):(Rt=!0,a(E.anchor=c("]"),I,B),B)},T=(g,E,z,Y,H,b)=>{if(Rt=!0,E.el=null,b){const B=A(g);for(;;){const L=s(g);if(L&&L!==B)l(L);else break}}const S=s(g),I=i(g);return l(g),n(null,E,I,S,z,Y,hr(I),H),S},A=(g,E="[",z="]")=>{let Y=0;for(;g;)if(g=s(g),g&&pr(g)&&(g.data===E&&Y++,g.data===z)){if(Y===0)return s(g);Y--}return g},P=(g,E,z)=>{const Y=E.parentNode;Y&&Y.replaceChild(g,E);let H=z;for(;H;)H.vnode.el===E&&(H.vnode.el=H.subTree.el=g),H=H.parent},R=g=>g.nodeType===1&&g.tagName.toLowerCase()==="template";return[u,f]}const Ye=dl;function uu(e){return fu(e,cu)}function fu(e,t){const n=_o();n.__VUE__=!0;const{insert:r,remove:o,patchProp:s,createElement:i,createText:l,createComment:a,setText:c,setElementText:u,parentNode:f,nextSibling:d,setScopeId:m=_t,insertStaticContent:y}=e,T=(h,p,v,w=null,x=null,O=null,U=!1,$=null,F=!!p.dynamicChildren)=>{if(h===p)return;h&&!Jt(h,p)&&(w=C(h),ke(h,x,O,!0),h=null),p.patchFlag===-2&&(F=!1,p.dynamicChildren=null);const{type:D,ref:X,shapeFlag:G}=p;switch(D){case gn:A(h,p,v,w);break;case tt:P(h,p,v,w);break;case Nn:h==null&&R(p,v,w,U);break;case Te:L(h,p,v,w,x,O,U,$,F);break;default:G&1?z(h,p,v,w,x,O,U,$,F):G&6?M(h,p,v,w,x,O,U,$,F):(G&64||G&128)&&D.process(h,p,v,w,x,O,U,$,F,N)}X!=null&&x&&kr(X,h&&h.ref,O,p||h,!p)},A=(h,p,v,w)=>{if(h==null)r(p.el=l(p.children),v,w);else{const x=p.el=h.el;p.children!==h.children&&c(x,p.children)}},P=(h,p,v,w)=>{h==null?r(p.el=a(p.children||""),v,w):p.el=h.el},R=(h,p,v,w)=>{[h.el,h.anchor]=y(h.children,p,v,w,h.el,h.anchor)},g=({el:h,anchor:p},v,w)=>{let x;for(;h&&h!==p;)x=d(h),r(h,v,w),h=x;r(p,v,w)},E=({el:h,anchor:p})=>{let v;for(;h&&h!==p;)v=d(h),o(h),h=v;o(p)},z=(h,p,v,w,x,O,U,$,F)=>{U=U||p.type==="svg",h==null?Y(p,v,w,x,O,U,$,F):S(h,p,x,O,U,$,F)},Y=(h,p,v,w,x,O,U,$)=>{let F,D;const{type:X,props:G,shapeFlag:ee,transition:le,dirs:fe}=h;if(F=h.el=i(h.type,O,G&&G.is,G),ee&8?u(F,h.children):ee&16&&b(h.children,F,null,w,x,O&&X!=="foreignObject",U,$),fe&&mt(h,null,w,"created"),H(F,h,h.scopeId,U,w),G){for(const be in G)be!=="value"&&!Mn(be)&&s(F,be,null,G[be],O,h.children,w,x,Re);"value"in G&&s(F,"value",null,G.value),(D=G.onVnodeBeforeMount)&&rt(D,w,h)}fe&&mt(h,null,w,"beforeMount");const Ee=xl(x,le);Ee&&le.beforeEnter(F),r(F,p,v),((D=G&&G.onVnodeMounted)||Ee||fe)&&Ye(()=>{D&&rt(D,w,h),Ee&&le.enter(F),fe&&mt(h,null,w,"mounted")},x)},H=(h,p,v,w,x)=>{if(v&&m(h,v),w)for(let O=0;O{for(let D=F;D{const $=p.el=h.el;let{patchFlag:F,dynamicChildren:D,dirs:X}=p;F|=h.patchFlag&16;const G=h.props||Le,ee=p.props||Le;let le;v&&Ut(v,!1),(le=ee.onVnodeBeforeUpdate)&&rt(le,v,p,h),X&&mt(p,h,v,"beforeUpdate"),v&&Ut(v,!0);const fe=x&&p.type!=="foreignObject";if(D?I(h.dynamicChildren,D,$,v,w,fe,O):U||q(h,p,$,null,v,w,fe,O,!1),F>0){if(F&16)B($,p,G,ee,v,w,x);else if(F&2&&G.class!==ee.class&&s($,"class",null,ee.class,x),F&4&&s($,"style",G.style,ee.style,x),F&8){const Ee=p.dynamicProps;for(let be=0;be{le&&rt(le,v,p,h),X&&mt(p,h,v,"updated")},w)},I=(h,p,v,w,x,O,U)=>{for(let $=0;${if(v!==w){if(v!==Le)for(const $ in v)!Mn($)&&!($ in w)&&s(h,$,v[$],null,U,p.children,x,O,Re);for(const $ in w){if(Mn($))continue;const F=w[$],D=v[$];F!==D&&$!=="value"&&s(h,$,D,F,U,p.children,x,O,Re)}"value"in w&&s(h,"value",v.value,w.value)}},L=(h,p,v,w,x,O,U,$,F)=>{const D=p.el=h?h.el:l(""),X=p.anchor=h?h.anchor:l("");let{patchFlag:G,dynamicChildren:ee,slotScopeIds:le}=p;le&&($=$?$.concat(le):le),h==null?(r(D,v,w),r(X,v,w),b(p.children,v,X,x,O,U,$,F)):G>0&&G&64&&ee&&h.dynamicChildren?(I(h.dynamicChildren,ee,v,x,O,U,$),(p.key!=null||x&&p===x.subTree)&&Pl(h,p,!0)):q(h,p,v,X,x,O,U,$,F)},M=(h,p,v,w,x,O,U,$,F)=>{p.slotScopeIds=$,h==null?p.shapeFlag&512?x.ctx.activate(p,v,w,U,F):oe(p,v,w,x,O,U,F):ie(h,p,F)},oe=(h,p,v,w,x,O,U)=>{const $=h.component=yu(h,w,x);if(tr(h)&&($.ctx.renderer=N),Eu($),$.asyncDep){if(x&&x.registerDep($,k),!h.el){const F=$.subTree=se(tt);P(null,F,p,v)}return}k($,h,p,v,x,O,U)},ie=(h,p,v)=>{const w=p.component=h.component;if(Oc(h,p,v))if(w.asyncDep&&!w.asyncResolved){J(w,p,v);return}else w.next=p,Cc(w.update),w.update();else p.el=h.el,w.vnode=p},k=(h,p,v,w,x,O,U)=>{const $=()=>{if(h.isMounted){let{next:X,bu:G,u:ee,parent:le,vnode:fe}=h,Ee=X,be;Ut(h,!1),X?(X.el=fe.el,J(h,X,U)):X=fe,G&&Er(G),(be=X.props&&X.props.onVnodeBeforeUpdate)&&rt(be,le,X,fe),Ut(h,!0);const Se=Xr(h),at=h.subTree;h.subTree=Se,T(at,Se,f(at.el),C(at),h,x,O),X.el=Se.el,Ee===null&&kc(h,Se.el),ee&&Ye(ee,x),(be=X.props&&X.props.onVnodeUpdated)&&Ye(()=>rt(be,le,X,fe),x)}else{let X;const{el:G,props:ee}=p,{bm:le,m:fe,parent:Ee}=h,be=vn(p);if(Ut(h,!1),le&&Er(le),!be&&(X=ee&&ee.onVnodeBeforeMount)&&rt(X,Ee,p),Ut(h,!0),G&&ue){const Se=()=>{h.subTree=Xr(h),ue(G,h.subTree,h,x,null)};be?p.type.__asyncLoader().then(()=>!h.isUnmounted&&Se()):Se()}else{const Se=h.subTree=Xr(h);T(null,Se,v,w,h,x,O),p.el=Se.el}if(fe&&Ye(fe,x),!be&&(X=ee&&ee.onVnodeMounted)){const Se=p;Ye(()=>rt(X,Ee,Se),x)}(p.shapeFlag&256||Ee&&vn(Ee.vnode)&&Ee.vnode.shapeFlag&256)&&h.a&&Ye(h.a,x),h.isMounted=!0,p=v=w=null}},F=h.effect=new zo($,()=>jr(D),h.scope),D=h.update=()=>F.run();D.id=h.uid,Ut(h,!0),D()},J=(h,p,v)=>{p.component=h;const w=h.vnode.props;h.vnode=p,h.next=null,su(h,p.props,w,v),au(h,p.children,v),Tn(),Rs(),Ln()},q=(h,p,v,w,x,O,U,$,F=!1)=>{const D=h&&h.children,X=h?h.shapeFlag:0,G=p.children,{patchFlag:ee,shapeFlag:le}=p;if(ee>0){if(ee&128){Me(D,G,v,w,x,O,U,$,F);return}else if(ee&256){ye(D,G,v,w,x,O,U,$,F);return}}le&8?(X&16&&Re(D,x,O),G!==D&&u(v,G)):X&16?le&16?Me(D,G,v,w,x,O,U,$,F):Re(D,x,O,!0):(X&8&&u(v,""),le&16&&b(G,v,w,x,O,U,$,F))},ye=(h,p,v,w,x,O,U,$,F)=>{h=h||dn,p=p||dn;const D=h.length,X=p.length,G=Math.min(D,X);let ee;for(ee=0;eeX?Re(h,x,O,!0,!1,G):b(p,v,w,x,O,U,$,F,G)},Me=(h,p,v,w,x,O,U,$,F)=>{let D=0;const X=p.length;let G=h.length-1,ee=X-1;for(;D<=G&&D<=ee;){const le=h[D],fe=p[D]=F?Dt(p[D]):ut(p[D]);if(Jt(le,fe))T(le,fe,v,null,x,O,U,$,F);else break;D++}for(;D<=G&&D<=ee;){const le=h[G],fe=p[ee]=F?Dt(p[ee]):ut(p[ee]);if(Jt(le,fe))T(le,fe,v,null,x,O,U,$,F);else break;G--,ee--}if(D>G){if(D<=ee){const le=ee+1,fe=leee)for(;D<=G;)ke(h[D],x,O,!0),D++;else{const le=D,fe=D,Ee=new Map;for(D=fe;D<=ee;D++){const Xe=p[D]=F?Dt(p[D]):ut(p[D]);Xe.key!=null&&Ee.set(Xe.key,D)}let be,Se=0;const at=ee-fe+1;let on=!1,gs=0;const Pn=new Array(at);for(D=0;D=at){ke(Xe,x,O,!0);continue}let pt;if(Xe.key!=null)pt=Ee.get(Xe.key);else for(be=fe;be<=ee;be++)if(Pn[be-fe]===0&&Jt(Xe,p[be])){pt=be;break}pt===void 0?ke(Xe,x,O,!0):(Pn[pt-fe]=D+1,pt>=gs?gs=pt:on=!0,T(Xe,p[pt],v,null,x,O,U,$,F),Se++)}const bs=on?du(Pn):dn;for(be=bs.length-1,D=at-1;D>=0;D--){const Xe=fe+D,pt=p[Xe],ys=Xe+1{const{el:O,type:U,transition:$,children:F,shapeFlag:D}=h;if(D&6){Be(h.component.subTree,p,v,w);return}if(D&128){h.suspense.move(p,v,w);return}if(D&64){U.move(h,p,v,N);return}if(U===Te){r(O,p,v);for(let G=0;G$.enter(O),x);else{const{leave:G,delayLeave:ee,afterLeave:le}=$,fe=()=>r(O,p,v),Ee=()=>{G(O,()=>{fe(),le&&le()})};ee?ee(O,fe,Ee):Ee()}else r(O,p,v)},ke=(h,p,v,w=!1,x=!1)=>{const{type:O,props:U,ref:$,children:F,dynamicChildren:D,shapeFlag:X,patchFlag:G,dirs:ee}=h;if($!=null&&kr($,null,v,h,!0),X&256){p.ctx.deactivate(h);return}const le=X&1&&ee,fe=!vn(h);let Ee;if(fe&&(Ee=U&&U.onVnodeBeforeUnmount)&&rt(Ee,p,h),X&6)je(h.component,v,w);else{if(X&128){h.suspense.unmount(v,w);return}le&&mt(h,null,p,"beforeUnmount"),X&64?h.type.remove(h,p,v,x,N,w):D&&(O!==Te||G>0&&G&64)?Re(D,p,v,!1,!0):(O===Te&&G&384||!x&&X&16)&&Re(F,p,v),w&&Ue(h)}(fe&&(Ee=U&&U.onVnodeUnmounted)||le)&&Ye(()=>{Ee&&rt(Ee,p,h),le&&mt(h,null,p,"unmounted")},v)},Ue=h=>{const{type:p,el:v,anchor:w,transition:x}=h;if(p===Te){lt(v,w);return}if(p===Nn){E(h);return}const O=()=>{o(v),x&&!x.persisted&&x.afterLeave&&x.afterLeave()};if(h.shapeFlag&1&&x&&!x.persisted){const{leave:U,delayLeave:$}=x,F=()=>U(v,O);$?$(h.el,O,F):F()}else O()},lt=(h,p)=>{let v;for(;h!==p;)v=d(h),o(h),h=v;o(p)},je=(h,p,v)=>{const{bum:w,scope:x,update:O,subTree:U,um:$}=h;w&&Er(w),x.stop(),O&&(O.active=!1,ke(U,h,p,v)),$&&Ye($,p),Ye(()=>{h.isUnmounted=!0},p),p&&p.pendingBranch&&!p.isUnmounted&&h.asyncDep&&!h.asyncResolved&&h.suspenseId===p.pendingId&&(p.deps--,p.deps===0&&p.resolve())},Re=(h,p,v,w=!1,x=!1,O=0)=>{for(let U=O;Uh.shapeFlag&6?C(h.component.subTree):h.shapeFlag&128?h.suspense.next():d(h.anchor||h.el),W=(h,p,v)=>{h==null?p._vnode&&ke(p._vnode,null,null,!0):T(p._vnode||null,h,p,null,null,null,v),Rs(),xr(),p._vnode=h},N={p:T,um:ke,m:Be,r:Ue,mt:oe,mc:b,pc:q,pbc:I,n:C,o:e};let Q,ue;return t&&([Q,ue]=t(N)),{render:W,hydrate:Q,createApp:ru(W,Q)}}function Ut({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function xl(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Pl(e,t,n=!1){const r=e.children,o=t.children;if(Z(r)&&Z(o))for(let s=0;s>1,e[n[l]]0&&(t[r]=n[s-1]),n[s]=r)}}for(s=n.length,i=n[s-1];s-- >0;)n[s]=i,i=t[i];return n}const hu=e=>e.__isTeleport,Te=Symbol.for("v-fgt"),gn=Symbol.for("v-txt"),tt=Symbol.for("v-cmt"),Nn=Symbol.for("v-stc"),Vn=[];let dt=null;function K(e=!1){Vn.push(dt=e?null:[])}function pu(){Vn.pop(),dt=Vn[Vn.length-1]||null}let Un=1;function zs(e){Un+=e}function Rl(e){return e.dynamicChildren=Un>0?dt||dn:null,pu(),Un>0&&dt&&dt.push(e),e}function te(e,t,n,r,o,s){return Rl(pe(e,t,n,r,o,s,!0))}function Oe(e,t,n,r,o){return Rl(se(e,t,n,r,o,!0))}function Sr(e){return e?e.__v_isVNode===!0:!1}function Jt(e,t){return e.type===t.type&&e.key===t.key}const qr="__vInternal",Il=({key:e})=>e??null,wr=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ve(e)||Fe(e)||ae(e)?{i:ze,r:e,k:t,f:!!n}:e:null);function pe(e,t=null,n=null,r=0,o=null,s=e===Te?0:1,i=!1,l=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Il(t),ref:t&&wr(t),scopeId:ul,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:r,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:ze};return l?(Xo(a,n),s&128&&e.normalize(a)):n&&(a.shapeFlag|=ve(n)?8:16),Un>0&&!i&&dt&&(a.patchFlag>0||s&6)&&a.patchFlag!==32&&dt.push(a),a}const se=mu;function mu(e,t=null,n=null,r=0,o=null,s=!1){if((!e||e===Sc)&&(e=tt),Sr(e)){const l=Bt(e,t,!0);return n&&Xo(l,n),Un>0&&!s&&dt&&(l.shapeFlag&6?dt[dt.indexOf(e)]=l:dt.push(l)),l.patchFlag|=-2,l}if(Au(e)&&(e=e.__vccOpts),t){t=vu(t);let{class:l,style:a}=t;l&&!ve(l)&&(t.class=Je(l)),Ae(a)&&(nl(a)&&!Z(a)&&(a=Ve({},a)),t.style=Jn(a))}const i=ve(e)?1:Mc(e)?128:hu(e)?64:Ae(e)?4:ae(e)?2:0;return pe(e,t,n,r,o,i,s,!0)}function vu(e){return e?nl(e)||qr in e?Ve({},e):e:null}function Bt(e,t,n=!1){const{props:r,ref:o,patchFlag:s,children:i}=e,l=t?Po(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&Il(l),ref:t&&t.ref?n&&o?Z(o)?o.concat(wr(t)):[o,wr(t)]:wr(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Te?s===-1?16:s|16:s,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Bt(e.ssContent),ssFallback:e.ssFallback&&Bt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function jt(e=" ",t=0){return se(gn,null,e,t)}function _u(e,t){const n=se(Nn,null,e);return n.staticCount=t,n}function Ie(e="",t=!1){return t?(K(),Oe(tt,null,e)):se(tt,null,e)}function ut(e){return e==null||typeof e=="boolean"?se(tt):Z(e)?se(Te,null,e.slice()):typeof e=="object"?Dt(e):se(gn,null,String(e))}function Dt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Bt(e)}function Xo(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(Z(t))n=16;else if(typeof t=="object")if(r&65){const o=t.default;o&&(o._c&&(o._d=!1),Xo(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!(qr in t)?t._ctx=ze:o===3&&ze&&(ze.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else ae(t)?(t={default:t,_ctx:ze},n=32):(t=String(t),r&64?(n=16,t=[jt(t)]):n=8);e.children=t,e.shapeFlag|=n}function Po(...e){const t={};for(let n=0;n$e||ze;let ts,sn,Bs="__VUE_INSTANCE_SETTERS__";(sn=_o()[Bs])||(sn=_o()[Bs]=[]),sn.push(e=>$e=e),ts=e=>{sn.length>1?sn.forEach(t=>t(e)):sn[0](e)};const bn=e=>{ts(e),e.scope.on()},en=()=>{$e&&$e.scope.off(),ts(null)};function Ol(e){return e.vnode.shapeFlag&4}let yn=!1;function Eu(e,t=!1){yn=t;const{props:n,children:r}=e.vnode,o=Ol(e);ou(e,n,o,t),lu(e,r);const s=o?wu(e,t):void 0;return yn=!1,s}function wu(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=rl(new Proxy(e.ctx,Jc));const{setup:r}=n;if(r){const o=e.setupContext=r.length>1?Lu(e):null;bn(e),Tn();const s=Nt(r,e,0,[e.props,o]);if(Ln(),en(),Hi(s)){if(s.then(en,en),t)return s.then(i=>{js(e,i,t)}).catch(i=>{Xn(i,e,0)});e.asyncDep=s}else js(e,s,t)}else kl(e,t)}function js(e,t,n){ae(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Ae(t)&&(e.setupState=sl(t)),kl(e,n)}let Ws;function kl(e,t,n){const r=e.type;if(!e.render){if(!t&&Ws&&!r.render){const o=r.template||Qo(e).template;if(o){const{isCustomElement:s,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:a}=r,c=Ve(Ve({isCustomElement:s,delimiters:l},i),a);r.render=Ws(o,c)}}e.render=r.render||_t}{bn(e),Tn();try{Qc(e)}finally{Ln(),en()}}}function Tu(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return Ze(e,"get","$attrs"),t[n]}}))}function Lu(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Tu(e)},slots:e.slots,emit:e.emit,expose:t}}function Gr(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(sl(rl(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in $n)return $n[n](e)},has(t,n){return n in t||n in $n}}))}function Cu(e,t=!0){return ae(e)?e.displayName||e.name:e.name||t&&e.__name}function Au(e){return ae(e)&&"__vccOpts"in e}const j=(e,t)=>wc(e,t,yn);function ne(e,t,n){const r=arguments.length;return r===2?Ae(t)&&!Z(t)?Sr(t)?se(e,null,[t]):se(e,t):se(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Sr(n)&&(n=[n]),se(e,t,n))}const xu=Symbol.for("v-scx"),Pu=()=>Pe(xu),Ru="3.3.8",Iu="http://www.w3.org/2000/svg",Qt=typeof document<"u"?document:null,Us=Qt&&Qt.createElement("template"),Ou={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o=t?Qt.createElementNS(Iu,e):Qt.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&o.setAttribute("multiple",r.multiple),o},createText:e=>Qt.createTextNode(e),createComment:e=>Qt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Qt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,s){const i=n?n.previousSibling:t.lastChild;if(o&&(o===s||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===s||!(o=o.nextSibling)););else{Us.innerHTML=r?`${e}`:e;const l=Us.content;if(r){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},It="transition",Rn="animation",Kn=Symbol("_vtc"),An=(e,{slots:t})=>ne(Hc,ku(e),t);An.displayName="Transition";const Sl={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};An.props=Ve({},ml,Sl);const Kt=(e,t=[])=>{Z(e)?e.forEach(n=>n(...t)):e&&e(...t)},Ks=e=>e?Z(e)?e.some(t=>t.length>1):e.length>1:!1;function ku(e){const t={};for(const L in e)L in Sl||(t[L]=e[L]);if(e.css===!1)return t;const{name:n="v",type:r,duration:o,enterFromClass:s=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:a=s,appearActiveClass:c=i,appearToClass:u=l,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:d=`${n}-leave-active`,leaveToClass:m=`${n}-leave-to`}=e,y=Su(o),T=y&&y[0],A=y&&y[1],{onBeforeEnter:P,onEnter:R,onEnterCancelled:g,onLeave:E,onLeaveCancelled:z,onBeforeAppear:Y=P,onAppear:H=R,onAppearCancelled:b=g}=t,S=(L,M,oe)=>{qt(L,M?u:l),qt(L,M?c:i),oe&&oe()},I=(L,M)=>{L._isLeaving=!1,qt(L,f),qt(L,m),qt(L,d),M&&M()},B=L=>(M,oe)=>{const ie=L?H:R,k=()=>S(M,L,oe);Kt(ie,[M,k]),qs(()=>{qt(M,L?a:s),Ot(M,L?u:l),Ks(ie)||Gs(M,r,T,k)})};return Ve(t,{onBeforeEnter(L){Kt(P,[L]),Ot(L,s),Ot(L,i)},onBeforeAppear(L){Kt(Y,[L]),Ot(L,a),Ot(L,c)},onEnter:B(!1),onAppear:B(!0),onLeave(L,M){L._isLeaving=!0;const oe=()=>I(L,M);Ot(L,f),$u(),Ot(L,d),qs(()=>{L._isLeaving&&(qt(L,f),Ot(L,m),Ks(E)||Gs(L,r,A,oe))}),Kt(E,[L,oe])},onEnterCancelled(L){S(L,!1),Kt(g,[L])},onAppearCancelled(L){S(L,!0),Kt(b,[L])},onLeaveCancelled(L){I(L),Kt(z,[L])}})}function Su(e){if(e==null)return null;if(Ae(e))return[ro(e.enter),ro(e.leave)];{const t=ro(e);return[t,t]}}function ro(e){return Va(e)}function Ot(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Kn]||(e[Kn]=new Set)).add(t)}function qt(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[Kn];n&&(n.delete(t),n.size||(e[Kn]=void 0))}function qs(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Du=0;function Gs(e,t,n,r){const o=e._endId=++Du,s=()=>{o===e._endId&&r()};if(n)return setTimeout(s,n);const{type:i,timeout:l,propCount:a}=Mu(e,t);if(!i)return r();const c=i+"end";let u=0;const f=()=>{e.removeEventListener(c,d),s()},d=m=>{m.target===e&&++u>=a&&f()};setTimeout(()=>{u(n[y]||"").split(", "),o=r(`${It}Delay`),s=r(`${It}Duration`),i=Ys(o,s),l=r(`${Rn}Delay`),a=r(`${Rn}Duration`),c=Ys(l,a);let u=null,f=0,d=0;t===It?i>0&&(u=It,f=i,d=s.length):t===Rn?c>0&&(u=Rn,f=c,d=a.length):(f=Math.max(i,c),u=f>0?i>c?It:Rn:null,d=u?u===It?s.length:a.length:0);const m=u===It&&/\b(transform|all)(,|$)/.test(r(`${It}Property`).toString());return{type:u,timeout:f,propCount:d,hasTransform:m}}function Ys(e,t){for(;e.lengthJs(n)+Js(e[r])))}function Js(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function $u(){return document.body.offsetHeight}function Nu(e,t,n){const r=e[Kn];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const ns=Symbol("_vod"),Dr={beforeMount(e,{value:t},{transition:n}){e[ns]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):In(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),In(e,!0),r.enter(e)):r.leave(e,()=>{In(e,!1)}):In(e,t))},beforeUnmount(e,{value:t}){In(e,t)}};function In(e,t){e.style.display=t?e[ns]:"none"}function Vu(e,t,n){const r=e.style,o=ve(n);if(n&&!o){if(t&&!ve(t))for(const s in t)n[s]==null&&Ro(r,s,"");for(const s in n)Ro(r,s,n[s])}else{const s=r.display;o?t!==n&&(r.cssText=n):t&&e.removeAttribute("style"),ns in e&&(r.display=s)}}const Qs=/\s*!important$/;function Ro(e,t,n){if(Z(n))n.forEach(r=>Ro(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Hu(e,t);Qs.test(n)?e.setProperty(nn(r),n.replace(Qs,""),"important"):e[r]=n}}const Zs=["Webkit","Moz","ms"],oo={};function Hu(e,t){const n=oo[t];if(n)return n;let r=bt(t);if(r!=="filter"&&r in e)return oo[t]=r;r=zr(r);for(let o=0;oso||(Uu.then(()=>so=0),so=Date.now());function qu(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;st(Gu(r,n.value),t,5,[r])};return n.value=e,n.attached=Ku(),n}function Gu(e,t){if(Z(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>o=>!o._stopped&&r&&r(o))}else return t}const ni=/^on[a-z]/,Yu=(e,t,n,r,o=!1,s,i,l,a)=>{t==="class"?Nu(e,r,o):t==="style"?Vu(e,n,r):Yn(t)?No(t)||ju(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Ju(e,t,r,o))?zu(e,t,r,s,i,l,a):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Fu(e,t,r,o))};function Ju(e,t,n,r){return r?!!(t==="innerHTML"||t==="textContent"||t in e&&ni.test(t)&&ae(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||ni.test(t)&&ve(n)?!1:t in e}const ri=e=>{const t=e.props["onUpdate:modelValue"]||!1;return Z(t)?n=>Er(t,n):t};function Qu(e){e.target.composing=!0}function oi(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const io=Symbol("_assign"),Uv={created(e,{modifiers:{lazy:t,trim:n,number:r}},o){e[io]=ri(o);const s=r||o.props&&o.props.type==="number";an(e,t?"change":"input",i=>{if(i.target.composing)return;let l=e.value;n&&(l=l.trim()),s&&(l=vo(l)),e[io](l)}),n&&an(e,"change",()=>{e.value=e.value.trim()}),t||(an(e,"compositionstart",Qu),an(e,"compositionend",oi),an(e,"change",oi))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:o}},s){if(e[io]=ri(s),e.composing||document.activeElement===e&&e.type!=="range"&&(n||r&&e.value.trim()===t||(o||e.type==="number")&&vo(e.value)===t))return;const i=t??"";e.value!==i&&(e.value=i)}},Zu=["ctrl","shift","alt","meta"],Xu={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Zu.some(n=>e[`${n}Key`]&&!t.includes(n))},Kv=(e,t)=>(n,...r)=>{for(let o=0;on=>{if(!("key"in n))return;const r=nn(n.key);if(t.some(o=>o===r||ef[o]===r))return e(n)},nf=Ve({patchProp:Yu},Ou);let lo,si=!1;function rf(){return lo=si?lo:uu(nf),si=!0,lo}const of=(...e)=>{const t=rf().createApp(...e),{mount:n}=t;return t.mount=r=>{const o=sf(r);if(o)return n(o,!0,o instanceof SVGElement)},t};function sf(e){return ve(e)?document.querySelector(e):e}const lf="modulepreload",af=function(e){return"/MicroCityNotes/"+e},ii={},_=function(t,n,r){if(!n||n.length===0)return t();const o=document.getElementsByTagName("link");return Promise.all(n.map(s=>{if(s=af(s),s in ii)return;ii[s]=!0;const i=s.endsWith(".css"),l=i?'[rel="stylesheet"]':"";if(!!r)for(let u=o.length-1;u>=0;u--){const f=o[u];if(f.href===s&&(!i||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${l}`))return;const c=document.createElement("link");if(c.rel=i?"stylesheet":lf,i||(c.as="script",c.crossOrigin=""),c.href=s,document.head.appendChild(c),i)return new Promise((u,f)=>{c.addEventListener("load",u),c.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${s}`)))})})).then(()=>t()).catch(s=>{const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=s,window.dispatchEvent(i),!i.defaultPrevented)throw s})},cf={"v-8daa1a0e":()=>_(()=>import("./index.html-WsgEQayQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2d0a870d":()=>_(()=>import("./index.html-YVKYSuDE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4ee3d2cc":()=>_(()=>import("./1.1_what_microcity_can_do.html-BudeEahj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-498b1a32":()=>_(()=>import("./2.1_showing_a_world_map.html-F73HLlmh.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0f6857b8":()=>_(()=>import("./2.2_searching_for_countries.html-t7DQyHf7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-27daeef9":()=>_(()=>import("./3.1_ui_overview.html-v38UIHQc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3c8d6dee":()=>_(()=>import("./3.2_vector_shapes.html-hHGdBrtV.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a2d64ac":()=>_(()=>import("./3.3_raster_grids.html-OMCyU_6r.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-26445025":()=>_(()=>import("./3.4_3d_scenes.html-E-00tpZF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b2a5ca98":()=>_(()=>import("./3.5_tables.html-LpE0kpTR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8532c374":()=>_(()=>import("./3.6_maps_and_layers.html-T_p6rWde.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-656b8bd0":()=>_(()=>import("./3.7_modules.html-yzio17Ud.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4c59099a":()=>_(()=>import("./4.1_si_overview.html-niv4qRLq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-68871b76":()=>_(()=>import("./4.2_ui_control.html-qgHwWAaN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3c0f83c0":()=>_(()=>import("./4.3_shapes_and_tables.html-Ix5omLFZ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c670a3a8":()=>_(()=>import("./4.4_grids.html-JfxVQVat.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-672fdfba":()=>_(()=>import("./4.5_3d_scenes.html-rRFZU4Tx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-34511d54":()=>_(()=>import("./4.6_networks.html-0YdpivDj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6802fed2":()=>_(()=>import("./4.7_des_simulations.html-W4OcSvr1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-64fe0a3e":()=>_(()=>import("./4.8_mixed_integer_programming.html-TGfmzRJO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-147825fb":()=>_(()=>import("./index.html-2U8qpeQG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0be8554c":()=>_(()=>import("./3d-objects.html-jGytICR_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41e82e22":()=>_(()=>import("./3d-scene.html-QeNNxNdQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e8b6c472":()=>_(()=>import("./index.html-nYDcqjx5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7fd381e2":()=>_(()=>import("./cy-simulation.html-0hk7J5DH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-44b81126":()=>_(()=>import("./debug.html-YQ27enDU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0ceacb2b":()=>_(()=>import("./event-scheduling.html-_wHScoNu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8138aba4":()=>_(()=>import("./lp.html-jETCO9wn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ed3d82b0":()=>_(()=>import("./lua.html-B6d7gWD8.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-dfdf5468":()=>_(()=>import("./mip.html-6_WAczY6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-16cb829c":()=>_(()=>import("./network.html-qaPJNigq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c58fd9e0":()=>_(()=>import("./oop.html-GH4Nnww4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f610fd24":()=>_(()=>import("./plots.html-wJZ2mJax.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-19652be0":()=>_(()=>import("./timelapse.html-xp-pHQoZ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6bb8b8e5":()=>_(()=>import("./tools.html-hzuhyAmn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-77d2e8b7":()=>_(()=>import("./versions.html-8A5Y-n6r.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-385f9c3c":()=>_(()=>import("./visualization.html-skftd09s.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-187abc41":()=>_(()=>import("./warehouse-simulation.html-rJTy601K.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ae3cdb6":()=>_(()=>import("./web-ui.html-gL6LgUwH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41d66a06":()=>_(()=>import("./1.1_what_microcity_can_do.html-m1yQS0yR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-79ce9d5a":()=>_(()=>import("./2.1_showing_a_world_map.html-6qnXe-uR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-30ccfc90":()=>_(()=>import("./2.2_searching_for_countries.html-I1-AYfhY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-45e45965":()=>_(()=>import("./3.1_ui_overview.html-MdRgXeyu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0434254c":()=>_(()=>import("./3.2_vector_shapes.html-Ggy6120F.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d5147c0":()=>_(()=>import("./3.3_raster_grids.html-t2xEoSZE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5e3d6591":()=>_(()=>import("./3.4_3d_scenes.html-Q6eGIaTn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-42244670":()=>_(()=>import("./3.5_tables.html-p1nKqUcK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-eac61a9c":()=>_(()=>import("./3.6_maps_and_layers.html-IZMNuK0Y.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-35430c3c":()=>_(()=>import("./3.7_modules.html-d3BG3VZc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a627406":()=>_(()=>import("./4.1_si_overview.html-aQjVZ38p.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-da33eb4e":()=>_(()=>import("./4.2_ui_control.html-n4jA58yX.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3aeb278c":()=>_(()=>import("./4.3_shapes_and_tables.html-TBHhEBxq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a1c74cd0":()=>_(()=>import("./4.4_grids.html-1OY5s52Z.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0461258f":()=>_(()=>import("./4.5_3d_scenes.html-wmTORBrk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-10effe6a":()=>_(()=>import("./4.6_networks.html-kqO_isZV.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cd9655fa":()=>_(()=>import("./4.7_des_simulations.html-JlfYhUg2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d7828c2":()=>_(()=>import("./4.7_des_simulations_zh.html-dVopgWmS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2b4c8f66":()=>_(()=>import("./4.8_mixed_integer_programming.html-MExXnfeH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-39540332":()=>_(()=>import("./index.html-a5Ef1Ykb.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6c395474":()=>_(()=>import("./3d-objects.html-AEqGn78x.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-543cd98e":()=>_(()=>import("./3d-scene.html-smFwVKZl.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cefc5a4a":()=>_(()=>import("./index.html-hYpF9QHg.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-46fd19f6":()=>_(()=>import("./cy-simulation.html-5ddk20cl.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3520e381":()=>_(()=>import("./debug.html-80fcUM2q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-63796ad2":()=>_(()=>import("./event-scheduling.html-py4kt8T8.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a86f52cc":()=>_(()=>import("./lp.html-yx0HpcA2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-29921fbc":()=>_(()=>import("./lua.html--q1iToUD.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-304136e0":()=>_(()=>import("./mip.html-EzteSB1w.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-608c75c6":()=>_(()=>import("./network.html-l_dMxKkp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3d68f424":()=>_(()=>import("./oop.html-lICjQDMc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-471724fc":()=>_(()=>import("./plots.html-FPAlzRUf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-51a5edf4":()=>_(()=>import("./timelapse.html-ghI-6cF8.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7994b60e":()=>_(()=>import("./tools.html-PgdIJCR5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ebb0d7ba":()=>_(()=>import("./versions.html-1Kk-C1xB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-00ed9760":()=>_(()=>import("./visualization.html-t9WbOvdj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-716da5ad":()=>_(()=>import("./warehouse-simulation.html-6ARLBksA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-eaa2a0de":()=>_(()=>import("./web-ui.html--l1JvFq2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-31b53ad6":()=>_(()=>import("./index.html-92lUUdK6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3706649a":()=>_(()=>import("./404.html-O1A74s9P.js"),__vite__mapDeps([])).then(({data:e})=>e)},uf=JSON.parse('{"base":"/MicroCityNotes/","lang":"en-US","title":"","description":"","head":[["link",{"rel":"manifest","href":"/MicroCityNotes/manifest.webmanifest","crossorigin":"use-credentials"}],["meta",{"name":"theme-color","content":"#46bd87"}],["meta",{"name":"viewport","content":"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"}]],"locales":{"/":{"lang":"zh-CN","title":"MicroCity笔记","description":"记录MicroCity的学习过程并提供快捷的参考","head":[["meta",{"name":"keywords","content":"MicroCity,笔记,文档"}],["link",{"rel":"manifest","href":"manifest.webmanifest"}],["link",{"rel":"icon","href":"./images/icon_microcity.png"}]]},"/en/":{"lang":"en-US","title":"MicroCity Notes","description":"Record the learning process of MicroCity and provide quick reference","head":[["meta",{"name":"keywords","content":"MicroCity,Notes,Docs"}],["link",{"rel":"manifest","href":"../manifest.webmanifest"}],["link",{"rel":"icon","href":"../images/icon_microcity.png"}]]}}}');var ff=([e,t,n])=>e==="meta"&&t.name?`${e}.${t.name}`:["title","base"].includes(e)?e:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,t,n]),df=e=>{const t=new Set,n=[];return e.forEach(r=>{const o=ff(r);t.has(o)||(t.add(o),n.push(r))}),n},rr=e=>/^(https?:)?\/\//.test(e),hf=e=>/^[a-z][a-z0-9+.-]*:/.test(e),rs=e=>Object.prototype.toString.call(e)==="[object Object]",Dl=e=>e[e.length-1]==="/"?e.slice(0,-1):e,Ml=e=>e[0]==="/"?e.slice(1):e,$l=(e,t)=>{const n=Object.keys(e).sort((r,o)=>{const s=o.split("/").length-r.split("/").length;return s!==0?s:o.length-r.length});for(const r of n)if(t.startsWith(r))return r;return"/"};const Nl={"v-8daa1a0e":V(()=>_(()=>import("./index.html-rmW5MKDv.js"),__vite__mapDeps([0,1,2,3,4]))),"v-2d0a870d":V(()=>_(()=>import("./index.html-dxC6HmKS.js"),__vite__mapDeps([5,1,2,3,4]))),"v-4ee3d2cc":V(()=>_(()=>import("./1.1_what_microcity_can_do.html-HcIFtvfI.js"),__vite__mapDeps([6,7]))),"v-498b1a32":V(()=>_(()=>import("./2.1_showing_a_world_map.html-Ybz9X3FC.js"),__vite__mapDeps([8,3,9,10,11,12]))),"v-0f6857b8":V(()=>_(()=>import("./2.2_searching_for_countries.html-Y0QCK0Nw.js"),__vite__mapDeps([13,14,2]))),"v-27daeef9":V(()=>_(()=>import("./3.1_ui_overview.html-3VU9Yk9s.js"),__vite__mapDeps([15,16]))),"v-3c8d6dee":V(()=>_(()=>import("./3.2_vector_shapes.html-uMTzJRD1.js"),__vite__mapDeps([17,9,18,11,12]))),"v-6a2d64ac":V(()=>_(()=>import("./3.3_raster_grids.html-_OMWjBic.js"),__vite__mapDeps([19,9,20,12,21]))),"v-26445025":V(()=>_(()=>import("./3.4_3d_scenes.html-IfcyMMcw.js"),__vite__mapDeps([22,9,23]))),"v-b2a5ca98":V(()=>_(()=>import("./3.5_tables.html-rfKSY5-v.js"),__vite__mapDeps([24,9,25]))),"v-8532c374":V(()=>_(()=>import("./3.6_maps_and_layers.html-KNvuRdkG.js"),__vite__mapDeps([26,27,12,21]))),"v-656b8bd0":V(()=>_(()=>import("./3.7_modules.html-acS-BfiZ.js"),__vite__mapDeps([28,2,9,4,29]))),"v-4c59099a":V(()=>_(()=>import("./4.1_si_overview.html-mGhzJSIB.js"),__vite__mapDeps([30,2,31,3]))),"v-68871b76":V(()=>_(()=>import("./4.2_ui_control.html-Zsu36Eou.js"),__vite__mapDeps([32,2,33]))),"v-3c0f83c0":V(()=>_(()=>import("./4.3_shapes_and_tables.html-SxckQf89.js"),__vite__mapDeps([34,2]))),"v-c670a3a8":V(()=>_(()=>import("./4.4_grids.html-exxRQ7PN.js"),__vite__mapDeps([35,2]))),"v-672fdfba":V(()=>_(()=>import("./4.5_3d_scenes.html-I_su3OaS.js"),__vite__mapDeps([36,2]))),"v-34511d54":V(()=>_(()=>import("./4.6_networks.html-HJVUieG0.js"),__vite__mapDeps([37,2]))),"v-6802fed2":V(()=>_(()=>import("./4.7_des_simulations.html-Ie9zDG_n.js"),__vite__mapDeps([38,2]))),"v-64fe0a3e":V(()=>_(()=>import("./4.8_mixed_integer_programming.html-spXsyES8.js"),__vite__mapDeps([39,2]))),"v-147825fb":V(()=>_(()=>import("./index.html-WLZyFhZW.js"),__vite__mapDeps([]))),"v-0be8554c":V(()=>_(()=>import("./3d-objects.html-frmlnhRb.js"),__vite__mapDeps([40,41]))),"v-41e82e22":V(()=>_(()=>import("./3d-scene.html-iJwBMXhE.js"),__vite__mapDeps([42,43]))),"v-e8b6c472":V(()=>_(()=>import("./index.html-IqC-sAFX.js"),__vite__mapDeps([]))),"v-7fd381e2":V(()=>_(()=>import("./cy-simulation.html-ms-pVG5v.js"),__vite__mapDeps([44,45]))),"v-44b81126":V(()=>_(()=>import("./debug.html-vC47hElk.js"),__vite__mapDeps([]))),"v-0ceacb2b":V(()=>_(()=>import("./event-scheduling.html-3ysZ_CTt.js"),__vite__mapDeps([46,47]))),"v-8138aba4":V(()=>_(()=>import("./lp.html-m-tLdpGS.js"),__vite__mapDeps([]))),"v-ed3d82b0":V(()=>_(()=>import("./lua.html-JK5rP34K.js"),__vite__mapDeps([]))),"v-dfdf5468":V(()=>_(()=>import("./mip.html-KGIauE4D.js"),__vite__mapDeps([]))),"v-16cb829c":V(()=>_(()=>import("./network.html-IGA5rLvk.js"),__vite__mapDeps([48,49]))),"v-c58fd9e0":V(()=>_(()=>import("./oop.html-VmjZry6A.js"),__vite__mapDeps([50,51]))),"v-f610fd24":V(()=>_(()=>import("./plots.html-KiXIG1Oc.js"),__vite__mapDeps([52,53]))),"v-19652be0":V(()=>_(()=>import("./timelapse.html-VDhH9cuD.js"),__vite__mapDeps([54,55]))),"v-6bb8b8e5":V(()=>_(()=>import("./tools.html-LamHaYH8.js"),__vite__mapDeps([]))),"v-77d2e8b7":V(()=>_(()=>import("./versions.html-aHfbE8Cr.js"),__vite__mapDeps([]))),"v-385f9c3c":V(()=>_(()=>import("./visualization.html-2T-VgKWL.js"),__vite__mapDeps([56,57]))),"v-187abc41":V(()=>_(()=>import("./warehouse-simulation.html-5OK9wBKc.js"),__vite__mapDeps([58,59]))),"v-1ae3cdb6":V(()=>_(()=>import("./web-ui.html-Ub-X1RXi.js"),__vite__mapDeps([60,61,47]))),"v-41d66a06":V(()=>_(()=>import("./1.1_what_microcity_can_do.html-YHpuvmc-.js"),__vite__mapDeps([62,7]))),"v-79ce9d5a":V(()=>_(()=>import("./2.1_showing_a_world_map.html-GZyM8T_I.js"),__vite__mapDeps([63,3,9,10,11,12]))),"v-30ccfc90":V(()=>_(()=>import("./2.2_searching_for_countries.html-OCp2-Zt6.js"),__vite__mapDeps([64,14,2]))),"v-45e45965":V(()=>_(()=>import("./3.1_ui_overview.html-6J3N08CW.js"),__vite__mapDeps([65,16]))),"v-0434254c":V(()=>_(()=>import("./3.2_vector_shapes.html-o5HA4H30.js"),__vite__mapDeps([66,9,18,11,12]))),"v-0d5147c0":V(()=>_(()=>import("./3.3_raster_grids.html-KMfHWMMp.js"),__vite__mapDeps([67,9,20,12,21]))),"v-5e3d6591":V(()=>_(()=>import("./3.4_3d_scenes.html-2qe1Dffq.js"),__vite__mapDeps([68,9,23]))),"v-42244670":V(()=>_(()=>import("./3.5_tables.html-KMEBPMHz.js"),__vite__mapDeps([69,9,25]))),"v-eac61a9c":V(()=>_(()=>import("./3.6_maps_and_layers.html-Zp7Na5N3.js"),__vite__mapDeps([70,27,12,21]))),"v-35430c3c":V(()=>_(()=>import("./3.7_modules.html-mmRRzoSK.js"),__vite__mapDeps([71,2,9,4,29]))),"v-6a627406":V(()=>_(()=>import("./4.1_si_overview.html-3JNy66LR.js"),__vite__mapDeps([72,2,31,3]))),"v-da33eb4e":V(()=>_(()=>import("./4.2_ui_control.html-it8dN_Kd.js"),__vite__mapDeps([73,2,33]))),"v-3aeb278c":V(()=>_(()=>import("./4.3_shapes_and_tables.html-9CbssTxf.js"),__vite__mapDeps([74,2]))),"v-a1c74cd0":V(()=>_(()=>import("./4.4_grids.html-H6iZCbel.js"),__vite__mapDeps([75,2]))),"v-0461258f":V(()=>_(()=>import("./4.5_3d_scenes.html-IYlmTIee.js"),__vite__mapDeps([76,2]))),"v-10effe6a":V(()=>_(()=>import("./4.6_networks.html-Z1GoybBX.js"),__vite__mapDeps([77,2]))),"v-cd9655fa":V(()=>_(()=>import("./4.7_des_simulations.html-WnzqINmi.js"),__vite__mapDeps([78,2]))),"v-4d7828c2":V(()=>_(()=>import("./4.7_des_simulations_zh.html-PYbnXFlK.js"),__vite__mapDeps([79,2]))),"v-2b4c8f66":V(()=>_(()=>import("./4.8_mixed_integer_programming.html-ixWGOETF.js"),__vite__mapDeps([80,2]))),"v-39540332":V(()=>_(()=>import("./index.html-NfP7JmCD.js"),__vite__mapDeps([]))),"v-6c395474":V(()=>_(()=>import("./3d-objects.html-l7ht6tpD.js"),__vite__mapDeps([81,41]))),"v-543cd98e":V(()=>_(()=>import("./3d-scene.html-pmrdLLCG.js"),__vite__mapDeps([82,43]))),"v-cefc5a4a":V(()=>_(()=>import("./index.html-b5l2JDLj.js"),__vite__mapDeps([]))),"v-46fd19f6":V(()=>_(()=>import("./cy-simulation.html-x04vq-Lr.js"),__vite__mapDeps([83,45]))),"v-3520e381":V(()=>_(()=>import("./debug.html-Pj0zKe-s.js"),__vite__mapDeps([]))),"v-63796ad2":V(()=>_(()=>import("./event-scheduling.html-UZg_AtmL.js"),__vite__mapDeps([84,47]))),"v-a86f52cc":V(()=>_(()=>import("./lp.html-BGRyuCz8.js"),__vite__mapDeps([]))),"v-29921fbc":V(()=>_(()=>import("./lua.html-bIzYAnJl.js"),__vite__mapDeps([]))),"v-304136e0":V(()=>_(()=>import("./mip.html-7cWhLBPI.js"),__vite__mapDeps([]))),"v-608c75c6":V(()=>_(()=>import("./network.html-rimWgBRX.js"),__vite__mapDeps([85,49]))),"v-3d68f424":V(()=>_(()=>import("./oop.html-QdhyUyOK.js"),__vite__mapDeps([86,51]))),"v-471724fc":V(()=>_(()=>import("./plots.html-6AeiZZxH.js"),__vite__mapDeps([87,53]))),"v-51a5edf4":V(()=>_(()=>import("./timelapse.html-rfk9Tyut.js"),__vite__mapDeps([88,55]))),"v-7994b60e":V(()=>_(()=>import("./tools.html-Tsv49Nwb.js"),__vite__mapDeps([]))),"v-ebb0d7ba":V(()=>_(()=>import("./versions.html-diw0opQu.js"),__vite__mapDeps([]))),"v-00ed9760":V(()=>_(()=>import("./visualization.html-URi_NNx7.js"),__vite__mapDeps([89,57]))),"v-716da5ad":V(()=>_(()=>import("./warehouse-simulation.html-I2Ep6WY5.js"),__vite__mapDeps([90,59]))),"v-eaa2a0de":V(()=>_(()=>import("./web-ui.html-MXj0sqtU.js"),__vite__mapDeps([91,61,47]))),"v-31b53ad6":V(()=>_(()=>import("./index.html-c3NKfYSn.js"),__vite__mapDeps([]))),"v-3706649a":V(()=>_(()=>import("./404.html-tJ8VjSOS.js"),__vite__mapDeps([])))};var pf=Symbol(""),Vl=Symbol(""),mf=Zn({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),Ht=()=>{const e=Pe(Vl);if(!e)throw new Error("pageData() is called without provider.");return e},Hl=Symbol(""),gt=()=>{const e=Pe(Hl);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},Fl=Symbol(""),vf=()=>{const e=Pe(Fl);if(!e)throw new Error("usePageHead() is called without provider.");return e},_f=Symbol(""),zl=Symbol(""),Bl=()=>{const e=Pe(zl);if(!e)throw new Error("usePageLang() is called without provider.");return e},jl=Symbol(""),gf=()=>{const e=Pe(jl);if(!e)throw new Error("usePageLayout() is called without provider.");return e},bf=ge(cf),os=Symbol(""),or=()=>{const e=Pe(os);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},un=ge(uf),Wl=()=>un,Ul=Symbol(""),ss=()=>{const e=Pe(Ul);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},yf=Symbol(""),Ef="Layout",wf="NotFound",wt=Qn({resolveLayouts:e=>e.reduce((t,n)=>({...t,...n.layouts}),{}),resolvePageData:async e=>{const t=bf.value[e];return await(t==null?void 0:t())??mf},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,n)=>{const r=ve(t.description)?t.description:n.description,o=[...Z(t.head)?t.head:[],...n.head,["title",{},e],["meta",{name:"description",content:r}]];return df(o)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(n=>!!n).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||"en-US",resolvePageLayout:(e,t)=>{let n;if(e.path){const r=e.frontmatter.layout;ve(r)?n=r:n=Ef}else n=wf;return t[n]},resolveRouteLocale:(e,t)=>$l(e,t),resolveSiteLocaleData:(e,t)=>({...e,...e.locales[t]})}),is=ce({name:"ClientOnly",setup(e,t){const n=ge(!1);return De(()=>{n.value=!0}),()=>{var r,o;return n.value?(o=(r=t.slots).default)==null?void 0:o.call(r):null}}}),Tf=ce({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=Ht(),n=j(()=>Nl[e.pageKey||t.value.key]);return()=>n.value?ne(n.value):ne("div","404 Not Found")}}),it=(e={})=>e,Yr=e=>rr(e)?e:`/MicroCityNotes/${Ml(e)}`;function Kl(e,t,n){var r,o,s;t===void 0&&(t=50),n===void 0&&(n={});var i=(r=n.isImmediate)!=null&&r,l=(o=n.callback)!=null&&o,a=n.maxWait,c=Date.now(),u=[];function f(){if(a!==void 0){var m=Date.now()-c;if(m+t>=a)return a-m}return t}var d=function(){var m=[].slice.call(arguments),y=this;return new Promise(function(T,A){var P=i&&s===void 0;if(s!==void 0&&clearTimeout(s),s=setTimeout(function(){if(s=void 0,c=Date.now(),!i){var g=e.apply(y,m);l&&l(g),u.forEach(function(E){return(0,E.resolve)(g)}),u=[]}},f()),P){var R=e.apply(y,m);return l&&l(R),T(R)}u.push({resolve:T,reject:A})})};return d.cancel=function(m){s!==void 0&&clearTimeout(s),u.forEach(function(y){return(0,y.reject)(m)}),u=[]},d}/*! + * vue-router v4.2.5 + * (c) 2023 Eduardo San Martin Morote + * @license MIT + */const cn=typeof window<"u";function Lf(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const _e=Object.assign;function ao(e,t){const n={};for(const r in t){const o=t[r];n[r]=ht(o)?o.map(e):e(o)}return n}const Hn=()=>{},ht=Array.isArray,Cf=/\/$/,Af=e=>e.replace(Cf,"");function co(e,t,n="/"){let r,o={},s="",i="";const l=t.indexOf("#");let a=t.indexOf("?");return l=0&&(a=-1),a>-1&&(r=t.slice(0,a),s=t.slice(a+1,l>-1?l:t.length),o=e(s)),l>-1&&(r=r||t.slice(0,l),i=t.slice(l,t.length)),r=If(r??t,n),{fullPath:r+(s&&"?")+s+i,path:r,query:o,hash:i}}function xf(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function li(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Pf(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&En(t.matched[r],n.matched[o])&&ql(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function En(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function ql(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!Rf(e[n],t[n]))return!1;return!0}function Rf(e,t){return ht(e)?ai(e,t):ht(t)?ai(t,e):e===t}function ai(e,t){return ht(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function If(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),o=r[r.length-1];(o===".."||o===".")&&r.push("");let s=n.length-1,i,l;for(i=0;i1&&s--;else break;return n.slice(0,s).join("/")+"/"+r.slice(i-(i===r.length?1:0)).join("/")}var qn;(function(e){e.pop="pop",e.push="push"})(qn||(qn={}));var Fn;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Fn||(Fn={}));function Of(e){if(!e)if(cn){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Af(e)}const kf=/^[^#]+#/;function Sf(e,t){return e.replace(kf,"#")+t}function Df(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const Jr=()=>({left:window.pageXOffset,top:window.pageYOffset});function Mf(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),o=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=Df(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function ci(e,t){return(history.state?history.state.position-t:-1)+e}const Io=new Map;function $f(e,t){Io.set(e,t)}function Nf(e){const t=Io.get(e);return Io.delete(e),t}let Vf=()=>location.protocol+"//"+location.host;function Gl(e,t){const{pathname:n,search:r,hash:o}=t,s=e.indexOf("#");if(s>-1){let l=o.includes(e.slice(s))?e.slice(s).length:1,a=o.slice(l);return a[0]!=="/"&&(a="/"+a),li(a,"")}return li(n,e)+r+o}function Hf(e,t,n,r){let o=[],s=[],i=null;const l=({state:d})=>{const m=Gl(e,location),y=n.value,T=t.value;let A=0;if(d){if(n.value=m,t.value=d,i&&i===y){i=null;return}A=T?d.position-T.position:0}else r(m);o.forEach(P=>{P(n.value,y,{delta:A,type:qn.pop,direction:A?A>0?Fn.forward:Fn.back:Fn.unknown})})};function a(){i=n.value}function c(d){o.push(d);const m=()=>{const y=o.indexOf(d);y>-1&&o.splice(y,1)};return s.push(m),m}function u(){const{history:d}=window;d.state&&d.replaceState(_e({},d.state,{scroll:Jr()}),"")}function f(){for(const d of s)d();s=[],window.removeEventListener("popstate",l),window.removeEventListener("beforeunload",u)}return window.addEventListener("popstate",l),window.addEventListener("beforeunload",u,{passive:!0}),{pauseListeners:a,listen:c,destroy:f}}function ui(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?Jr():null}}function Ff(e){const{history:t,location:n}=window,r={value:Gl(e,n)},o={value:t.state};o.value||s(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function s(a,c,u){const f=e.indexOf("#"),d=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+a:Vf()+e+a;try{t[u?"replaceState":"pushState"](c,"",d),o.value=c}catch(m){console.error(m),n[u?"replace":"assign"](d)}}function i(a,c){const u=_e({},t.state,ui(o.value.back,a,o.value.forward,!0),c,{position:o.value.position});s(a,u,!0),r.value=a}function l(a,c){const u=_e({},o.value,t.state,{forward:a,scroll:Jr()});s(u.current,u,!0);const f=_e({},ui(r.value,a,null),{position:u.position+1},c);s(a,f,!1),r.value=a}return{location:r,state:o,push:l,replace:i}}function zf(e){e=Of(e);const t=Ff(e),n=Hf(e,t.state,t.location,t.replace);function r(s,i=!0){i||n.pauseListeners(),history.go(s)}const o=_e({location:"",base:e,go:r,createHref:Sf.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function Bf(e){return typeof e=="string"||e&&typeof e=="object"}function Yl(e){return typeof e=="string"||typeof e=="symbol"}const Tt={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},Jl=Symbol("");var fi;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(fi||(fi={}));function wn(e,t){return _e(new Error,{type:e,[Jl]:!0},t)}function Et(e,t){return e instanceof Error&&Jl in e&&(t==null||!!(e.type&t))}const di="[^/]+?",jf={sensitive:!1,strict:!1,start:!0,end:!0},Wf=/[.+*?^${}()[\]/\\]/g;function Uf(e,t){const n=_e({},jf,t),r=[];let o=n.start?"^":"";const s=[];for(const c of e){const u=c.length?[]:[90];n.strict&&!c.length&&(o+="/");for(let f=0;ft.length?t.length===1&&t[0]===80?1:-1:0}function qf(e,t){let n=0;const r=e.score,o=t.score;for(;n0&&t[t.length-1]<0}const Gf={type:0,value:""},Yf=/[a-zA-Z0-9_]/;function Jf(e){if(!e)return[[]];if(e==="/")return[[Gf]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(m){throw new Error(`ERR (${n})/"${c}": ${m}`)}let n=0,r=n;const o=[];let s;function i(){s&&o.push(s),s=[]}let l=0,a,c="",u="";function f(){c&&(n===0?s.push({type:0,value:c}):n===1||n===2||n===3?(s.length>1&&(a==="*"||a==="+")&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),s.push({type:1,value:c,regexp:u,repeatable:a==="*"||a==="+",optional:a==="*"||a==="?"})):t("Invalid state to consume buffer"),c="")}function d(){c+=a}for(;l{i(R)}:Hn}function i(u){if(Yl(u)){const f=r.get(u);f&&(r.delete(u),n.splice(n.indexOf(f),1),f.children.forEach(i),f.alias.forEach(i))}else{const f=n.indexOf(u);f>-1&&(n.splice(f,1),u.record.name&&r.delete(u.record.name),u.children.forEach(i),u.alias.forEach(i))}}function l(){return n}function a(u){let f=0;for(;f=0&&(u.record.path!==n[f].record.path||!Ql(u,n[f]));)f++;n.splice(f,0,u),u.record.name&&!mi(u)&&r.set(u.record.name,u)}function c(u,f){let d,m={},y,T;if("name"in u&&u.name){if(d=r.get(u.name),!d)throw wn(1,{location:u});T=d.record.name,m=_e(pi(f.params,d.keys.filter(R=>!R.optional).map(R=>R.name)),u.params&&pi(u.params,d.keys.map(R=>R.name))),y=d.stringify(m)}else if("path"in u)y=u.path,d=n.find(R=>R.re.test(y)),d&&(m=d.parse(y),T=d.record.name);else{if(d=f.name?r.get(f.name):n.find(R=>R.re.test(f.path)),!d)throw wn(1,{location:u,currentLocation:f});T=d.record.name,m=_e({},f.params,u.params),y=d.stringify(m)}const A=[];let P=d;for(;P;)A.unshift(P.record),P=P.parent;return{name:T,path:y,params:m,matched:A,meta:td(A)}}return e.forEach(u=>s(u)),{addRoute:s,resolve:c,removeRoute:i,getRoutes:l,getRecordMatcher:o}}function pi(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function Xf(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:ed(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function ed(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]=typeof n=="object"?n[r]:n;return t}function mi(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function td(e){return e.reduce((t,n)=>_e(t,n.meta),{})}function vi(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}function Ql(e,t){return t.children.some(n=>n===e||Ql(e,n))}const Zl=/#/g,nd=/&/g,rd=/\//g,od=/=/g,sd=/\?/g,Xl=/\+/g,id=/%5B/g,ld=/%5D/g,ea=/%5E/g,ad=/%60/g,ta=/%7B/g,cd=/%7C/g,na=/%7D/g,ud=/%20/g;function ls(e){return encodeURI(""+e).replace(cd,"|").replace(id,"[").replace(ld,"]")}function fd(e){return ls(e).replace(ta,"{").replace(na,"}").replace(ea,"^")}function Oo(e){return ls(e).replace(Xl,"%2B").replace(ud,"+").replace(Zl,"%23").replace(nd,"%26").replace(ad,"`").replace(ta,"{").replace(na,"}").replace(ea,"^")}function dd(e){return Oo(e).replace(od,"%3D")}function hd(e){return ls(e).replace(Zl,"%23").replace(sd,"%3F")}function pd(e){return e==null?"":hd(e).replace(rd,"%2F")}function Mr(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function md(e){const t={};if(e===""||e==="?")return t;const r=(e[0]==="?"?e.slice(1):e).split("&");for(let o=0;os&&Oo(s)):[r&&Oo(r)]).forEach(s=>{s!==void 0&&(t+=(t.length?"&":"")+n,s!=null&&(t+="="+s))})}return t}function vd(e){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=ht(r)?r.map(o=>o==null?null:""+o):r==null?r:""+r)}return t}const _d=Symbol(""),gi=Symbol(""),Qr=Symbol(""),as=Symbol(""),ko=Symbol("");function On(){let e=[];function t(r){return e.push(r),()=>{const o=e.indexOf(r);o>-1&&e.splice(o,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Mt(e,t,n,r,o){const s=r&&(r.enterCallbacks[o]=r.enterCallbacks[o]||[]);return()=>new Promise((i,l)=>{const a=f=>{f===!1?l(wn(4,{from:n,to:t})):f instanceof Error?l(f):Bf(f)?l(wn(2,{from:t,to:f})):(s&&r.enterCallbacks[o]===s&&typeof f=="function"&&s.push(f),i())},c=e.call(r&&r.instances[o],t,n,a);let u=Promise.resolve(c);e.length<3&&(u=u.then(a)),u.catch(f=>l(f))})}function uo(e,t,n,r){const o=[];for(const s of e)for(const i in s.components){let l=s.components[i];if(!(t!=="beforeRouteEnter"&&!s.instances[i]))if(gd(l)){const c=(l.__vccOpts||l)[t];c&&o.push(Mt(c,n,r,s,i))}else{let a=l();o.push(()=>a.then(c=>{if(!c)return Promise.reject(new Error(`Couldn't resolve component "${i}" at "${s.path}"`));const u=Lf(c)?c.default:c;s.components[i]=u;const d=(u.__vccOpts||u)[t];return d&&Mt(d,n,r,s,i)()}))}}return o}function gd(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function bi(e){const t=Pe(Qr),n=Pe(as),r=j(()=>t.resolve(re(e.to))),o=j(()=>{const{matched:a}=r.value,{length:c}=a,u=a[c-1],f=n.matched;if(!u||!f.length)return-1;const d=f.findIndex(En.bind(null,u));if(d>-1)return d;const m=yi(a[c-2]);return c>1&&yi(u)===m&&f[f.length-1].path!==m?f.findIndex(En.bind(null,a[c-2])):d}),s=j(()=>o.value>-1&&wd(n.params,r.value.params)),i=j(()=>o.value>-1&&o.value===n.matched.length-1&&ql(n.params,r.value.params));function l(a={}){return Ed(a)?t[re(e.replace)?"replace":"push"](re(e.to)).catch(Hn):Promise.resolve()}return{route:r,href:j(()=>r.value.href),isActive:s,isExactActive:i,navigate:l}}const bd=ce({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:bi,setup(e,{slots:t}){const n=Qn(bi(e)),{options:r}=Pe(Qr),o=j(()=>({[Ei(e.activeClass,r.linkActiveClass,"router-link-active")]:n.isActive,[Ei(e.exactActiveClass,r.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const s=t.default&&t.default(n);return e.custom?s:ne("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:o.value},s)}}}),yd=bd;function Ed(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function wd(e,t){for(const n in t){const r=t[n],o=e[n];if(typeof r=="string"){if(r!==o)return!1}else if(!ht(o)||o.length!==r.length||r.some((s,i)=>s!==o[i]))return!1}return!0}function yi(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Ei=(e,t,n)=>e??t??n,Td=ce({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const r=Pe(ko),o=j(()=>e.route||r.value),s=Pe(gi,0),i=j(()=>{let c=re(s);const{matched:u}=o.value;let f;for(;(f=u[c])&&!f.components;)c++;return c}),l=j(()=>o.value.matched[i.value]);Vt(gi,j(()=>i.value+1)),Vt(_d,l),Vt(ko,o);const a=ge();return Qe(()=>[a.value,l.value,e.name],([c,u,f],[d,m,y])=>{u&&(u.instances[f]=c,m&&m!==u&&c&&c===d&&(u.leaveGuards.size||(u.leaveGuards=m.leaveGuards),u.updateGuards.size||(u.updateGuards=m.updateGuards))),c&&u&&(!m||!En(u,m)||!d)&&(u.enterCallbacks[f]||[]).forEach(T=>T(c))},{flush:"post"}),()=>{const c=o.value,u=e.name,f=l.value,d=f&&f.components[u];if(!d)return wi(n.default,{Component:d,route:c});const m=f.props[u],y=m?m===!0?c.params:typeof m=="function"?m(c):m:null,A=ne(d,_e({},y,t,{onVnodeUnmounted:P=>{P.component.isUnmounted&&(f.instances[u]=null)},ref:a}));return wi(n.default,{Component:A,route:c})||A}}});function wi(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const ra=Td;function Ld(e){const t=Zf(e.routes,e),n=e.parseQuery||md,r=e.stringifyQuery||_i,o=e.history,s=On(),i=On(),l=On(),a=Cn(Tt);let c=Tt;cn&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=ao.bind(null,C=>""+C),f=ao.bind(null,pd),d=ao.bind(null,Mr);function m(C,W){let N,Q;return Yl(C)?(N=t.getRecordMatcher(C),Q=W):Q=C,t.addRoute(Q,N)}function y(C){const W=t.getRecordMatcher(C);W&&t.removeRoute(W)}function T(){return t.getRoutes().map(C=>C.record)}function A(C){return!!t.getRecordMatcher(C)}function P(C,W){if(W=_e({},W||a.value),typeof C=="string"){const v=co(n,C,W.path),w=t.resolve({path:v.path},W),x=o.createHref(v.fullPath);return _e(v,w,{params:d(w.params),hash:Mr(v.hash),redirectedFrom:void 0,href:x})}let N;if("path"in C)N=_e({},C,{path:co(n,C.path,W.path).path});else{const v=_e({},C.params);for(const w in v)v[w]==null&&delete v[w];N=_e({},C,{params:f(v)}),W.params=f(W.params)}const Q=t.resolve(N,W),ue=C.hash||"";Q.params=u(d(Q.params));const h=xf(r,_e({},C,{hash:fd(ue),path:Q.path})),p=o.createHref(h);return _e({fullPath:h,hash:ue,query:r===_i?vd(C.query):C.query||{}},Q,{redirectedFrom:void 0,href:p})}function R(C){return typeof C=="string"?co(n,C,a.value.path):_e({},C)}function g(C,W){if(c!==C)return wn(8,{from:W,to:C})}function E(C){return H(C)}function z(C){return E(_e(R(C),{replace:!0}))}function Y(C){const W=C.matched[C.matched.length-1];if(W&&W.redirect){const{redirect:N}=W;let Q=typeof N=="function"?N(C):N;return typeof Q=="string"&&(Q=Q.includes("?")||Q.includes("#")?Q=R(Q):{path:Q},Q.params={}),_e({query:C.query,hash:C.hash,params:"path"in Q?{}:C.params},Q)}}function H(C,W){const N=c=P(C),Q=a.value,ue=C.state,h=C.force,p=C.replace===!0,v=Y(N);if(v)return H(_e(R(v),{state:typeof v=="object"?_e({},ue,v.state):ue,force:h,replace:p}),W||N);const w=N;w.redirectedFrom=W;let x;return!h&&Pf(r,Q,N)&&(x=wn(16,{to:w,from:Q}),Be(Q,Q,!0,!1)),(x?Promise.resolve(x):I(w,Q)).catch(O=>Et(O)?Et(O,2)?O:Me(O):q(O,w,Q)).then(O=>{if(O){if(Et(O,2))return H(_e({replace:p},R(O.to),{state:typeof O.to=="object"?_e({},ue,O.to.state):ue,force:h}),W||w)}else O=L(w,Q,!0,p,ue);return B(w,Q,O),O})}function b(C,W){const N=g(C,W);return N?Promise.reject(N):Promise.resolve()}function S(C){const W=lt.values().next().value;return W&&typeof W.runWithContext=="function"?W.runWithContext(C):C()}function I(C,W){let N;const[Q,ue,h]=Cd(C,W);N=uo(Q.reverse(),"beforeRouteLeave",C,W);for(const v of Q)v.leaveGuards.forEach(w=>{N.push(Mt(w,C,W))});const p=b.bind(null,C,W);return N.push(p),Re(N).then(()=>{N=[];for(const v of s.list())N.push(Mt(v,C,W));return N.push(p),Re(N)}).then(()=>{N=uo(ue,"beforeRouteUpdate",C,W);for(const v of ue)v.updateGuards.forEach(w=>{N.push(Mt(w,C,W))});return N.push(p),Re(N)}).then(()=>{N=[];for(const v of h)if(v.beforeEnter)if(ht(v.beforeEnter))for(const w of v.beforeEnter)N.push(Mt(w,C,W));else N.push(Mt(v.beforeEnter,C,W));return N.push(p),Re(N)}).then(()=>(C.matched.forEach(v=>v.enterCallbacks={}),N=uo(h,"beforeRouteEnter",C,W),N.push(p),Re(N))).then(()=>{N=[];for(const v of i.list())N.push(Mt(v,C,W));return N.push(p),Re(N)}).catch(v=>Et(v,8)?v:Promise.reject(v))}function B(C,W,N){l.list().forEach(Q=>S(()=>Q(C,W,N)))}function L(C,W,N,Q,ue){const h=g(C,W);if(h)return h;const p=W===Tt,v=cn?history.state:{};N&&(Q||p?o.replace(C.fullPath,_e({scroll:p&&v&&v.scroll},ue)):o.push(C.fullPath,ue)),a.value=C,Be(C,W,N,p),Me()}let M;function oe(){M||(M=o.listen((C,W,N)=>{if(!je.listening)return;const Q=P(C),ue=Y(Q);if(ue){H(_e(ue,{replace:!0}),Q).catch(Hn);return}c=Q;const h=a.value;cn&&$f(ci(h.fullPath,N.delta),Jr()),I(Q,h).catch(p=>Et(p,12)?p:Et(p,2)?(H(p.to,Q).then(v=>{Et(v,20)&&!N.delta&&N.type===qn.pop&&o.go(-1,!1)}).catch(Hn),Promise.reject()):(N.delta&&o.go(-N.delta,!1),q(p,Q,h))).then(p=>{p=p||L(Q,h,!1),p&&(N.delta&&!Et(p,8)?o.go(-N.delta,!1):N.type===qn.pop&&Et(p,20)&&o.go(-1,!1)),B(Q,h,p)}).catch(Hn)}))}let ie=On(),k=On(),J;function q(C,W,N){Me(C);const Q=k.list();return Q.length?Q.forEach(ue=>ue(C,W,N)):console.error(C),Promise.reject(C)}function ye(){return J&&a.value!==Tt?Promise.resolve():new Promise((C,W)=>{ie.add([C,W])})}function Me(C){return J||(J=!C,oe(),ie.list().forEach(([W,N])=>C?N(C):W()),ie.reset()),C}function Be(C,W,N,Q){const{scrollBehavior:ue}=e;if(!cn||!ue)return Promise.resolve();const h=!N&&Nf(ci(C.fullPath,0))||(Q||!N)&&history.state&&history.state.scroll||null;return er().then(()=>ue(C,W,h)).then(p=>p&&Mf(p)).catch(p=>q(p,C,W))}const ke=C=>o.go(C);let Ue;const lt=new Set,je={currentRoute:a,listening:!0,addRoute:m,removeRoute:y,hasRoute:A,getRoutes:T,resolve:P,options:e,push:E,replace:z,go:ke,back:()=>ke(-1),forward:()=>ke(1),beforeEach:s.add,beforeResolve:i.add,afterEach:l.add,onError:k.add,isReady:ye,install(C){const W=this;C.component("RouterLink",yd),C.component("RouterView",ra),C.config.globalProperties.$router=W,Object.defineProperty(C.config.globalProperties,"$route",{enumerable:!0,get:()=>re(a)}),cn&&!Ue&&a.value===Tt&&(Ue=!0,E(o.location).catch(ue=>{}));const N={};for(const ue in Tt)Object.defineProperty(N,ue,{get:()=>a.value[ue],enumerable:!0});C.provide(Qr,W),C.provide(as,tl(N)),C.provide(ko,a);const Q=C.unmount;lt.add(C),C.unmount=function(){lt.delete(C),lt.size<1&&(c=Tt,M&&M(),M=null,a.value=Tt,Ue=!1,J=!1),Q()}}};function Re(C){return C.reduce((W,N)=>W.then(()=>S(N)),Promise.resolve())}return je}function Cd(e,t){const n=[],r=[],o=[],s=Math.max(t.matched.length,e.matched.length);for(let i=0;iEn(c,l))?r.push(l):n.push(l));const a=e.matched[i];a&&(t.matched.find(c=>En(c,a))||o.push(a))}return[n,r,o]}function xn(){return Pe(Qr)}function rn(){return Pe(as)}const Ad=({headerLinkSelector:e,headerAnchorSelector:t,delay:n,offset:r=5})=>{const o=xn(),i=Kl(()=>{var T,A;const l=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(l-0)d.some(R=>R.hash===P.hash));for(let P=0;P=(((T=R.parentElement)==null?void 0:T.offsetTop)??0)-r,z=!g||l<(((A=g.parentElement)==null?void 0:A.offsetTop)??0)-r;if(!(E&&z))continue;const H=decodeURIComponent(o.currentRoute.value.hash),b=decodeURIComponent(R.hash);if(H===b)return;if(f){for(let S=P+1;S{window.addEventListener("scroll",i)}),Kr(()=>{window.removeEventListener("scroll",i)})},Ti=async(e,t)=>{const{scrollBehavior:n}=e.options;e.options.scrollBehavior=void 0,await e.replace({query:e.currentRoute.value.query,hash:t}).finally(()=>e.options.scrollBehavior=n)},xd="a.sidebar-item",Pd=".header-anchor",Rd=300,Id=5,Od=it({setup(){Ad({headerLinkSelector:xd,headerAnchorSelector:Pd,delay:Rd,offset:Id})}}),Li=()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,kd=()=>window.scrollTo({top:0,behavior:"smooth"}),Sd=ce({name:"BackToTop",setup(){const e=ge(0),t=j(()=>e.value>300),n=Kl(()=>{e.value=Li()},100);De(()=>{e.value=Li(),window.addEventListener("scroll",()=>n())});const r=ne("div",{class:"back-to-top",onClick:kd});return()=>ne(An,{name:"back-to-top"},()=>t.value?r:null)}}),Dd=it({rootComponents:[Sd]}),Md=ne("svg",{class:"external-link-icon",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"},[ne("path",{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}),ne("polygon",{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"})]),$d=ce({name:"ExternalLinkIcon",props:{locales:{type:Object,required:!1,default:()=>({})}},setup(e){const t=or(),n=j(()=>e.locales[t.value]??{openInNewWindow:"open in new window"});return()=>ne("span",[Md,ne("span",{class:"external-link-icon-sr-only"},n.value.openInNewWindow)])}});var Nd={"/":{openInNewWindow:"open in new window"},"/en/":{openInNewWindow:"open in new window"}};const Vd=Nd,Hd=it({enhance({app:e}){e.component("ExternalLinkIcon",ne($d,{locales:Vd}))}});/*! medium-zoom 1.1.0 | MIT License | https://github.com/francoischalifour/medium-zoom */var Gt=Object.assign||function(e){for(var t=1;t1&&arguments[1]!==void 0?arguments[1]:{},r=window.Promise||function(L){function M(){}L(M,M)},o=function(L){var M=L.target;if(M===S){y();return}g.indexOf(M)!==-1&&T({target:M})},s=function(){if(!(z||!b.original)){var L=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(Y-L)>H.scrollOffset&&setTimeout(y,150)}},i=function(L){var M=L.key||L.keyCode;(M==="Escape"||M==="Esc"||M===27)&&y()},l=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=L;if(L.background&&(S.style.background=L.background),L.container&&L.container instanceof Object&&(M.container=Gt({},H.container,L.container)),L.template){var oe=Tr(L.template)?L.template:document.querySelector(L.template);M.template=oe}return H=Gt({},H,M),g.forEach(function(ie){ie.dispatchEvent(ln("medium-zoom:update",{detail:{zoom:I}}))}),I},a=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return e(Gt({},H,L))},c=function(){for(var L=arguments.length,M=Array(L),oe=0;oe0?M.reduce(function(k,J){return[].concat(k,Ai(J))},[]):g;return ie.forEach(function(k){k.classList.remove("medium-zoom-image"),k.dispatchEvent(ln("medium-zoom:detach",{detail:{zoom:I}}))}),g=g.filter(function(k){return ie.indexOf(k)===-1}),I},f=function(L,M){var oe=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return g.forEach(function(ie){ie.addEventListener("medium-zoom:"+L,M,oe)}),E.push({type:"medium-zoom:"+L,listener:M,options:oe}),I},d=function(L,M){var oe=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return g.forEach(function(ie){ie.removeEventListener("medium-zoom:"+L,M,oe)}),E=E.filter(function(ie){return!(ie.type==="medium-zoom:"+L&&ie.listener.toString()===M.toString())}),I},m=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=L.target,oe=function(){var k={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},J=void 0,q=void 0;if(H.container)if(H.container instanceof Object)k=Gt({},k,H.container),J=k.width-k.left-k.right-H.margin*2,q=k.height-k.top-k.bottom-H.margin*2;else{var ye=Tr(H.container)?H.container:document.querySelector(H.container),Me=ye.getBoundingClientRect(),Be=Me.width,ke=Me.height,Ue=Me.left,lt=Me.top;k=Gt({},k,{width:Be,height:ke,left:Ue,top:lt})}J=J||k.width-H.margin*2,q=q||k.height-H.margin*2;var je=b.zoomedHd||b.original,Re=Ci(je)?J:je.naturalWidth||J,C=Ci(je)?q:je.naturalHeight||q,W=je.getBoundingClientRect(),N=W.top,Q=W.left,ue=W.width,h=W.height,p=Math.min(Math.max(ue,Re),J)/ue,v=Math.min(Math.max(h,C),q)/h,w=Math.min(p,v),x=(-Q+(J-ue)/2+H.margin+k.left)/w,O=(-N+(q-h)/2+H.margin+k.top)/w,U="scale("+w+") translate3d("+x+"px, "+O+"px, 0)";b.zoomed.style.transform=U,b.zoomedHd&&(b.zoomedHd.style.transform=U)};return new r(function(ie){if(M&&g.indexOf(M)===-1){ie(I);return}var k=function Be(){z=!1,b.zoomed.removeEventListener("transitionend",Be),b.original.dispatchEvent(ln("medium-zoom:opened",{detail:{zoom:I}})),ie(I)};if(b.zoomed){ie(I);return}if(M)b.original=M;else if(g.length>0){var J=g;b.original=J[0]}else{ie(I);return}if(b.original.dispatchEvent(ln("medium-zoom:open",{detail:{zoom:I}})),Y=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,z=!0,b.zoomed=Bd(b.original),document.body.appendChild(S),H.template){var q=Tr(H.template)?H.template:document.querySelector(H.template);b.template=document.createElement("div"),b.template.appendChild(q.content.cloneNode(!0)),document.body.appendChild(b.template)}if(b.original.parentElement&&b.original.parentElement.tagName==="PICTURE"&&b.original.currentSrc&&(b.zoomed.src=b.original.currentSrc),document.body.appendChild(b.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),b.original.classList.add("medium-zoom-image--hidden"),b.zoomed.classList.add("medium-zoom-image--opened"),b.zoomed.addEventListener("click",y),b.zoomed.addEventListener("transitionend",k),b.original.getAttribute("data-zoom-src")){b.zoomedHd=b.zoomed.cloneNode(),b.zoomedHd.removeAttribute("srcset"),b.zoomedHd.removeAttribute("sizes"),b.zoomedHd.removeAttribute("loading"),b.zoomedHd.src=b.zoomed.getAttribute("data-zoom-src"),b.zoomedHd.onerror=function(){clearInterval(ye),console.warn("Unable to reach the zoom image target "+b.zoomedHd.src),b.zoomedHd=null,oe()};var ye=setInterval(function(){b.zoomedHd.complete&&(clearInterval(ye),b.zoomedHd.classList.add("medium-zoom-image--opened"),b.zoomedHd.addEventListener("click",y),document.body.appendChild(b.zoomedHd),oe())},10)}else if(b.original.hasAttribute("srcset")){b.zoomedHd=b.zoomed.cloneNode(),b.zoomedHd.removeAttribute("sizes"),b.zoomedHd.removeAttribute("loading");var Me=b.zoomedHd.addEventListener("load",function(){b.zoomedHd.removeEventListener("load",Me),b.zoomedHd.classList.add("medium-zoom-image--opened"),b.zoomedHd.addEventListener("click",y),document.body.appendChild(b.zoomedHd),oe()})}else oe()})},y=function(){return new r(function(L){if(z||!b.original){L(I);return}var M=function oe(){b.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(b.zoomed),b.zoomedHd&&document.body.removeChild(b.zoomedHd),document.body.removeChild(S),b.zoomed.classList.remove("medium-zoom-image--opened"),b.template&&document.body.removeChild(b.template),z=!1,b.zoomed.removeEventListener("transitionend",oe),b.original.dispatchEvent(ln("medium-zoom:closed",{detail:{zoom:I}})),b.original=null,b.zoomed=null,b.zoomedHd=null,b.template=null,L(I)};z=!0,document.body.classList.remove("medium-zoom--opened"),b.zoomed.style.transform="",b.zoomedHd&&(b.zoomedHd.style.transform=""),b.template&&(b.template.style.transition="opacity 150ms",b.template.style.opacity=0),b.original.dispatchEvent(ln("medium-zoom:close",{detail:{zoom:I}})),b.zoomed.addEventListener("transitionend",M)})},T=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=L.target;return b.original?y():m({target:M})},A=function(){return H},P=function(){return g},R=function(){return b.original},g=[],E=[],z=!1,Y=0,H=n,b={original:null,zoomed:null,zoomedHd:null,template:null};Object.prototype.toString.call(t)==="[object Object]"?H=t:(t||typeof t=="string")&&c(t),H=Gt({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},H);var S=zd(H.background);document.addEventListener("click",o),document.addEventListener("keyup",i),document.addEventListener("scroll",s),window.addEventListener("resize",y);var I={open:m,close:y,toggle:T,update:l,clone:a,attach:c,detach:u,on:f,off:d,getOptions:A,getImages:P,getZoomedImage:R};return I};function Wd(e,t){t===void 0&&(t={});var n=t.insertAt;if(!(!e||typeof document>"u")){var r=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css",n==="top"&&r.firstChild?r.insertBefore(o,r.firstChild):r.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}var Ud=".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";Wd(Ud);const Kd=jd,qd=Symbol("mediumZoom");var Gd={};const Yd=".theme-default-content > img, .theme-default-content :not(a) > img",Jd=Gd,Qd=300,Zd=it({enhance({app:e,router:t}){const n=Kd(Jd);n.refresh=(r=Yd)=>{n.detach(),n.attach(r)},e.provide(qd,n),t.afterEach(()=>{setTimeout(()=>n.refresh(),Qd)})}});/** + * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT + */const de={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},status:null,set:e=>{const t=de.isStarted();e=fo(e,de.settings.minimum,1),de.status=e===1?null:e;const n=de.render(!t),r=n.querySelector(de.settings.barSelector),o=de.settings.speed,s=de.settings.easing;return n.offsetWidth,Xd(i=>{vr(r,{transform:"translate3d("+xi(e)+"%,0,0)",transition:"all "+o+"ms "+s}),e===1?(vr(n,{transition:"none",opacity:"1"}),n.offsetWidth,setTimeout(function(){vr(n,{transition:"all "+o+"ms linear",opacity:"0"}),setTimeout(function(){de.remove(),i()},o)},o)):setTimeout(()=>i(),o)}),de},isStarted:()=>typeof de.status=="number",start:()=>{de.status||de.set(0);const e=()=>{setTimeout(()=>{de.status&&(de.trickle(),e())},de.settings.trickleSpeed)};return de.settings.trickle&&e(),de},done:e=>!e&&!de.status?de:de.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=de.status;return t?(typeof e!="number"&&(e=(1-t)*fo(Math.random()*t,.1,.95)),t=fo(t+e,0,.994),de.set(t)):de.start()},trickle:()=>de.inc(Math.random()*de.settings.trickleRate),render:e=>{if(de.isRendered())return document.getElementById("nprogress");Pi(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=de.settings.template;const n=t.querySelector(de.settings.barSelector),r=e?"-100":xi(de.status||0),o=document.querySelector(de.settings.parent);return vr(n,{transition:"all 0 linear",transform:"translate3d("+r+"%,0,0)"}),o!==document.body&&Pi(o,"nprogress-custom-parent"),o==null||o.appendChild(t),t},remove:()=>{Ri(document.documentElement,"nprogress-busy"),Ri(document.querySelector(de.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&eh(e)},isRendered:()=>!!document.getElementById("nprogress")},fo=(e,t,n)=>en?n:e,xi=e=>(-1+e)*100,Xd=function(){const e=[];function t(){const n=e.shift();n&&n(t)}return function(n){e.push(n),e.length===1&&t()}}(),vr=function(){const e=["Webkit","O","Moz","ms"],t={};function n(i){return i.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(l,a){return a.toUpperCase()})}function r(i){const l=document.body.style;if(i in l)return i;let a=e.length;const c=i.charAt(0).toUpperCase()+i.slice(1);let u;for(;a--;)if(u=e[a]+c,u in l)return u;return i}function o(i){return i=n(i),t[i]??(t[i]=r(i))}function s(i,l,a){l=o(l),i.style[l]=a}return function(i,l){for(const a in l){const c=l[a];c!==void 0&&Object.prototype.hasOwnProperty.call(l,a)&&s(i,a,c)}}}(),oa=(e,t)=>(typeof e=="string"?e:cs(e)).indexOf(" "+t+" ")>=0,Pi=(e,t)=>{const n=cs(e),r=n+t;oa(n,t)||(e.className=r.substring(1))},Ri=(e,t)=>{const n=cs(e);if(!oa(e,t))return;const r=n.replace(" "+t+" "," ");e.className=r.substring(1,r.length-1)},cs=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),eh=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},th=()=>{De(()=>{const e=xn(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(n=>{t.has(n.path)||de.start()}),e.afterEach(n=>{t.add(n.path),de.done()})})},nh=it({setup(){th()}}),rh=JSON.parse(`{"logo":"/images/icon_microcitynotes.png","locales":{"/":{"selectLanguageName":"简体中文","navbar":[{"text":"首页","link":"/"},{"text":"笔记","link":"/notes/"},{"text":"文档","children":[{"text":"Desktop版文档","link":"/docs/","children":[{"text":"1.MicroCity介绍","link":"/docs/1.1_what_microcity_can_do"},{"text":"2.开始使用MicroCity","link":"/docs/2.1_showing_a_world_map"},{"text":"3.用户界面","link":"/docs/3.1_ui_overview"},{"text":"4.脚本编写","link":"/docs/4.1_si_overview"}]}]},{"text":"MicroCity项目仓库","children":[{"text":"github","children":[{"text":"MicroCity Desktop","link":"https://github.com/microcity/Desktop"},{"text":"MicroCity Web","link":"https://github.com/microcity/microcity.github.io"}]},{"text":"gitee","children":[{"text":"MicroCity Web","link":"https://gitee.com/microcity/microcity"},{"text":"MicroCity Desktop","link":"https://gitee.com/microcity/desktop"}]}]},{"text":"MicroCity Web","link":"https://microcity.gitee.io/"}],"sidebar":{"/":[{"text":"MicroCity文档","link":"/docs/","collapsible":true},{"text":"笔记","link":"/notes/","collapsible":true}],"/docs/":[{"text":"MicroCity文档","children":[{"text":"目录","link":"/docs/","children":[]},{"text":"1.MicroCity介绍","collapsible":true,"children":["/docs/1.1_what_microcity_can_do"]},{"text":"2.开始使用MicroCity","collapsible":true,"children":["/docs/2.1_showing_a_world_map","/docs/2.2_searching_for_countries"]},{"text":"3.用户界面","collapsible":true,"children":["/docs/3.1_ui_overview","/docs/3.2_vector_shapes","/docs/3.3_raster_grids","/docs/3.4_3d_scenes","/docs/3.5_tables","/docs/3.6_maps_and_layers","/docs/3.7_modules"]},{"text":"4.脚本编写","collapsible":true,"children":["/docs/4.1_si_overview","/docs/4.2_ui_control","/docs/4.3_shapes_and_tables","/docs/4.4_grids","/docs/4.5_3d_scenes","/docs/4.6_networks","/docs/4.7_des_simulations","/docs/4.8_mixed_integer_programming"]}]}],"/notes/":[{"text":"目录","link":"/notes/","children":[]},{"text":"通用知识","collapsible":true,"children":["/notes/lua","/notes/versions","/notes/timelapse","/notes/oop"]},{"text":"MicroCity","collapsible":true,"children":["/notes/visualization","/notes/network","/notes/lp"]},{"text":"MicroCityWeb","collapsible":true,"children":["/notes/web-ui","/notes/3d-scene","/notes/3d-objects","/notes/event-scheduling","/notes/mip","/notes/debug"]},{"text":"思路","collapsible":true,"children":["/notes/warehouse-simulation","/notes/plots","/notes/cy-simulation"]}]}},"/en/":{"selectLanguageName":"English","navbar":[{"text":"Home","link":"/en/"},{"text":"Notes","link":"/en/notes/"},{"text":"Documentation","children":[{"text":"Desktop Documentation","link":"/en/docs/","children":[{"text":"1. MicroCity Introduction","link":"/en/docs/1.1_what_microcity_can_do"},{"text":"2. Getting Started with MicroCity","link":"/en/docs/2.1_showing_a_world_map"},{"text":"3. User Interface","link":"/en/docs/3.1_ui_overview"},{"text":"4. Script Writing","link":"/en/docs/4.1_si_overview"}]}]},{"text":"MicroCity Repositories","children":[{"text":"GitHub","children":[{"text":"MicroCity Desktop","link":"https://github.com/microcity/Desktop"},{"text":"MicroCity Web","link":"https://github.com/microcity/microcity.github.io"}]},{"text":"Gitee","children":[{"text":"MicroCity Web","link":"https://gitee.com/microcity/microcity"},{"text":"MicroCity Desktop","link":"https://gitee.com/microcity/desktop"}]}]},{"text":"MicroCity Web","link":"https://microcity.gitee.io/"}],"sidebar":{"/":[{"text":"MicroCity Documentation","link":"/en/docs/","collapsible":true},{"text":"Notes","link":"/en/notes/","collapsible":true}],"/en/docs/":[{"text":"MicroCity Documentation","children":[{"text":"Table of Contents","link":"/en/docs/","children":[]},{"text":"1. MicroCity Introduction","collapsible":true,"children":["/en/docs/1.1_what_microcity_can_do"]},{"text":"2. Getting Started with MicroCity","collapsible":true,"children":["/en/docs/2.1_showing_a_world_map","/en/docs/2.2_searching_for_countries"]},{"text":"3. User Interface","collapsible":true,"children":["/en/docs/3.1_ui_overview","/en/docs/3.2_vector_shapes","/en/docs/3.3_raster_grids","/en/docs/3.4_3d_scenes","/en/docs/3.5_tables","/en/docs/3.6_maps_and_layers","/en/docs/3.7_modules"]},{"text":"4. Script Writing","collapsible":true,"children":["/en/docs/4.1_si_overview","/en/docs/4.2_ui_control","/en/docs/4.3_shapes_and_tables","/en/docs/4.4_grids","/en/docs/4.5_3d_scenes","/en/docs/4.6_networks","/en/docs/4.7_des_simulations","/en/docs/4.8_mixed_integer_programming"]}]}],"/en/notes/":[{"text":"Table of Contents","link":"/en/notes/","children":[]},{"text":"General Knowledge","collapsible":true,"children":["/en/notes/lua","/en/notes/versions","/en/notes/timelapse","/en/notes/oop"]},{"text":"MicroCity","collapsible":true,"children":["/en/notes/visualization","/en/notes/network","/en/notes/lp"]},{"text":"MicroCityWeb","collapsible":true,"children":["/en/notes/web-ui","/en/notes/3d-scene","/en/notes/3d-objects","/en/notes/event-scheduling","/en/notes/mip","/en/notes/debug"]},{"text":"Concepts","collapsible":true,"children":["/en/notes/warehouse-simulation","/en/notes/plots","/en/notes/cy-simulation"]}]}}},"colorMode":"auto","colorModeSwitch":true,"navbar":[],"repo":null,"selectLanguageText":"Languages","selectLanguageAriaLabel":"Select language","sidebar":"auto","sidebarDepth":2,"editLink":true,"editLinkText":"Edit this page","lastUpdated":true,"lastUpdatedText":"Last Updated","contributors":true,"contributorsText":"Contributors","notFound":["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],"backToHome":"Take me home","openInNewWindow":"open in new window","toggleColorMode":"toggle color mode","toggleSidebar":"toggle sidebar"}`),oh=ge(rh),sa=()=>oh,ia=Symbol(""),sh=()=>{const e=Pe(ia);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},ih=(e,t)=>{const{locales:n,...r}=e;return{...r,...n==null?void 0:n[t]}},lh=it({enhance({app:e}){const t=sa(),n=e._context.provides[os],r=j(()=>ih(t.value,n.value));e.provide(ia,r),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return r.value}}})}}),ah=ce({__name:"Badge",props:{type:{type:String,required:!1,default:"tip"},text:{type:String,required:!1,default:""},vertical:{type:String,required:!1,default:void 0}},setup(e){return(t,n)=>(K(),te("span",{class:Je(["badge",e.type]),style:Jn({verticalAlign:e.vertical})},[we(t.$slots,"default",{},()=>[jt(Ne(e.text),1)])],6))}}),xe=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},ch=xe(ah,[["__file","Badge.vue"]]);function Ii(e,t){var n;const r=Cn();return hl(()=>{r.value=e()},{...t,flush:(n=t==null?void 0:t.flush)!=null?n:"sync"}),Zn(r)}function uh(e,t){let n,r,o;const s=ge(!0),i=()=>{s.value=!0,o()};Qe(e,i,{flush:"sync"});const l=typeof t=="function"?t:t.get,a=typeof t=="function"?void 0:t.set,c=gc((u,f)=>(r=u,o=f,{get(){return s.value&&(n=l(),s.value=!1),r(),n},set(d){a==null||a(d)}}));return Object.isExtensible(c)&&(c.trigger=i),c}function la(e){return Wi()?(qa(e),!0):!1}function Wt(e){return typeof e=="function"?e():re(e)}const fh=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const dh=Object.prototype.toString,hh=e=>dh.call(e)==="[object Object]",So=()=>{};function aa(e,t){function n(...r){return new Promise((o,s)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(o).catch(s)})}return n}const ca=e=>e();function ph(e,t={}){let n,r,o=So;const s=l=>{clearTimeout(l),o(),o=So};return l=>{const a=Wt(e),c=Wt(t.maxWait);return n&&s(n),a<=0||c!==void 0&&c<=0?(r&&(s(r),r=null),Promise.resolve(l())):new Promise((u,f)=>{o=t.rejectOnCancel?f:u,c&&!r&&(r=setTimeout(()=>{n&&s(n),r=null,u(l())},c)),n=setTimeout(()=>{r&&s(r),r=null,u(l())},a)})}}function mh(e=ca){const t=ge(!0);function n(){t.value=!1}function r(){t.value=!0}const o=(...s)=>{t.value&&e(...s)};return{isActive:Zn(t),pause:n,resume:r,eventFilter:o}}function vh(e,t=200,n={}){return aa(ph(t,n),e)}function _h(e,t,n={}){const{eventFilter:r=ca,...o}=n;return Qe(e,aa(r,t),o)}function gh(e,t,n={}){const{eventFilter:r,...o}=n,{eventFilter:s,pause:i,resume:l,isActive:a}=mh(r);return{stop:_h(e,t,{...o,eventFilter:s}),pause:i,resume:l,isActive:a}}function bh(e,t=!0){es()?De(e):t?e():er(e)}function yh(e=!1,t={}){const{truthyValue:n=!0,falsyValue:r=!1}=t,o=Fe(e),s=ge(e);function i(l){if(arguments.length)return s.value=l,s.value;{const a=Wt(n);return s.value=s.value===a?Wt(r):a,s.value}}return o?i:[s,i]}function Eh(e){var t;const n=Wt(e);return(t=n==null?void 0:n.$el)!=null?t:n}const $r=fh?window:void 0;function Nr(...e){let t,n,r,o;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,o]=e,t=$r):[t,n,r,o]=e,!t)return So;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const s=[],i=()=>{s.forEach(u=>u()),s.length=0},l=(u,f,d,m)=>(u.addEventListener(f,d,m),()=>u.removeEventListener(f,d,m)),a=Qe(()=>[Eh(t),Wt(o)],([u,f])=>{if(i(),!u)return;const d=hh(f)?{...f}:f;s.push(...n.flatMap(m=>r.map(y=>l(u,m,y,d))))},{immediate:!0,flush:"post"}),c=()=>{a(),i()};return la(c),c}function wh(){const e=ge(!1);return es()&&De(()=>{e.value=!0}),e}function Th(e){const t=wh();return j(()=>(t.value,!!e()))}function Lh(e,t={}){const{window:n=$r}=t,r=Th(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let o;const s=ge(!1),i=c=>{s.value=c.matches},l=()=>{o&&("removeEventListener"in o?o.removeEventListener("change",i):o.removeListener(i))},a=hl(()=>{r.value&&(l(),o=n.matchMedia(Wt(e)),"addEventListener"in o?o.addEventListener("change",i):o.addListener(i),s.value=o.matches)});return la(()=>{a(),l(),o=void 0}),s}const _r=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},gr="__vueuse_ssr_handlers__",Ch=Ah();function Ah(){return gr in _r||(_r[gr]=_r[gr]||{}),_r[gr]}function xh(e,t){return Ch[e]||t}function Ph(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Rh={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Oi="vueuse-storage";function us(e,t,n,r={}){var o;const{flush:s="pre",deep:i=!0,listenToStorageChanges:l=!0,writeDefaults:a=!0,mergeDefaults:c=!1,shallow:u,window:f=$r,eventFilter:d,onError:m=S=>{console.error(S)},initOnMounted:y}=r,T=(u?Cn:ge)(typeof t=="function"?t():t);if(!n)try{n=xh("getDefaultStorage",()=>{var S;return(S=$r)==null?void 0:S.localStorage})()}catch(S){m(S)}if(!n)return T;const A=Wt(t),P=Ph(A),R=(o=r.serializer)!=null?o:Rh[P],{pause:g,resume:E}=gh(T,()=>z(T.value),{flush:s,deep:i,eventFilter:d});return f&&l&&bh(()=>{Nr(f,"storage",b),Nr(f,Oi,H),y&&b()}),y||b(),T;function z(S){try{if(S==null)n.removeItem(e);else{const I=R.write(S),B=n.getItem(e);B!==I&&(n.setItem(e,I),f&&f.dispatchEvent(new CustomEvent(Oi,{detail:{key:e,oldValue:B,newValue:I,storageArea:n}})))}}catch(I){m(I)}}function Y(S){const I=S?S.newValue:n.getItem(e);if(I==null)return a&&A!==null&&n.setItem(e,R.write(A)),A;if(!S&&c){const B=R.read(I);return typeof c=="function"?c(B,A):P==="object"&&!Array.isArray(B)?{...A,...B}:B}else return typeof I!="string"?I:R.read(I)}function H(S){b(S.detail)}function b(S){if(!(S&&S.storageArea!==n)){if(S&&S.key==null){T.value=A;return}if(!(S&&S.key!==e)){g();try{(S==null?void 0:S.newValue)!==R.write(T.value)&&(T.value=Y(S))}catch(I){m(I)}finally{S?er(E):E()}}}}}function Ih(e){return Lh("(prefers-color-scheme: dark)",e)}const Oh=ce({name:"CodeGroup",slots:Object,setup(e,{slots:t}){const n=ge([]),r=ge(-1),o=us("vuepress-code-group",{}),s=j(()=>n.value.map(c=>c.innerText).join(","));De(()=>{Qe(()=>o.value[s.value],(c=-1)=>{r.value!==c&&(r.value=c)},{immediate:!0}),Qe(r,c=>{o.value[s.value]!==c&&(o.value[s.value]=c)})});const i=(c=r.value)=>{c{c>0?r.value=c-1:r.value=n.value.length-1,n.value[r.value].focus()},a=(c,u)=>{c.key===" "||c.key==="Enter"?(c.preventDefault(),r.value=u):c.key==="ArrowRight"?(c.preventDefault(),i(u)):c.key==="ArrowLeft"&&(c.preventDefault(),l(u))};return()=>{var u;const c=(((u=t.default)==null?void 0:u.call(t))||[]).filter(f=>f.type.name==="CodeGroupItem").map(f=>(f.props===null&&(f.props={}),f));return c.length===0?null:(r.value<0||r.value>c.length-1?(r.value=c.findIndex(f=>f.props.active===""||f.props.active===!0),r.value===-1&&(r.value=0)):c.forEach((f,d)=>{f.props.active=d===r.value}),ne("div",{class:"code-group"},[ne("div",{class:"code-group__nav"},ne("ul",{class:"code-group__ul"},c.map((f,d)=>{const m=d===r.value;return ne("li",{class:"code-group__li"},ne("button",{ref:y=>{y&&(n.value[d]=y)},class:{"code-group__nav-tab":!0,"code-group__nav-tab-active":m},ariaPressed:m,ariaExpanded:m,onClick:()=>r.value=d,onKeydown:y=>a(y,d)},f.props.title))}))),c]))}}}),kh=["aria-selected"],Sh=ce({name:"CodeGroupItem"}),Dh=ce({...Sh,props:{title:{type:String,required:!0},active:{type:Boolean,required:!1,default:!1}},setup(e){return(t,n)=>(K(),te("div",{class:Je(["code-group-item",{"code-group-item__active":e.active}]),"aria-selected":e.active},[we(t.$slots,"default")],10,kh))}}),Mh=xe(Dh,[["__file","CodeGroupItem.vue"]]),$h=()=>sa(),Ge=()=>sh(),ua=Symbol(""),fs=()=>{const e=Pe(ua);if(!e)throw new Error("useDarkMode() is called without provider.");return e},Nh=()=>{const e=Ge(),t=Ih(),n=us("vuepress-color-scheme",e.value.colorMode),r=j({get(){return e.value.colorModeSwitch?n.value==="auto"?t.value:n.value==="dark":e.value.colorMode==="dark"},set(o){o===t.value?n.value="auto":n.value=o?"dark":"light"}});Vt(ua,r),Vh(r)},Vh=e=>{const t=(n=e.value)=>{const r=window==null?void 0:window.document.querySelector("html");r==null||r.classList.toggle("dark",n)};De(()=>{Qe(e,t,{immediate:!0})}),nr(()=>t())},fa=(...e)=>{const n=xn().resolve(...e),r=n.matched[n.matched.length-1];if(!(r!=null&&r.redirect))return n;const{redirect:o}=r,s=ae(o)?o(n):o,i=ve(s)?{path:s}:s;return fa({hash:n.hash,query:n.query,params:n.params,...i})},ds=e=>{const t=fa(encodeURI(e));return{text:t.meta.title||e,link:t.name==="404"?e:t.fullPath}};let ho=null,kn=null;const Hh={wait:()=>ho,pending:()=>{ho=new Promise(e=>kn=e)},resolve:()=>{kn==null||kn(),ho=null,kn=null}},da=()=>Hh,ha=Symbol("sidebarItems"),hs=()=>{const e=Pe(ha);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},Fh=()=>{const e=Ge(),t=gt(),n=j(()=>zh(t.value,e.value));Vt(ha,n)},zh=(e,t)=>{const n=e.sidebar??t.sidebar??"auto",r=e.sidebarDepth??t.sidebarDepth??2;return e.home||n===!1?[]:n==="auto"?jh(r):Z(n)?pa(n,r):rs(n)?Wh(n,r):[]},Bh=(e,t)=>({text:e.title,link:e.link,children:ps(e.children,t)}),ps=(e,t)=>t>0?e.map(n=>Bh(n,t-1)):[],jh=e=>{const t=Ht();return[{text:t.value.title,children:ps(t.value.headers,e)}]},pa=(e,t)=>{const n=rn(),r=Ht(),o=s=>{var l;let i;if(ve(s)?i=ds(s):i=s,i.children)return{...i,children:i.children.map(a=>o(a))};if(i.link===n.path){const a=((l=r.value.headers[0])==null?void 0:l.level)===1?r.value.headers[0].children:r.value.headers;return{...i,children:ps(a,t)}}return i};return e.map(s=>o(s))},Wh=(e,t)=>{const n=rn(),r=$l(e,n.path),o=e[r]??[];return pa(o,t)},Uh="719px",Kh={mobile:Uh};var Gn;(function(e){e.MOBILE="mobile"})(Gn||(Gn={}));var Ni;const qh={[Gn.MOBILE]:Number.parseInt((Ni=Kh.mobile)==null?void 0:Ni.replace("px",""),10)},ma=(e,t)=>{const n=qh[e];Number.isInteger(n)&&De(()=>{t(n),window.addEventListener("resize",()=>t(n),!1),window.addEventListener("orientationchange",()=>t(n),!1)})},Gh={},Yh={class:"theme-default-content"};function Jh(e,t){const n=yt("Content");return K(),te("div",Yh,[se(n)])}const Qh=xe(Gh,[["render",Jh],["__file","HomeContent.vue"]]),Zh={key:0,class:"features"},Xh=ce({__name:"HomeFeatures",setup(e){const t=gt(),n=j(()=>Z(t.value.features)?t.value.features:[]);return(r,o)=>n.value.length?(K(),te("div",Zh,[(K(!0),te(Te,null,zt(n.value,s=>(K(),te("div",{key:s.title,class:"feature"},[pe("h2",null,Ne(s.title),1),pe("p",null,Ne(s.details),1)]))),128))])):Ie("v-if",!0)}}),ep=xe(Xh,[["__file","HomeFeatures.vue"]]),tp=["innerHTML"],np=["textContent"],rp=ce({__name:"HomeFooter",setup(e){const t=gt(),n=j(()=>t.value.footer),r=j(()=>t.value.footerHtml);return(o,s)=>n.value?(K(),te(Te,{key:0},[Ie(" eslint-disable-next-line vue/no-v-html "),r.value?(K(),te("div",{key:0,class:"footer",innerHTML:n.value},null,8,tp)):(K(),te("div",{key:1,class:"footer",textContent:Ne(n.value)},null,8,np))],64)):Ie("v-if",!0)}}),op=xe(rp,[["__file","HomeFooter.vue"]]),sp=["href","rel","target","aria-label"],ip=ce({inheritAttrs:!1}),lp=ce({...ip,__name:"AutoLink",props:{item:{type:Object,required:!0}},setup(e){const t=e,n=rn(),r=Wl(),{item:o}=Go(t),s=j(()=>rr(o.value.link)),i=j(()=>!s.value&&hf(o.value.link)),l=j(()=>{if(!i.value){if(o.value.target)return o.value.target;if(s.value)return"_blank"}}),a=j(()=>l.value==="_blank"),c=j(()=>!s.value&&!i.value&&!a.value),u=j(()=>{if(!i.value){if(o.value.rel)return o.value.rel;if(a.value)return"noopener noreferrer"}}),f=j(()=>o.value.ariaLabel||o.value.text),d=j(()=>{const T=Object.keys(r.value.locales);return T.length?!T.some(A=>A===o.value.link):o.value.link!=="/"}),m=j(()=>d.value?n.path.startsWith(o.value.link):!1),y=j(()=>c.value?o.value.activeMatch?new RegExp(o.value.activeMatch).test(n.path):m.value:!1);return(T,A)=>{const P=yt("RouterLink"),R=yt("AutoLinkExternalIcon");return c.value?(K(),Oe(P,Po({key:0,class:{"router-link-active":y.value},to:re(o).link,"aria-label":f.value},T.$attrs),{default:He(()=>[we(T.$slots,"before"),jt(" "+Ne(re(o).text)+" ",1),we(T.$slots,"after")]),_:3},16,["class","to","aria-label"])):(K(),te("a",Po({key:1,class:"external-link",href:re(o).link,rel:u.value,target:l.value,"aria-label":f.value},T.$attrs),[we(T.$slots,"before"),jt(" "+Ne(re(o).text)+" ",1),a.value?(K(),Oe(R,{key:0})):Ie("v-if",!0),we(T.$slots,"after")],16,sp))}}}),At=xe(lp,[["__file","AutoLink.vue"]]),ap={class:"hero"},cp={key:0,id:"main-title"},up={key:1,class:"description"},fp={key:2,class:"actions"},dp=ce({__name:"HomeHero",setup(e){const t=gt(),n=ss(),r=fs(),o=j(()=>r.value&&t.value.heroImageDark!==void 0?t.value.heroImageDark:t.value.heroImage),s=j(()=>t.value.heroAlt||l.value||"hero"),i=j(()=>t.value.heroHeight||280),l=j(()=>t.value.heroText===null?null:t.value.heroText||n.value.title||"Hello"),a=j(()=>t.value.tagline===null?null:t.value.tagline||n.value.description||"Welcome to your VuePress site"),c=j(()=>Z(t.value.actions)?t.value.actions.map(({text:f,link:d,type:m="primary"})=>({text:f,link:d,type:m})):[]),u=()=>{if(!o.value)return null;const f=ne("img",{src:Yr(o.value),alt:s.value,height:i.value});return t.value.heroImageDark===void 0?f:ne(is,()=>f)};return(f,d)=>(K(),te("header",ap,[se(u),l.value?(K(),te("h1",cp,Ne(l.value),1)):Ie("v-if",!0),a.value?(K(),te("p",up,Ne(a.value),1)):Ie("v-if",!0),c.value.length?(K(),te("p",fp,[(K(!0),te(Te,null,zt(c.value,m=>(K(),Oe(At,{key:m.text,class:Je(["action-button",[m.type]]),item:m},null,8,["class","item"]))),128))])):Ie("v-if",!0)]))}}),hp=xe(dp,[["__file","HomeHero.vue"]]),pp={class:"home"},mp=ce({__name:"Home",setup(e){return(t,n)=>(K(),te("main",pp,[se(hp),se(ep),se(Qh),se(op)]))}}),vp=xe(mp,[["__file","Home.vue"]]),_p=ce({__name:"NavbarBrand",setup(e){const t=or(),n=ss(),r=Ge(),o=fs(),s=j(()=>r.value.home||t.value),i=j(()=>n.value.title),l=j(()=>o.value&&r.value.logoDark!==void 0?r.value.logoDark:r.value.logo),a=()=>{if(!l.value)return null;const c=ne("img",{class:"logo",src:Yr(l.value),alt:i.value});return r.value.logoDark===void 0?c:ne(is,()=>c)};return(c,u)=>{const f=yt("RouterLink");return K(),Oe(f,{to:s.value},{default:He(()=>[se(a),i.value?(K(),te("span",{key:0,class:Je(["site-name",{"can-hide":l.value}])},Ne(i.value),3)):Ie("v-if",!0)]),_:1},8,["to"])}}}),gp=xe(_p,[["__file","NavbarBrand.vue"]]),bp=ce({__name:"DropdownTransition",setup(e){const t=r=>{r.style.height=r.scrollHeight+"px"},n=r=>{r.style.height=""};return(r,o)=>(K(),Oe(An,{name:"dropdown",onEnter:t,onAfterEnter:n,onBeforeLeave:t},{default:He(()=>[we(r.$slots,"default")]),_:3}))}}),va=xe(bp,[["__file","DropdownTransition.vue"]]),yp=["aria-label"],Ep={class:"title"},wp=pe("span",{class:"arrow down"},null,-1),Tp=["aria-label"],Lp={class:"title"},Cp={class:"navbar-dropdown"},Ap={class:"navbar-dropdown-subtitle"},xp={key:1},Pp={class:"navbar-dropdown-subitem-wrapper"},Rp=ce({__name:"NavbarDropdown",props:{item:{type:Object,required:!0}},setup(e){const t=e,{item:n}=Go(t),r=j(()=>n.value.ariaLabel||n.value.text),o=ge(!1),s=rn();Qe(()=>s.path,()=>{o.value=!1});const i=a=>{a.detail===0?o.value=!o.value:o.value=!1},l=(a,c)=>c[c.length-1]===a;return(a,c)=>(K(),te("div",{class:Je(["navbar-dropdown-wrapper",{open:o.value}])},[pe("button",{class:"navbar-dropdown-title",type:"button","aria-label":r.value,onClick:i},[pe("span",Ep,Ne(re(n).text),1),wp],8,yp),pe("button",{class:"navbar-dropdown-title-mobile",type:"button","aria-label":r.value,onClick:c[0]||(c[0]=u=>o.value=!o.value)},[pe("span",Lp,Ne(re(n).text),1),pe("span",{class:Je(["arrow",o.value?"down":"right"])},null,2)],8,Tp),se(va,null,{default:He(()=>[Rr(pe("ul",Cp,[(K(!0),te(Te,null,zt(re(n).children,u=>(K(),te("li",{key:u.text,class:"navbar-dropdown-item"},[u.children?(K(),te(Te,{key:0},[pe("h4",Ap,[u.link?(K(),Oe(At,{key:0,item:u,onFocusout:f=>l(u,re(n).children)&&u.children.length===0&&(o.value=!1)},null,8,["item","onFocusout"])):(K(),te("span",xp,Ne(u.text),1))]),pe("ul",Pp,[(K(!0),te(Te,null,zt(u.children,f=>(K(),te("li",{key:f.link,class:"navbar-dropdown-subitem"},[se(At,{item:f,onFocusout:d=>l(f,u.children)&&l(u,re(n).children)&&(o.value=!1)},null,8,["item","onFocusout"])]))),128))])],64)):(K(),Oe(At,{key:1,item:u,onFocusout:f=>l(u,re(n).children)&&(o.value=!1)},null,8,["item","onFocusout"]))]))),128))],512),[[Dr,o.value]])]),_:1})],2))}}),Ip=xe(Rp,[["__file","NavbarDropdown.vue"]]),ki=e=>decodeURI(e).replace(/#.*$/,"").replace(/(index)?\.(md|html)$/,""),Op=(e,t)=>{if(t.hash===e)return!0;const n=ki(t.path),r=ki(e);return n===r},_a=(e,t)=>e.link&&Op(e.link,t)?!0:e.children?e.children.some(n=>_a(n,t)):!1,ga=e=>!rr(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,kp={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},Sp=({docsRepo:e,editLinkPattern:t})=>{if(t)return t;const n=ga(e);return n!==null?kp[n]:null},Dp=({docsRepo:e,docsBranch:t,docsDir:n,filePathRelative:r,editLinkPattern:o})=>{if(!r)return null;const s=Sp({docsRepo:e,editLinkPattern:o});return s?s.replace(/:repo/,rr(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,Ml(`${Dl(n)}/${r}`)):null},Mp={key:0,class:"navbar-items"},$p=ce({__name:"NavbarItems",setup(e){const t=()=>{const u=xn(),f=or(),d=Wl(),m=ss(),y=$h(),T=Ge();return j(()=>{const A=Object.keys(d.value.locales);if(A.length<2)return[];const P=u.currentRoute.value.path,R=u.currentRoute.value.fullPath;return[{text:`${T.value.selectLanguageText}`,ariaLabel:`${T.value.selectLanguageAriaLabel??T.value.selectLanguageText}`,children:A.map(E=>{var I,B;const z=((I=d.value.locales)==null?void 0:I[E])??{},Y=((B=y.value.locales)==null?void 0:B[E])??{},H=`${z.lang}`,b=Y.selectLanguageName??H;let S;if(H===m.value.lang)S=R;else{const L=P.replace(f.value,E);u.getRoutes().some(M=>M.path===L)?S=R.replace(P,L):S=Y.home??E}return{text:b,link:S}})}]})},n=()=>{const u=Ge(),f=j(()=>u.value.repo),d=j(()=>f.value?ga(f.value):null),m=j(()=>f.value&&!rr(f.value)?`https://github.com/${f.value}`:f.value),y=j(()=>m.value?u.value.repoLabel?u.value.repoLabel:d.value===null?"Source":d.value:null);return j(()=>!m.value||!y.value?[]:[{text:y.value,link:m.value}])},r=u=>ve(u)?ds(u):u.children?{...u,children:u.children.map(r)}:u,o=()=>{const u=Ge();return j(()=>(u.value.navbar||[]).map(r))},s=ge(!1),i=o(),l=t(),a=n(),c=j(()=>[...i.value,...l.value,...a.value]);return ma(Gn.MOBILE,u=>{window.innerWidthc.value.length?(K(),te("nav",Mp,[(K(!0),te(Te,null,zt(c.value,d=>(K(),te("div",{key:d.text,class:"navbar-item"},[d.children?(K(),Oe(Ip,{key:0,item:d,class:Je(s.value?"mobile":"")},null,8,["item","class"])):(K(),Oe(At,{key:1,item:d},null,8,["item"]))]))),128))])):Ie("v-if",!0)}}),ba=xe($p,[["__file","NavbarItems.vue"]]),Np=["title"],Vp={class:"icon",focusable:"false",viewBox:"0 0 32 32"},Hp=_u('',9),Fp=[Hp],zp={class:"icon",focusable:"false",viewBox:"0 0 32 32"},Bp=pe("path",{d:"M13.502 5.414a15.075 15.075 0 0 0 11.594 18.194a11.113 11.113 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1.002 1.002 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.072 13.072 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3z",fill:"currentColor"},null,-1),jp=[Bp],Wp=ce({__name:"ToggleColorModeButton",setup(e){const t=Ge(),n=fs(),r=()=>{n.value=!n.value};return(o,s)=>(K(),te("button",{class:"toggle-color-mode-button",title:re(t).toggleColorMode,onClick:r},[Rr((K(),te("svg",Vp,Fp,512)),[[Dr,!re(n)]]),Rr((K(),te("svg",zp,jp,512)),[[Dr,re(n)]])],8,Np))}}),Up=xe(Wp,[["__file","ToggleColorModeButton.vue"]]),Kp=["title"],qp=pe("div",{class:"icon","aria-hidden":"true"},[pe("span"),pe("span"),pe("span")],-1),Gp=[qp],Yp=ce({__name:"ToggleSidebarButton",emits:["toggle"],setup(e){const t=Ge();return(n,r)=>(K(),te("div",{class:"toggle-sidebar-button",title:re(t).toggleSidebar,"aria-expanded":"false",role:"button",tabindex:"0",onClick:r[0]||(r[0]=o=>n.$emit("toggle"))},Gp,8,Kp))}}),Jp=xe(Yp,[["__file","ToggleSidebarButton.vue"]]),Qp=ce({__name:"Navbar",emits:["toggle-sidebar"],setup(e){const t=Ge(),n=ge(null),r=ge(null),o=ge(0),s=j(()=>o.value?{maxWidth:o.value+"px"}:{});ma(Gn.MOBILE,l=>{var c;const a=i(n.value,"paddingLeft")+i(n.value,"paddingRight");window.innerWidth{const c=yt("NavbarSearch");return K(),te("header",{ref_key:"navbar",ref:n,class:"navbar"},[se(Jp,{onToggle:a[0]||(a[0]=u=>l.$emit("toggle-sidebar"))}),pe("span",{ref_key:"navbarBrand",ref:r},[se(gp)],512),pe("div",{class:"navbar-items-wrapper",style:Jn(s.value)},[we(l.$slots,"before"),se(ba,{class:"can-hide"}),we(l.$slots,"after"),re(t).colorModeSwitch?(K(),Oe(Up,{key:0})):Ie("v-if",!0),se(c)],4)],512)}}}),Zp=xe(Qp,[["__file","Navbar.vue"]]),Xp={class:"page-meta"},em={key:0,class:"meta-item edit-link"},tm={key:1,class:"meta-item last-updated"},nm={class:"meta-item-label"},rm={class:"meta-item-info"},om={key:2,class:"meta-item contributors"},sm={class:"meta-item-label"},im={class:"meta-item-info"},lm=["title"],am=ce({__name:"PageMeta",setup(e){const t=()=>{const a=Ge(),c=Ht(),u=gt();return j(()=>{if(!(u.value.editLink??a.value.editLink??!0))return null;const{repo:d,docsRepo:m=d,docsBranch:y="main",docsDir:T="",editLinkText:A}=a.value;if(!m)return null;const P=Dp({docsRepo:m,docsBranch:y,docsDir:T,filePathRelative:c.value.filePathRelative,editLinkPattern:u.value.editLinkPattern??a.value.editLinkPattern});return P?{text:A??"Edit this page",link:P}:null})},n=()=>{const a=Ge(),c=Ht(),u=gt();return j(()=>{var m,y;return!(u.value.lastUpdated??a.value.lastUpdated??!0)||!((m=c.value.git)!=null&&m.updatedTime)?null:new Date((y=c.value.git)==null?void 0:y.updatedTime).toLocaleString()})},r=()=>{const a=Ge(),c=Ht(),u=gt();return j(()=>{var d;return u.value.contributors??a.value.contributors??!0?((d=c.value.git)==null?void 0:d.contributors)??null:null})},o=Ge(),s=t(),i=n(),l=r();return(a,c)=>{const u=yt("ClientOnly");return K(),te("footer",Xp,[re(s)?(K(),te("div",em,[se(At,{class:"meta-item-label",item:re(s)},null,8,["item"])])):Ie("v-if",!0),re(i)?(K(),te("div",tm,[pe("span",nm,Ne(re(o).lastUpdatedText)+": ",1),se(u,null,{default:He(()=>[pe("span",rm,Ne(re(i)),1)]),_:1})])):Ie("v-if",!0),re(l)&&re(l).length?(K(),te("div",om,[pe("span",sm,Ne(re(o).contributorsText)+": ",1),pe("span",im,[(K(!0),te(Te,null,zt(re(l),(f,d)=>(K(),te(Te,{key:d},[pe("span",{class:"contributor",title:`email: ${f.email}`},Ne(f.name),9,lm),d!==re(l).length-1?(K(),te(Te,{key:0},[jt(", ")],64)):Ie("v-if",!0)],64))),128))])])):Ie("v-if",!0)])}}}),cm=xe(am,[["__file","PageMeta.vue"]]),um={key:0,class:"page-nav"},fm={class:"inner"},dm={key:0,class:"prev"},hm={key:1,class:"next"},pm=ce({__name:"PageNav",setup(e){const t=a=>a===!1?null:ve(a)?ds(a):rs(a)?a:!1,n=(a,c,u)=>{const f=a.findIndex(d=>d.link===c);if(f!==-1){const d=a[f+u];return d!=null&&d.link?d:null}for(const d of a)if(d.children){const m=n(d.children,c,u);if(m)return m}return null},r=gt(),o=hs(),s=rn(),i=j(()=>{const a=t(r.value.prev);return a!==!1?a:n(o.value,s.path,-1)}),l=j(()=>{const a=t(r.value.next);return a!==!1?a:n(o.value,s.path,1)});return(a,c)=>i.value||l.value?(K(),te("nav",um,[pe("p",fm,[i.value?(K(),te("span",dm,[se(At,{item:i.value},null,8,["item"])])):Ie("v-if",!0),l.value?(K(),te("span",hm,[se(At,{item:l.value},null,8,["item"])])):Ie("v-if",!0)])])):Ie("v-if",!0)}}),mm=xe(pm,[["__file","PageNav.vue"]]),vm={class:"page"},_m={class:"theme-default-content"},gm=ce({__name:"Page",setup(e){return(t,n)=>{const r=yt("Content");return K(),te("main",vm,[we(t.$slots,"top"),pe("div",_m,[we(t.$slots,"content-top"),se(r),we(t.$slots,"content-bottom")]),se(cm),se(mm),we(t.$slots,"bottom")])}}}),bm=xe(gm,[["__file","Page.vue"]]),ym=["onKeydown"],Em={class:"sidebar-item-children"},wm=ce({__name:"SidebarItem",props:{item:{type:Object,required:!0},depth:{type:Number,required:!1,default:0}},setup(e){const t=e,{item:n,depth:r}=Go(t),o=rn(),s=xn(),i=j(()=>_a(n.value,o)),l=j(()=>({"sidebar-item":!0,"sidebar-heading":r.value===0,active:i.value,collapsible:n.value.collapsible})),a=j(()=>n.value.collapsible?i.value:!0),[c,u]=yh(a.value),f=m=>{n.value.collapsible&&(m.preventDefault(),u())},d=s.afterEach(m=>{er(()=>{c.value=a.value})});return Kr(()=>{d()}),(m,y)=>{var A;const T=yt("SidebarItem",!0);return K(),te("li",null,[re(n).link?(K(),Oe(At,{key:0,class:Je(l.value),item:re(n)},null,8,["class","item"])):(K(),te("p",{key:1,tabindex:"0",class:Je(l.value),onClick:f,onKeydown:tf(f,["enter"])},[jt(Ne(re(n).text)+" ",1),re(n).collapsible?(K(),te("span",{key:0,class:Je(["arrow",re(c)?"down":"right"])},null,2)):Ie("v-if",!0)],42,ym)),(A=re(n).children)!=null&&A.length?(K(),Oe(va,{key:2},{default:He(()=>[Rr(pe("ul",Em,[(K(!0),te(Te,null,zt(re(n).children,P=>(K(),Oe(T,{key:`${re(r)}${P.text}${P.link}`,item:P,depth:re(r)+1},null,8,["item","depth"]))),128))],512),[[Dr,re(c)]])]),_:1})):Ie("v-if",!0)])}}}),Tm=xe(wm,[["__file","SidebarItem.vue"]]),Lm={key:0,class:"sidebar-items"},Cm=ce({__name:"SidebarItems",setup(e){const t=rn(),n=hs();return De(()=>{Qe(()=>t.hash,r=>{const o=document.querySelector(".sidebar");if(!o)return;const s=document.querySelector(`.sidebar a.sidebar-item[href="${t.path}${r}"]`);if(!s)return;const{top:i,height:l}=o.getBoundingClientRect(),{top:a,height:c}=s.getBoundingClientRect();ai+l&&s.scrollIntoView(!1)})}),(r,o)=>re(n).length?(K(),te("ul",Lm,[(K(!0),te(Te,null,zt(re(n),s=>(K(),Oe(Tm,{key:`${s.text}${s.link}`,item:s},null,8,["item"]))),128))])):Ie("v-if",!0)}}),Am=xe(Cm,[["__file","SidebarItems.vue"]]),xm={class:"sidebar"},Pm=ce({__name:"Sidebar",setup(e){return(t,n)=>(K(),te("aside",xm,[se(ba),we(t.$slots,"top"),se(Am),we(t.$slots,"bottom")]))}}),Rm=xe(Pm,[["__file","Sidebar.vue"]]),Im=ce({__name:"Layout",setup(e){const t=Ht(),n=gt(),r=Ge(),o=j(()=>n.value.navbar!==!1&&r.value.navbar!==!1),s=hs(),i=ge(!1),l=A=>{i.value=typeof A=="boolean"?A:!i.value},a={x:0,y:0},c=A=>{a.x=A.changedTouches[0].clientX,a.y=A.changedTouches[0].clientY},u=A=>{const P=A.changedTouches[0].clientX-a.x,R=A.changedTouches[0].clientY-a.y;Math.abs(P)>Math.abs(R)&&Math.abs(P)>40&&(P>0&&a.x<=80?l(!0):l(!1))},f=j(()=>[{"no-navbar":!o.value,"no-sidebar":!s.value.length,"sidebar-open":i.value},n.value.pageClass]);let d;De(()=>{d=xn().afterEach(()=>{l(!1)})}),nr(()=>{d()});const m=da(),y=m.resolve,T=m.pending;return(A,P)=>(K(),te("div",{class:Je(["theme-container",f.value]),onTouchstart:c,onTouchend:u},[we(A.$slots,"navbar",{},()=>[o.value?(K(),Oe(Zp,{key:0,onToggleSidebar:l},{before:He(()=>[we(A.$slots,"navbar-before")]),after:He(()=>[we(A.$slots,"navbar-after")]),_:3})):Ie("v-if",!0)]),pe("div",{class:"sidebar-mask",onClick:P[0]||(P[0]=R=>l(!1))}),we(A.$slots,"sidebar",{},()=>[se(Rm,null,{top:He(()=>[we(A.$slots,"sidebar-top")]),bottom:He(()=>[we(A.$slots,"sidebar-bottom")]),_:3})]),we(A.$slots,"page",{},()=>[re(n).home?(K(),Oe(vp,{key:0})):(K(),Oe(An,{key:1,name:"fade-slide-y",mode:"out-in",onBeforeEnter:re(y),onBeforeLeave:re(T)},{default:He(()=>[(K(),Oe(bm,{key:re(t).path},{top:He(()=>[we(A.$slots,"page-top")]),"content-top":He(()=>[we(A.$slots,"page-content-top")]),"content-bottom":He(()=>[we(A.$slots,"page-content-bottom")]),bottom:He(()=>[we(A.$slots,"page-bottom")]),_:3}))]),_:3},8,["onBeforeEnter","onBeforeLeave"]))])],34))}}),ya=xe(Im,[["__file","Layout.vue"]]),Om={class:"theme-container"},km={class:"page"},Sm={class:"theme-default-content"},Dm=pe("h1",null,"404",-1),Mm=ce({__name:"NotFound",setup(e){const t=or(),n=Ge(),r=n.value.notFound??["Not Found"],o=()=>r[Math.floor(Math.random()*r.length)],s=n.value.home??t.value,i=n.value.backToHome??"Back to home";return(l,a)=>{const c=yt("RouterLink");return K(),te("div",Om,[pe("main",km,[pe("div",Sm,[Dm,pe("blockquote",null,Ne(o()),1),se(c,{to:re(s)},{default:He(()=>[jt(Ne(re(i)),1)]),_:1},8,["to"])])])])}}}),$m=xe(Mm,[["__file","NotFound.vue"]]),Nm=it({enhance({app:e,router:t}){e.component("Badge",ch),e.component("CodeGroup",Oh),e.component("CodeGroupItem",Mh),e.component("AutoLinkExternalIcon",()=>{const r=e.component("ExternalLinkIcon");return r?ne(r):null}),e.component("NavbarSearch",()=>{const r=e.component("Docsearch")||e.component("SearchBox");return r?ne(r):null});const n=t.options.scrollBehavior;t.options.scrollBehavior=async(...r)=>(await da().wait(),n(...r))},setup(){Nh(),Fh()},layouts:{Layout:ya,NotFound:$m}});var Vm=it({enhance({app:e}){const t=V(()=>_(()=>import("./SearchBox-dgLZwYTI.js"),__vite__mapDeps([])));e.component("SearchBox",t)}});const Hm={},br=us("VUEPRESS_CODE_TAB_STORE",{});var Fm=ce({name:"CodeTabs",props:{active:{type:Number,default:0},data:{type:Array,required:!0},id:{type:String,required:!0},tabId:{type:String,default:""}},slots:Object,setup(e,{slots:t}){const n=ge(e.active),r=Cn([]),o=()=>{e.tabId&&(br.value[e.tabId]=e.data[n.value].id)},s=(c=n.value)=>{n.value=c{n.value=c>0?c-1:r.value.length-1,r.value[n.value].focus()},l=(c,u)=>{c.key===" "||c.key==="Enter"?(c.preventDefault(),n.value=u):c.key==="ArrowRight"?(c.preventDefault(),s()):c.key==="ArrowLeft"&&(c.preventDefault(),i()),e.tabId&&(br.value[e.tabId]=e.data[n.value].id)},a=()=>{if(e.tabId){const c=e.data.findIndex(({id:u})=>br.value[e.tabId]===u);if(c!==-1)return c}return e.active};return De(()=>{n.value=a(),Qe(()=>br.value[e.tabId],(c,u)=>{if(e.tabId&&c!==u){const f=e.data.findIndex(({id:d})=>d===c);f!==-1&&(n.value=f)}})}),()=>e.data.length?ne("div",{class:"vp-code-tabs"},[ne("div",{class:"vp-code-tabs-nav",role:"tablist"},e.data.map(({id:c},u)=>{const f=u===n.value;return ne("button",{type:"button",ref:d=>{d&&(r.value[u]=d)},class:["vp-code-tab-nav",{active:f}],role:"tab","aria-controls":`codetab-${e.id}-${u}`,"aria-selected":f,onClick:()=>{n.value=u,o()},onKeydown:d=>l(d,u)},t[`title${u}`]({value:c,isActive:f}))})),e.data.map(({id:c},u)=>{const f=u===n.value;return ne("div",{class:["vp-code-tab",{active:f}],id:`codetab-${e.id}-${u}`,role:"tabpanel","aria-expanded":f},[ne("div",{class:"vp-code-tab-title"},t[`title${u}`]({value:c,isActive:f})),t[`tab${u}`]({value:c,isActive:f})])})]):null}});const zm=()=>{Nr("beforeprint",()=>{document.querySelectorAll("details").forEach(e=>{e.open=!0})})};var qe=Uint8Array,fn=Uint16Array,Bm=Int32Array,Ea=new qe([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),wa=new qe([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),jm=new qe([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ta=function(e,t){for(var n=new fn(31),r=0;r<31;++r)n[r]=t+=1<>1|(Ce&21845)<<1;kt=(kt&52428)>>2|(kt&13107)<<2,kt=(kt&61680)>>4|(kt&3855)<<4,Do[Ce]=((kt&65280)>>8|(kt&255)<<8)>>1}var zn=function(e,t,n){for(var r=e.length,o=0,s=new fn(t);o>a]=c}else for(l=new fn(r),o=0;o>15-e[o]);return l},sr=new qe(288);for(var Ce=0;Ce<144;++Ce)sr[Ce]=8;for(var Ce=144;Ce<256;++Ce)sr[Ce]=9;for(var Ce=256;Ce<280;++Ce)sr[Ce]=7;for(var Ce=280;Ce<288;++Ce)sr[Ce]=8;var Aa=new qe(32);for(var Ce=0;Ce<32;++Ce)Aa[Ce]=5;var qm=zn(sr,9,1),Gm=zn(Aa,5,1),po=function(e){for(var t=e[0],n=1;nt&&(t=e[n]);return t},ct=function(e,t,n){var r=t/8|0;return(e[r]|e[r+1]<<8)>>(t&7)&n},mo=function(e,t){var n=t/8|0;return(e[n]|e[n+1]<<8|e[n+2]<<16)>>(t&7)},Ym=function(e){return(e+7)/8|0},ms=function(e,t,n){return(t==null||t<0)&&(t=0),(n==null||n>e.length)&&(n=e.length),new qe(e.subarray(t,n))},Jm=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],ot=function(e,t,n){var r=new Error(t||Jm[e]);if(r.code=e,Error.captureStackTrace&&Error.captureStackTrace(r,ot),!n)throw r;return r},Qm=function(e,t,n,r){var o=e.length,s=r?r.length:0;if(!o||t.f&&!t.l)return n||new qe(0);var i=!n,l=i||t.i!=2,a=t.i;i&&(n=new qe(o*3));var c=function(ue){var h=n.length;if(ue>h){var p=new qe(Math.max(h*2,ue));p.set(n),n=p}},u=t.f||0,f=t.p||0,d=t.b||0,m=t.l,y=t.d,T=t.m,A=t.n,P=o*8;do{if(!m){u=ct(e,f,1);var R=ct(e,f+1,3);if(f+=3,R)if(R==1)m=qm,y=Gm,T=9,A=5;else if(R==2){var Y=ct(e,f,31)+257,H=ct(e,f+10,15)+4,b=Y+ct(e,f+5,31)+1;f+=14;for(var S=new qe(b),I=new qe(19),B=0;B>4;if(g<16)S[B++]=g;else{var k=0,J=0;for(g==16?(J=3+ct(e,f,3),f+=2,k=S[B-1]):g==17?(J=3+ct(e,f,7),f+=3):g==18&&(J=11+ct(e,f,127),f+=7);J--;)S[B++]=k}}var q=S.subarray(0,Y),ye=S.subarray(Y);T=po(q),A=po(ye),m=zn(q,T,1),y=zn(ye,A,1)}else ot(1);else{var g=Ym(f)+4,E=e[g-4]|e[g-3]<<8,z=g+E;if(z>o){a&&ot(0);break}l&&c(d+E),n.set(e.subarray(g,z),d),t.b=d+=E,t.p=f=z*8,t.f=u;continue}if(f>P){a&&ot(0);break}}l&&c(d+131072);for(var Me=(1<>4;if(f+=k&15,f>P){a&&ot(0);break}if(k||ot(2),Ue<256)n[d++]=Ue;else if(Ue==256){ke=f,m=null;break}else{var lt=Ue-254;if(Ue>264){var B=Ue-257,je=Ea[B];lt=ct(e,f,(1<>4;Re||ot(3),f+=Re&15;var ye=Km[C];if(C>3){var je=wa[C];ye+=mo(e,f)&(1<P){a&&ot(0);break}l&&c(d+131072);var W=d+lt;if(d>4>7||(e[0]<<8|e[1])%31)&&ot(6,"invalid zlib data"),(e[1]>>5&1)==+!t&&ot(6,"invalid zlib data: "+(e[1]&32?"need":"unexpected")+" dictionary"),(e[1]>>3&4)+2};function ev(e,t){return Qm(e.subarray(Xm(e,t&&t.dictionary),-4),{i:2},t&&t.out,t&&t.dictionary)}var Si=typeof TextEncoder<"u"&&new TextEncoder,Mo=typeof TextDecoder<"u"&&new TextDecoder,tv=0;try{Mo.decode(Zm,{stream:!0}),tv=1}catch{}var nv=function(e){for(var t="",n=0;;){var r=e[n++],o=(r>127)+(r>223)+(r>239);if(n+o>e.length)return{s:t,r:ms(e,n-1)};o?o==3?(r=((r&15)<<18|(e[n++]&63)<<12|(e[n++]&63)<<6|e[n++]&63)-65536,t+=String.fromCharCode(55296|r>>10,56320|r&1023)):o&1?t+=String.fromCharCode((r&31)<<6|e[n++]&63):t+=String.fromCharCode((r&15)<<12|(e[n++]&63)<<6|e[n++]&63):t+=String.fromCharCode(r)}};function rv(e,t){if(t){for(var n=new qe(e.length),r=0;r>1)),i=0,l=function(u){s[i++]=u},r=0;rs.length){var a=new qe(i+8+(o-r<<1));a.set(s),s=a}var c=e.charCodeAt(r);c<128||t?l(c):c<2048?(l(192|c>>6),l(128|c&63)):c>55295&&c<57344?(c=65536+(c&1047552)|e.charCodeAt(++r)&1023,l(240|c>>18),l(128|c>>12&63),l(128|c>>6&63),l(128|c&63)):(l(224|c>>12),l(128|c>>6&63),l(128|c&63))}return ms(s,0,i)}function ov(e,t){if(t){for(var n="",r=0;r{var r;return ne("svg",{xmlns:"http://www.w3.org/2000/svg",class:["icon",`${e}-icon`],viewBox:"0 0 1024 1024",fill:t,"aria-label":`${e} icon`},(r=n.default)==null?void 0:r.call(n))};xa.displayName="IconBase";const vs=({size:e=48,stroke:t=4,wrapper:n=!0,height:r=2*e})=>{const o=ne("svg",{xmlns:"http://www.w3.org/2000/svg",width:e,height:e,preserveAspectRatio:"xMidYMid",viewBox:"25 25 50 50"},[ne("animateTransform",{attributeName:"transform",type:"rotate",dur:"2s",keyTimes:"0;1",repeatCount:"indefinite",values:"0;360"}),ne("circle",{cx:"50",cy:"50",r:"20",fill:"none",stroke:"currentColor","stroke-width":t,"stroke-linecap":"round"},[ne("animate",{attributeName:"stroke-dasharray",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"1,200;90,200;1,200"}),ne("animate",{attributeName:"stroke-dashoffset",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"0;-35px;-125px"})])]);return n?ne("div",{class:"loading-icon-wrapper",style:`display:flex;align-items:center;justify-content:center;height:${r}px`},o):o};vs.displayName="LoadingIcon";const sv=e=>{const t=atob(e);return ov(ev(rv(t,!0)))},iv=e=>{const t=or();return j(()=>e[t.value])};var _s={x:0,y:0,"line-width":2,"line-length":40,"text-margin":8,"font-size":14,"font-color":"#8DA1AC","line-color":"#8DA1AC","element-color":"black",fill:"white","yes-text":"Yes","no-text":"No","arrow-end":"block",scale:1},lv={..._s,symbols:{start:{class:"start-element","font-color":"#fff",fill:"#595959","line-width":"0px"},end:{class:"end-element","font-color":"#fff",fill:"#595959","line-width":"0px"},operation:{class:"operation-element","font-color":"#fff",fill:"#1890ff","line-width":"0px"},inputoutput:{class:"inputoutput-element","font-color":"#fff",fill:"#1890ff","line-width":"0px"},subroutine:{class:"subroutine-element","font-color":"#fff",fill:"#FF485E","element-color":"#fff","line-color":"red"},condition:{class:"condition-element","font-color":"#fff",fill:"#FF485E","line-width":"0px"},parallel:{class:"parallel-element","font-color":"#fff",fill:"#1890ff","line-width":"0px"}}},av={..._s,"line-width":1,symbols:{start:{class:"start-element",fill:"#ccc","line-color":"#5c6ac4","font-color":"#000"},end:{class:"end-element",fill:"#ccc","line-color":"#5c6ac4","font-color":"#000"},operation:{class:"operation-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},inputoutput:{class:"inputoutput-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},subroutine:{class:"subroutine-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},condition:{class:"condition-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"},parallel:{class:"parallel-element",fill:"#f1f1f1","line-color":"#5c6ac4","font-color":"#000"}}},cv={..._s,symbols:{start:{class:"start-element","font-color":"#fff",fill:"#2F495F","line-width":"0px"},end:{class:"end-element","font-color":"#fff",fill:"#2F495F","line-width":"0px"},operation:{class:"operation-element","font-color":"#fff",fill:"#00BC7D","line-width":"0px"},inputoutput:{class:"inputoutput-element","font-color":"#fff",fill:"#EB4D5D","line-width":"0px"},subroutine:{class:"subroutine-element","font-color":"#fff",fill:"#937AC4","element-color":"#fff","line-color":"red"},condition:{class:"condition-element","font-color":"#fff",fill:"#FFB500","line-width":"0px"},parallel:{class:"parallel-element","font-color":"#fff",fill:"#2F495F","line-width":"0px"}}};const Di={ant:lv,vue:cv,pie:av};var uv=ce({name:"FlowChart",props:{code:{type:String,required:!0},id:{type:String,required:!0},preset:{type:String,default:"vue"}},setup(e){let t=null;const n=Cn(),r=ge(!0),o=ge(1),s=j(()=>Di[e.preset]||(console.warn(`[md-enhance:flowchart] Unknown preset: ${e.preset}`),Di.vue)),i=l=>l<419?.8:l>1280?1:.9;return De(()=>{Promise.all([_(()=>import("./flowchart-loQwkp6e.js"),__vite__mapDeps([])),new Promise(l=>setTimeout(l,800))]).then(([{parse:l}])=>{t=l(sv(e.code)),o.value=i(window.innerWidth),r.value=!1,t.draw(e.id,{...s.value,scale:o.value})}),Nr("resize",vh(()=>{if(t){const l=i(window.innerWidth);o.value!==l&&(o.value=l,t.draw(e.id,{...s.value,scale:l}))}},100))}),()=>[r.value?ne(vs,{class:"flowchart-loading",height:192}):null,ne("div",{ref:n,class:["flowchart-wrapper",e.preset],id:e.id,style:{display:r.value?"none":"block"}})]}});const fv=it({enhance:({app:e})=>{e.component("CodeTabs",Fm),e.component("FlowChart",uv)},setup:()=>{zm()}});function dv(e){return{all:e=e||new Map,on:function(t,n){var r=e.get(t);r?r.push(n):e.set(t,[n])},off:function(t,n){var r=e.get(t);r&&(n?r.splice(r.indexOf(n)>>>0,1):e.set(t,[]))},emit:function(t,n){var r=e.get(t);r&&r.slice().map(function(o){o(n)}),(r=e.get("*"))&&r.slice().map(function(o){o(t,n)})}}}const Pa=Symbol(""),hv=()=>{const e=Pe(Pa);if(!e)throw new Error("usePWAEvent() is called without provider.");return e},pv=async(e,t={},n=!0)=>{const{register:r}=await _(()=>import("./index-7SG8bi1h.js"),__vite__mapDeps([]));r(e,{ready(o){var s;n&&console.info("[Service Worker]: active"),(s=t.ready)==null||s.call(t,o)},registered(o){var s;n&&console.log("[Service Worker]: registered"),(s=t.registered)==null||s.call(t,o)},cached(o){var s;n&&console.log("[Service Worker]: cached"),(s=t.cached)==null||s.call(t,o)},async updatefound(o){var s;await navigator.serviceWorker.getRegistration()&&(n&&console.log("[Service Worker]: update found"),(s=t.updatefound)==null||s.call(t,o))},updated(o){var s;n&&console.log("[Service Worker]: updated"),(s=t.updated)==null||s.call(t,o)},offline(){var o;n&&console.log("[Service Worker]: offline"),(o=t.offline)==null||o.call(t)},error(o){var s;n&&console.error("[Service Worker]: ",o),(s=t.error)==null||s.call(t,o)}})},mv=async e=>pv(Yr("service-worker.js"),{ready(t){e.emit("ready",t)},registered(t){e.emit("registered",t)},cached(t){e.emit("cached",t)},updatefound(t){e.emit("updatefound",t)},updated(t){const n="service-worker-version",r=Number(localStorage.getItem(n)||0);localStorage.setItem(n,(r+1).toString()),localStorage.removeItem("manifest"),e.emit("updated",t)},offline(){e.emit("offline")},error(t){e.emit("error",t)}}),vv=()=>{const e=dv();Vt(Pa,e),De(async()=>{var n;let t=!1;(n=navigator.serviceWorker)!=null&&n.controller&&navigator.serviceWorker.addEventListener("controllerchange",()=>{t||(t=!0,window.location.reload())}),await mv(e)})};var _v={"/en/":{install:"Install",iOSInstall:"Tap the share button and then 'Add to Home Screen'",cancel:"Cancel",close:"Close",prevImage:"Previous Image",nextImage:"Next Image",desc:"Description",feature:"Key Features",explain:"This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system. ",hint:"New content found.",update:"New content is available."},"/":{install:"安装",iOSInstall:"点击分享按钮然后点击“添加到主屏幕”",cancel:"取消",close:"关闭",prevImage:"上一张图片",nextImage:"下一张图片",desc:"详情",feature:"主要特色",explain:"该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。",hint:"发现新内容可用",update:"新内容已就绪"}};const Ra=()=>ne(xa,{name:"update"},()=>ne("path",{d:"M949.949 146.25v255.826c0 21.981-13.989 35.97-35.97 35.97H658.154c-13.988 0-25.983-7.992-33.973-21.981-5.997-13.989-4-27.977 7.991-39.97l79.942-77.946c-55.954-51.973-121.918-77.955-199.863-77.955-37.975 0-75.95 8.002-113.924 21.99-37.975 15.985-67.948 37.976-91.934 63.957-25.982 23.987-47.973 53.96-63.957 91.934-29.983 73.955-29.983 153.895 0 227.85 15.984 37.976 37.975 67.947 63.957 91.934 23.986 25.982 53.959 47.973 91.934 63.956 37.974 13.989 75.95 21.991 113.924 21.991 45.967 0 87.942-9.998 127.913-29.982 41.976-17.99 75.951-45.967 101.931-83.943 7.993-4 11.994-5.995 13.989-5.995 5.997 0 9.998 1.994 13.988 5.995l77.958 77.946c3.989 4 5.986 7.993 5.986 11.994 0 1.994-1.996 5.995-3.99 11.994-43.973 51.962-93.941 91.934-151.9 117.914-53.958 25.983-115.92 39.972-185.874 39.972-61.961 0-119.921-11.984-169.89-33.973-57.96-25.985-105.923-57.963-139.896-93.943-35.98-33.972-67.958-81.936-93.94-139.897-45.967-101.93-45.967-237.846 0-339.777 25.982-57.96 57.96-105.923 93.94-139.896 33.973-35.98 81.936-67.958 139.896-93.94 49.968-21.99 107.928-33.974 169.89-33.974 55.963 0 109.923 9.988 161.885 29.973 53.97 21.99 101.933 51.963 139.908 89.938l73.954-73.944c9.987-9.998 23.987-13.988 39.971-8.002 13.988 8.002 21.98 19.995 21.98 33.984z"}));Ra.displayName="UpdateIcon";const gv=_v,bv=e=>{const t=e.waiting;if(!t)return;const n=new MessageChannel;t.postMessage({type:"SKIP_WAITING"},[n.port2])};var yv=ce({name:"SWUpdatePopup",slots:Object,setup(e,{slots:t}){const n=iv(gv),r=Cn(),o=j(()=>!!r.value),s=()=>{r.value&&(bv(r.value),r.value=void 0)};return De(()=>{hv().on("updated",i=>{i&&(r.value=i)})}),()=>ne(An,{name:"popup"},()=>{var i;return((i=t.default)==null?void 0:i.call(t,{enabled:o.value,reload:s}))||(o.value?ne("button",{type:"button",class:"sw-update-popup",tabindex:0,onClick:()=>s()},[n.value.update,ne("span",{class:"icon-wrapper"},ne(Ra))]):null)})}});const Ev=it({setup:()=>{vv()},rootComponents:[yv]}),wv={enhance:({app:e})=>{e.component("A2hs",V(()=>_(()=>import("./A2hs-LwmLJR8r.js"),__vite__mapDeps([]))))}};var Tv={provider:"Giscus",comment:!0,repo:"huuhghhgyg/MicroCityNotes",repoId:"R_kgDOIf-Z0Q",category:"讨论",categoryId:"DIC_kwDOIf-Z0c4CTl1f"};const Lv=Tv;let Cv=Lv;const Ia=Symbol(""),Oa=()=>Pe(Ia),Av=Oa,xv=e=>{e.provide(Ia,Cv)},Mi=["ar","ca","de","en","eo","es","fa","fr","he","id","it","ja","ko","nl","pl","pt","ro","ru","th","tr","uk","vi","zh-CN","zh-TW"];var Pv=ce({name:"GiscusComment",props:{identifier:{type:String,required:!0},darkmode:Boolean},setup(e){const t=Av(),n=!!(t.repo&&t.repoId&&t.category&&t.categoryId),{repo:r,repoId:o,category:s,categoryId:i}=t,l=ge(!1),a=j(()=>{const u=Bl().value;if(Mi.includes(u))return u;const f=u.split("-")[0];return Mi.includes(f)?f:"en"}),c=j(()=>({repo:r,repoId:o,category:s,categoryId:i,lang:a.value,theme:e.darkmode?t.darkTheme||"dark":t.lightTheme||"light",mapping:t.mapping||"pathname",term:e.identifier,inputPosition:t.inputPosition||"top",reactionsEnabled:t.reactionsEnabled===!1?"0":"1",strict:t.strict===!1?"0":"1",loading:t.lazyLoading===!1?"eager":"lazy",emitMetadata:"0"}));return De(async()=>{await _(()=>import("./giscus-unEZQsJ0.js"),__vite__mapDeps([])),l.value=!0}),()=>n?ne("div",{id:"comment",class:["giscus-wrapper",{"input-top":t.inputPosition!=="bottom"}]},l.value?ne("giscus-widget",c.value):ne(vs)):null}}),Rv=ce({name:"CommentService",props:{darkmode:Boolean},setup(e){const t=Oa(),n=Ht(),r=gt(),o=t.comment!==!1,s=j(()=>r.value.comment||o&&r.value.comment!==!1);return()=>ne(Pv,{identifier:r.value.commentID||n.value.path,darkmode:e.darkmode,style:{display:s.value?"block":"none"}})}}),Iv=it({enhance:({app:e})=>{xv(e),e.component("CommentService",Rv)}});const Ov=ce({__name:"Layout",setup(e){const t=ge(!1);return De(()=>{const n=document.querySelector("html");t.value=n.classList.contains("dark");const r=new MutationObserver(()=>{t.value=n.classList.contains("dark")});r.observe(n,{attributeFilter:["class"],attributes:!0}),nr(()=>{r.disconnect()})}),(n,r)=>{const o=yt("CommentService");return K(),Oe(ya,null,{"page-bottom":He(()=>[Ie(" 评论 "),se(o,{darkmode:t.value},null,8,["darkmode"])]),_:1})}}}),kv=xe(Ov,[["__file","Layout.vue"]]),Sv=it({layouts:{Layout:kv}}),yr=[Od,Dd,Hd,Zd,nh,lh,Nm,Vm,Hm,fv,Ev,wv,Iv,Sv],Dv=[["v-8daa1a0e","/",{title:"首页"},["/README.md"]],["v-2d0a870d","/en/",{title:"Home Page"},["/en/README.md"]],["v-4ee3d2cc","/docs/1.1_what_microcity_can_do.html",{title:"1.1 MicroCity的功能"},[":md"]],["v-498b1a32","/docs/2.1_showing_a_world_map.html",{title:"2.1 显示世界地图"},[":md"]],["v-0f6857b8","/docs/2.2_searching_for_countries.html",{title:"2.2 寻找国家"},[":md"]],["v-27daeef9","/docs/3.1_ui_overview.html",{title:"3.1 用户界面概览"},[":md"]],["v-3c8d6dee","/docs/3.2_vector_shapes.html",{title:"3.2 矢量图"},[":md"]],["v-6a2d64ac","/docs/3.3_raster_grids.html",{title:"3.3 栅格图"},[":md"]],["v-26445025","/docs/3.4_3d_scenes.html",{title:"3.4 3D场景"},[":md"]],["v-b2a5ca98","/docs/3.5_tables.html",{title:"3.5 表格"},[":md"]],["v-8532c374","/docs/3.6_maps_and_layers.html",{title:"3.6 地图和图层"},[":md"]],["v-656b8bd0","/docs/3.7_modules.html",{title:"3.7 拓展模块"},[":md"]],["v-4c59099a","/docs/4.1_si_overview.html",{title:"4.1 脚本概览"},[":md"]],["v-68871b76","/docs/4.2_ui_control.html",{title:"4.2 控制用户界面"},[":md"]],["v-3c0f83c0","/docs/4.3_shapes_and_tables.html",{title:"4.3 矢量图形和表格"},[":md"]],["v-c670a3a8","/docs/4.4_grids.html",{title:"4.4 栅格图形"},[":md"]],["v-672fdfba","/docs/4.5_3d_scenes.html",{title:"4.5 3D场景"},[":md"]],["v-34511d54","/docs/4.6_networks.html",{title:"4.6 网络"},[":md"]],["v-6802fed2","/docs/4.7_des_simulations.html",{title:"4.7 离散事件仿真"},[":md"]],["v-64fe0a3e","/docs/4.8_mixed_integer_programming.html",{title:"4.8 混合整数线性规划"},[":md"]],["v-147825fb","/docs/",{title:"MicroCity Desktop 文档"},["/docs/readme.md"]],["v-0be8554c","/notes/3d-objects.html",{title:"3D 对象"},[":md"]],["v-41e82e22","/notes/3d-scene.html",{title:"3D 场景"},[":md"]],["v-e8b6c472","/notes/",{title:"笔记"},["/notes/README.md"]],["v-7fd381e2","/notes/cy-simulation.html",{title:"港口AGV服务流程三维仿真思路"},[":md"]],["v-44b81126","/notes/debug.html",{title:"调试相关"},[":md"]],["v-0ceacb2b","/notes/event-scheduling.html",{title:"离散事件模拟和程序控制"},[":md"]],["v-8138aba4","/notes/lp.html",{title:"模型求解"},[":md"]],["v-ed3d82b0","/notes/lua.html",{title:"Lua语言快速上手"},[":md"]],["v-dfdf5468","/notes/mip.html",{title:"混合整数规划"},[":md"]],["v-16cb829c","/notes/network.html",{title:"操作网络"},[":md"]],["v-c58fd9e0","/notes/oop.html",{title:"面向对象编程"},[":md"]],["v-f610fd24","/notes/plots.html",{title:"通用绘图代码"},[":md"]],["v-19652be0","/notes/timelapse.html",{title:"时间推进法"},[":md"]],["v-6bb8b8e5","/notes/tools.html",{title:"有关工具"},[":md"]],["v-77d2e8b7","/notes/versions.html",{title:"MicroCity的版本"},[":md"]],["v-385f9c3c","/notes/visualization.html",{title:"结果可视化"},[":md"]],["v-187abc41","/notes/warehouse-simulation.html",{title:"自动化仓库仿真思路"},[":md"]],["v-1ae3cdb6","/notes/web-ui.html",{title:"用户界面简介"},[":md"]],["v-41d66a06","/en/docs/1.1_what_microcity_can_do.html",{title:"1.1 What MicroCity can Do"},[":md"]],["v-79ce9d5a","/en/docs/2.1_showing_a_world_map.html",{title:"2.1 Showing a World Map"},[":md"]],["v-30ccfc90","/en/docs/2.2_searching_for_countries.html",{title:"2.2 Searching for Countries"},[":md"]],["v-45e45965","/en/docs/3.1_ui_overview.html",{title:"3.1 UI Overview"},[":md"]],["v-0434254c","/en/docs/3.2_vector_shapes.html",{title:"3.2 Vector Shapes"},[":md"]],["v-0d5147c0","/en/docs/3.3_raster_grids.html",{title:"3.3 Raster Grids"},[":md"]],["v-5e3d6591","/en/docs/3.4_3d_scenes.html",{title:"3.4 3D Scenes"},[":md"]],["v-42244670","/en/docs/3.5_tables.html",{title:"3.5 Tables"},[":md"]],["v-eac61a9c","/en/docs/3.6_maps_and_layers.html",{title:"3.6 Maps and Layers"},[":md"]],["v-35430c3c","/en/docs/3.7_modules.html",{title:"3.7 Modules"},[":md"]],["v-6a627406","/en/docs/4.1_si_overview.html",{title:"4.1 SI Overview"},[":md"]],["v-da33eb4e","/en/docs/4.2_ui_control.html",{title:"4.2 UI Control"},[":md"]],["v-3aeb278c","/en/docs/4.3_shapes_and_tables.html",{title:"4.3 Shapes and Tables"},[":md"]],["v-a1c74cd0","/en/docs/4.4_grids.html",{title:"4.4 Grids"},[":md"]],["v-0461258f","/en/docs/4.5_3d_scenes.html",{title:"4.5 3D Scenes"},[":md"]],["v-10effe6a","/en/docs/4.6_networks.html",{title:"4.6 Networks"},[":md"]],["v-cd9655fa","/en/docs/4.7_des_simulations.html",{title:"4.7 Discrete Event Simulations"},[":md"]],["v-4d7828c2","/en/docs/4.7_des_simulations_zh.html",{title:"4.7 离散事件模拟"},[":md"]],["v-2b4c8f66","/en/docs/4.8_mixed_integer_programming.html",{title:"4.8 Mixed Integer Programming"},[":md"]],["v-39540332","/en/docs/",{title:"MicroCity Desktop Documents"},["/en/docs/readme.md"]],["v-6c395474","/en/notes/3d-objects.html",{title:"3D Objects"},[":md"]],["v-543cd98e","/en/notes/3d-scene.html",{title:"3D Scene"},[":md"]],["v-cefc5a4a","/en/notes/",{title:"Notes"},["/en/notes/README.md"]],["v-46fd19f6","/en/notes/cy-simulation.html",{title:"Port AGV Service Process 3D Simulation Approach"},[":md"]],["v-3520e381","/en/notes/debug.html",{title:"Debugging"},[":md"]],["v-63796ad2","/en/notes/event-scheduling.html",{title:"Discrete Event Simulation and Program Control"},[":md"]],["v-a86f52cc","/en/notes/lp.html",{title:"Model Solving"},[":md"]],["v-29921fbc","/en/notes/lua.html",{title:"Quick Start with Lua Language"},[":md"]],["v-304136e0","/en/notes/mip.html",{title:"Mixed integer programming"},[":md"]],["v-608c75c6","/en/notes/network.html",{title:"Operating Networks"},[":md"]],["v-3d68f424","/en/notes/oop.html",{title:"Object-Oriented Programming"},[":md"]],["v-471724fc","/en/notes/plots.html",{title:"Generic Drawing Code"},[":md"]],["v-51a5edf4","/en/notes/timelapse.html",{title:"Time Advancement Methods"},[":md"]],["v-7994b60e","/en/notes/tools.html",{title:"Tools"},[":md"]],["v-ebb0d7ba","/en/notes/versions.html",{title:"Versions of MicroCity"},[":md"]],["v-00ed9760","/en/notes/visualization.html",{title:"Visualization of Results"},[":md"]],["v-716da5ad","/en/notes/warehouse-simulation.html",{title:"Ideas for Warehouse Automation Simulation"},[":md"]],["v-eaa2a0de","/en/notes/web-ui.html",{title:"Introduction to the User Interface"},[":md"]],["v-31b53ad6","/images/doc/",{title:""},["/images/doc/readme.md"]],["v-3706649a","/404.html",{title:""},[]]];var $i=ce({name:"Vuepress",setup(){const e=gf();return()=>ne(e.value)}}),Mv=()=>Dv.reduce((e,[t,n,r,o])=>(e.push({name:t,path:n,component:$i,meta:r},{path:n.endsWith("/")?n+"index.html":n.substring(0,n.length-5),redirect:n},...o.map(s=>({path:s===":md"?n.substring(0,n.length-5)+".md":s,redirect:n}))),e),[{name:"404",path:"/:catchAll(.*)",component:$i}]),$v=zf,Nv=()=>{const e=Ld({history:$v(Dl("/MicroCityNotes/")),routes:Mv(),scrollBehavior:(t,n,r)=>r||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,n)=>{var r;(t.path!==n.path||n===Tt)&&([t.meta._data]=await Promise.all([wt.resolvePageData(t.name),(r=Nl[t.name])==null?void 0:r.__asyncLoader()]))}),e},Vv=e=>{e.component("ClientOnly",is),e.component("Content",Tf)},Hv=(e,t,n)=>{const r=Ii(()=>t.currentRoute.value.path),o=Ii(()=>wt.resolveRouteLocale(un.value.locales,r.value)),s=uh(r,()=>t.currentRoute.value.meta._data),i=j(()=>wt.resolveLayouts(n)),l=j(()=>wt.resolveSiteLocaleData(un.value,o.value)),a=j(()=>wt.resolvePageFrontmatter(s.value)),c=j(()=>wt.resolvePageHeadTitle(s.value,l.value)),u=j(()=>wt.resolvePageHead(c.value,a.value,l.value)),f=j(()=>wt.resolvePageLang(s.value,l.value)),d=j(()=>wt.resolvePageLayout(s.value,i.value));return e.provide(pf,i),e.provide(Vl,s),e.provide(Hl,a),e.provide(_f,c),e.provide(Fl,u),e.provide(zl,f),e.provide(jl,d),e.provide(os,o),e.provide(Ul,l),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>a.value},$head:{get:()=>u.value},$headTitle:{get:()=>c.value},$lang:{get:()=>f.value},$page:{get:()=>s.value},$routeLocale:{get:()=>o.value},$site:{get:()=>un.value},$siteLocale:{get:()=>l.value},$withBase:{get:()=>Yr}}),{layouts:i,pageData:s,pageFrontmatter:a,pageHead:u,pageHeadTitle:c,pageLang:f,pageLayout:d,routeLocale:o,siteData:un,siteLocaleData:l}},Fv=()=>{const e=vf(),t=Bl(),n=ge([]),r=()=>{e.value.forEach(s=>{const i=zv(s);i&&n.value.push(i)})},o=()=>{document.documentElement.lang=t.value,n.value.forEach(s=>{s.parentNode===document.head&&document.head.removeChild(s)}),n.value.splice(0,n.value.length),e.value.forEach(s=>{const i=Bv(s);i!==null&&(document.head.appendChild(i),n.value.push(i))})};Vt(yf,o),De(()=>{r(),o(),Qe(()=>e.value,o)})},zv=([e,t,n=""])=>{const r=Object.entries(t).map(([l,a])=>ve(a)?`[${l}=${JSON.stringify(a)}]`:a===!0?`[${l}]`:"").join(""),o=`head > ${e}${r}`;return Array.from(document.querySelectorAll(o)).find(l=>l.innerText===n)||null},Bv=([e,t,n])=>{if(!ve(e))return null;const r=document.createElement(e);return rs(t)&&Object.entries(t).forEach(([o,s])=>{ve(s)?r.setAttribute(o,s):s===!0&&r.setAttribute(o,"")}),ve(n)&&r.appendChild(document.createTextNode(n)),r},jv=of,Wv=async()=>{var n;const e=jv({name:"VuepressApp",setup(){var r;Fv();for(const o of yr)(r=o.setup)==null||r.call(o);return()=>[ne(ra),...yr.flatMap(({rootComponents:o=[]})=>o.map(s=>ne(s)))]}}),t=Nv();Vv(e),Hv(e,t,yr);for(const r of yr)await((n=r.enhance)==null?void 0:n.call(r,{app:e,router:t,siteData:un}));return e.use(t),{app:e,router:t}};Wv().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{Te as F,xe as _,pe as a,jt as b,te as c,Wv as createVueApp,se as d,_u as e,Ie as f,ge as g,j as h,Qe as i,ce as j,or as k,Rr as l,tf as m,Je as n,K as o,zt as p,Ne as q,yt as r,Kv as s,Go as t,xn as u,Uv as v,He as w}; +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = ["assets/index.html-rmW5MKDv.js","assets/play-RaBYbg3m.js","assets/icon_script_editor-ibm_2NsU.js","assets/icon_microcity-Je85-7MO.js","assets/icon_module-AxwvBQMt.js","assets/index.html-dxC6HmKS.js","assets/1.1_what_microcity_can_do.html-HcIFtvfI.js","assets/shot_script_editor-VtQOeIXC.js","assets/2.1_showing_a_world_map.html-Ybz9X3FC.js","assets/button_load-GOP3K2yO.js","assets/data_visualization-NDO9FqTF.js","assets/icon_shapes_polygon-5WS2EZQN.js","assets/button_action-tmG_4IgV.js","assets/2.2_searching_for_countries.html-Y0QCK0Nw.js","assets/query_results-qHjDevxa.js","assets/3.1_ui_overview.html-3VU9Yk9s.js","assets/main_window-T08x4hNs.js","assets/3.2_vector_shapes.html-uMTzJRD1.js","assets/edit_point-Z0R1Z63o.js","assets/3.3_raster_grids.html-_OMWjBic.js","assets/grid_attributes-xxRYXyrC.js","assets/button_3d-coWyniAs.js","assets/3.4_3d_scenes.html-IfcyMMcw.js","assets/scene_coordinate-_YCPy6or.js","assets/3.5_tables.html-rfKSY5-v.js","assets/add_field-ZFhY51wb.js","assets/3.6_maps_and_layers.html-KNvuRdkG.js","assets/button_ruler-TjPjykp6.js","assets/3.7_modules.html-acS-BfiZ.js","assets/module_settings-yrsWXh8u.js","assets/4.1_si_overview.html-mGhzJSIB.js","assets/script_editor-a48-sxc_.js","assets/4.2_ui_control.html-Zsu36Eou.js","assets/shot_parameter_id-roH75mzn.js","assets/4.3_shapes_and_tables.html-SxckQf89.js","assets/4.4_grids.html-exxRQ7PN.js","assets/4.5_3d_scenes.html-I_su3OaS.js","assets/4.6_networks.html-HJVUieG0.js","assets/4.7_des_simulations.html-Ie9zDG_n.js","assets/4.8_mixed_integer_programming.html-spXsyES8.js","assets/3d-objects.html-frmlnhRb.js","assets/polygon_sizes-bVJYQmiT.js","assets/3d-scene.html-iJwBMXhE.js","assets/coordinate-R7ZKfirG.js","assets/cy-simulation.html-ms-pVG5v.js","assets/Result-All2-cnkq843b.js","assets/event-scheduling.html-3ysZ_CTt.js","assets/CommandBar-jgj8yIQP.js","assets/network.html-IGA5rLvk.js","assets/two_way-xpspXH9g.js","assets/oop.html-VmjZry6A.js","assets/RMGObjects-PwARz0cG.js","assets/plots.html-KiXIG1Oc.js","assets/Subplot_Vertical-oXTmfxKU.js","assets/timelapse.html-VDhH9cuD.js","assets/fixed_increment_advance-iwDvqivb.js","assets/visualization.html-2T-VgKWL.js","assets/DL_Heatmap-RXB-9ZZK.js","assets/warehouse-simulation.html-5OK9wBKc.js","assets/6-1trend-atJpgMOK.js","assets/web-ui.html-Ub-X1RXi.js","assets/AutoTranslate-DxMBsWAh.js","assets/1.1_what_microcity_can_do.html-YHpuvmc-.js","assets/2.1_showing_a_world_map.html-GZyM8T_I.js","assets/2.2_searching_for_countries.html-OCp2-Zt6.js","assets/3.1_ui_overview.html-6J3N08CW.js","assets/3.2_vector_shapes.html-o5HA4H30.js","assets/3.3_raster_grids.html-KMfHWMMp.js","assets/3.4_3d_scenes.html-2qe1Dffq.js","assets/3.5_tables.html-KMEBPMHz.js","assets/3.6_maps_and_layers.html-Zp7Na5N3.js","assets/3.7_modules.html-mmRRzoSK.js","assets/4.1_si_overview.html-3JNy66LR.js","assets/4.2_ui_control.html-it8dN_Kd.js","assets/4.3_shapes_and_tables.html-9CbssTxf.js","assets/4.4_grids.html-H6iZCbel.js","assets/4.5_3d_scenes.html-IYlmTIee.js","assets/4.6_networks.html-Z1GoybBX.js","assets/4.7_des_simulations.html-WnzqINmi.js","assets/4.7_des_simulations_zh.html-PYbnXFlK.js","assets/4.8_mixed_integer_programming.html-ixWGOETF.js","assets/3d-objects.html-l7ht6tpD.js","assets/3d-scene.html-pmrdLLCG.js","assets/cy-simulation.html-x04vq-Lr.js","assets/event-scheduling.html-UZg_AtmL.js","assets/network.html-rimWgBRX.js","assets/oop.html-QdhyUyOK.js","assets/plots.html-6AeiZZxH.js","assets/timelapse.html-rfk9Tyut.js","assets/visualization.html-URi_NNx7.js","assets/warehouse-simulation.html-I2Ep6WY5.js","assets/web-ui.html-MXj0sqtU.js"] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} \ No newline at end of file diff --git a/assets/button_ruler-TjPjykp6.js b/assets/button_ruler-TjPjykp6.js new file mode 100644 index 00000000..38951e2e --- /dev/null +++ b/assets/button_ruler-TjPjykp6.js @@ -0,0 +1 @@ +const A="/MicroCityNotes/assets/map_coordinates-8ybUOErD.png",a="/MicroCityNotes/assets/map_menu-zU_XTli2.png",g="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUwAAAFMCAMAAACXsHVtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKpUExURf///6CgoGJnbK2treLi5IKHkFNTU/Hx8QB41+Hh4RaE23BwcAAAANv/////trb///+2Zv//2wA6kFtbW2a2//DOhr+/v//bj5A6AMzMzM7w8GYAADU1hmYAZjk5j+HBf6vw8MHh4YbO8AAAZhkZGRkZcLZmAJDb/zMzf2Z41wUHCACR7DqQ22YAOjUAYPDwzqDi5P/bkABmtvDwqwA5j4/b/9v/8uLCgKDh4Y85AH/B4TkAZjUAAAA1hjMAW4Y1ANuQOuHhoGCr8AAANX8zADoAAPCrYABgq9u/3oY1NQCo8gB43joAZjWGzuHhwcF/M5CR1wAAW6tgAGbV/2AAADkAAGAANQBaoOGgWs6GNQAAOs7OhjOAw485OVoAAOLiogAAWgB45cKANFqh5OKhW7ZmZjUANQAzf8Li5HBXPJDq+WAAYP/V5QAzgDN/wTmP27b/8uLiw5Dq/zMAAAAAYGYAOZCQZgAAMzMAWloAMwAAOf//8tvq8jp416BaALao16tgYFxhZTMzM1tgZVc8GV1hZhk8V2Jma1pfZFoAWtvbj1ozf6BbAJA6Oma2tlqg4dvV5Wao8tvq7Dq/+YZgAM7wzv//+QA1YJDq8tuPOY9mAH8zMzMAMzpmZpBmkH/C5FoANNv/ts7wq2BlaV5jZ2BlamFma11iZ2BkaV1iZmZna2Fmal9kaWFlal9jaFtfZF9kaGJna1tgZFxhZlxgZWlqbF5iZxSD2gBbopCQ26B/M5C2kNv/+ZC2/4+P29vq+TqQkDo6OmY6Otu/5To6ZmA1AH9aAGZmZmbV8v/q7AAzWjU1YNvV8rb/+WZ43maR7FozM86rYDkAOaBaWmaPj6ChW6DiojVgYIaGNTU1NavwzqvOhmA1hqtgNYarhobOq7bbj9uPZmA1Nb5w/AIAAAmiSURBVHja7d2HfxvlHcdxNb0gmT62rGIrjh1ixU5lXBsntnEWDnFMEhsbB5PRNAkNhDTQppSR0NKWhFDaQkuhrLaM7gF0QAvde++99/5L+ow7DWv69ESRTp/vK7qlky56+/c8z52UyKFziLWEzgkRSwETTDDBJGCCCSYBs5qYrS9uzpy3nB/1f4xSD/aOVVcRy818uSiAGesYAbPMLH/p8oxZHszh714e9YcZ62grH3PhznWJaRizLLMxJwaTbWAuQjPbMgszdn+ffl0tXUIIueDNXY/h7UK0xToG9atX9w1Klnd1eY8w23pdtwm9aPZSDzZLevad1M6DoaxjXPj17aKtVW/Wx9JPr+Y1q5ltmYWpjC7sk69P/vWT6uWauYsZ+2BzqLU3qriTbWo/WWCxDhdPFVtLl3I2G4Z1f+HuJR/sLaldzM7ehoxjyJ9LqxhRj3WPpZ++tTdaj5jJQX3T1Skn3jzVUnW1SQW5IutHZjDVYNWC3tXd0tJ1oE8+2OyV3t88m945Y4N3DPWDdG/mWPrJivYgNdvMdYsTpvbyYA5vH9QFNzE4MeJtzoN5f5+35UBf+sHuUgZmxoZcTPdYNY1ZfADS7Um2O9X0Yh2mmat5hseE3GX4B99zu4Kj0SxM08zN/sPfTDXio1HVzN0lOWv5qtk5tSF1jDSmeyx9qjZRm828xKlRcsSdyiZ44PXy5Xhzt8/sEOIDqivUXZw3QnhVM7FgAEoK2fu5e6VGL71B7qF2djdkHiON6R4r1vHj9DPW20l7eVFda3VSs92ltWvz4cujYFrCTFbxvC/4lUnABBNMMAmYYIJJysIME0sBE0wwwSRgnpXcBaa9fApMe3k7mGDWZD4Lpr18Lo3pMPE7cfMWKtNewLSYL4BpL28G00YcMG3n874x21d0wpedt+Vgto9PyemuWxN5/MaF2NyZH3PNZT0ND5wH87qfJ8Kje/Jgju6ZDIfvTBTBbPB8Mhdz6C+T4R1/HkrsF0LMSbN3i0t73HsM5JotaovENAtqXTz6Q7n35oMrOmX16jtTj8ruowO3kHnS/nQezL+v6PznvzRc+3U97eOT4f2mbY/umdN77JoL79jcKTHNQnjXVLqZv2fLpL5zXM9yjxfofCkP5t8u+/c/DmpMKaRa8+jLelJ95mR49DUJtaV9xUfNglpPYR40u6tHNV4H+vE8mIn9f51TTVq280uzMGV2yC2SVN9x0F0YysD8rSzHNVsmGxPzM/kwVeseSuy4NeFWptdZ6v5y0lRi2FRmqiv1KnMo0biV+Vw+TLc+p3SfKUn2T5mqnNO9qOoz5aBu+ky5sGaLvnvXZGaf2ZCYzxTGHN0jHv1fT8a5pdyQGr2n3NFcLnjr495oLs+qCmAGbERfuOETpa6AuNApdUWezsfAtJcneaPDXp6tEmZDnLh/msq0l6fAtJd7qo0Z0LOjKmEGvrdMv8Dnaeb2siQT08Gjokb3oipWZuB/VovDdLArlrtzMZ1cCqfgDoWmjTCk5+StJSrToYGXn1czmoNZk8N6CpPTosqT22cuJWWn5Gi+lP+dW26WljzPBLNQFrZqMMGsb8yWLvOFduV+cXPsFWNmYdnKZjCzMWMb20KtI+q7ynoXiUll5mCqglx2cXRhZcY2CnFR87K94k1jugTlbdnKJ+SaukNcdO/KJ3r/s7JZrsj71Zc+3gSmaqwX58XU37Cpq1aSuph79ZquTLUsNyVvUlvkn5ZvBRIzXhBzdUHMlteNLcA0K0pR3peqTD0zmHr5I+frx0rMYDbzeDxuozL1FlV1qjoLYt67VzZ50/LbAogZj6c0K+ozDaZbtdq7UGWaPB6w4vTq0tNc5GjuYiaNSmxjZp/5uzG13cUMqV894C7LPjN0NPrfMfMMgcP0Jos+z5QjshqSXUw9mo/IcUbf97gQf0hVptooR3NTpXqv1pr96uXKMDPGIK6AuJysY8wIyRcwwQwW5kDztJys60fQBuY3TvaDaQtz3UPTGnP2eOi985GZGyKR3eo2DaYfzF891q8wJd/MT08NPHxq9tjJ/tlj82D6weyfmZaTwzf3Rw7/cl4qDjz4yGm1BqYfzNnHfr2uf0BdRsp2vvv0I6dnbhh4kD7TH2Zk5hemMlVmvn9s/vDND02D6RNz9vjtus+M/EQO7N9++FRk98l5MH1iRmZu16N5SA7js8enzTqYXAGBGQxMwvuZYIIJJphgggkmmGCCCSaYYIIJJphgggkmmARMMMEEE0wwwQSTgAkmmGCCCSaYYILpH/MlYIIJJn0mARPMOsdcDaY9zPPAZDQHk2ZOwAQTTDDBBJMrICqTUJlgggkm1+Zg0sw5NQITTDDBBBNMMMEEE0wwwQSTgMkbHVQmmGCCCSaYBExOjcAEk2YOJs0cTAImmGCCyb+CA7N+MPnP+2CCCSYBE0wwwQQTTDDBJGCCybtGYIIJJpgMQGCCCSaYYIIJJphgggkmmGASMHmjA0wwwaTPBBNMAiYDEJhg0szBBBNMAiaYYIIJJphgggkmmGCCCSaYYIIJJphgggkmARNMMMEEE0wwwSRgggkmmGCCCWYAMePh9BTMSjHj3oTfbWEBM65v/KYqG31mPO5Zgln5AJSyBNPCaB7nF9JV49QITDDBBJOAWZWUgUnKTklM4jtgggkmmARMMOs9q8G0l6zPgBw8fMUp+IEasVOZLyCLT6gAJm9dVPZmEs38TDVzAiaYYBIwwQQTTGIdk3c5Kn2fg8o8k83cqbGpTsRWvCd8oa3UYZ8Z+fK5VpLGbLKTusQ817ERMMEEE0wwq4XZfcGqBsB8pRDiKsdZf8la55Ztr32Vb8wr5PPc2OCY11651rn60FUa876v+K/MK67Z0LT1nasaGvOWbUdUdV65VmJeW6wuS2BufeOmdHl2X/AjcZtc37lNiOtXyalcaQRMVZCOc/WHP7T+kj8WtyyO2f2GDd7S+zd1n3ig6eXXr2q6Y5/acMeNamXxmLX0boezGMxDR9afEJVgKjuTne/bpODkbes7FLCayrr1W5lO4Zlzpi/h8/08y6zMP8me0z/mNRu8Yeg2D9NUa/cJ4W1rpD5z/YkjlfaZ0jRdmQbT1Gc5febqQI3marmy0fxr+3SfaTB3bvP6zKbfb2i480znvmKaZZxnPrD1kPjZbzxMPZrvc6eNgcnlJJhggnk2MJ0axuRjC3uY9f2BmlNgfoZLuMCnk/X6UW+JF+EUfeWWPtmt2/CPEMAEE0wSGEynfjGdoqdHxFplQlpaZonfZl6dM/f6yhIGIKuYZz93fXFJMPJ/r7GE4HhtUrsAAAAASUVORK5CYII=",m="/MicroCityNotes/assets/layer_menu-lHo367yT.png",s="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAg0lEQVR42r3TSw6AMAgE0M65rS60PTfKAoMoBONnNo0GX8amRTFpcyP9XKeKkggsMIzDYaAvPQVCEA0AKER0AiPsPUgjDNgwePXeloFt4zVyWtE/kJcQerjZH0GC8cqghuRASsJf02FwG+Z1/zC4Nj5kB2xjg6WgbELIjW6m9+s25GUFzwp8EfbjQrsAAAAASUVORK5CYII=",M="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAbUlEQVR42q2TWQ7AIAhEO/c/NG3SmqAMW5UfgzKPRcUVm3wrkjgToIXy2OsAkcZsGqH2lzOcBInWm9Y8MUuiq/sFYm0OEB0yHWoAcmeTmQtaM1YhU2vVKjJQG3YExB6le/27oBRW+SIlWBfUthvY82MRgXNcRQAAAABJRU5ErkJggg==",o="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAeUlEQVR42s2T0RbAEAhA67u3x/nu2AwtZfKkB+R0rq4DghkXtfWJ8BM4BNGRKsLeIHKA2N1U0JveuQQg5knsU4q0GzrQCCI7eiCtaKqTTu0D4TALUuq5mgoxL1WBlGGekk/1q3m62kat+i2rgXjMS2qg/Ai3Ghj/MwKEPFUOVRcF+QAAAABJRU5ErkJggg==",t="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAkklEQVR42p3S3Q6AIAgFYM5z27po9txmPzZFOLS8k8E3ASH8FCMG+RpsSD0CQPKWZVkXaXerDgx5k2qxvutaxMheA2luRWGIkDs4QxpDhPgDTAMGijgvEdXuiV1Q3UppW/nzonOrb2sMYzN6vgaGYXuYt7WGWFszsQgxoQizEBfy27QRCmmMISHUYwz5BHUYzT0A22OImeMm74kAAAAASUVORK5CYII=",B="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAlElEQVR42p3SSQ6AIAwF0P5zS1wYPDfiUMROENkB7UtpAcWrGGeg2UNG6iIAlLdMaU3EeysPEdKCarLcy1yMkDd5rxeLi2EGYegOsDFYCCf5zdMYJNKgLliXp595QXUqhafyp6Jzqu1pEpvt0fM18Gl2hFlTY8Sa2rAyCzGhcWUacSEP85AQkliEDKEei5ApqMPC2AOBS4iZAFEifAAAAABJRU5ErkJggg==",Y="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAjUlEQVR42s2TSw6AIAxE7XG8oYkuJfGGHqcWkV9pEXDjLICS5qXTAkyqdoznDaYXQRWEK2WYf4OwA5T0JoCe0MYcAOA2do8kujUFqAbhFd2QmNRUSWEtg6QwFbKcLjjmYE2EqE0VIH5pp1jlkNJaSGgRQbyLdGqfIUPWJEhmrbvh7DGPTU34Ef1TU/7nBemGUA6duqlQAAAAAElFTkSuQmCC",C="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAArklEQVR42o3SQRLDIAgFUDh3nC4yem6LMSrih9ZN1OALBJniUcEer2mW94nN5onIIGamfGdKn0Rj3c9l9ZHEHCEzBQnb1+WNumRRbJoYOeoCCMoIIu1wlYMeYjNyy5mAQTreHY6Q9SwQ0fEPJF2poysuFCCtq7M0DztKmyVc+mrsP9tiA3xrNw1YCGy/xvas9rlGvHt0YDojhLhQVCZCQghl5iE/IY1FyF+QwsLYL0f7sRzChG+ZAAAAAElFTkSuQmCC",G="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAATUlEQVR42mNkIBEwgskWotXXwDVUE6G6FVWDE17F+7BqcMKtGqcGJxyq8WmwRFJ9nDgN/+EhSCsNJDqJNE+TFqykRRyJSYNIANVAAgAA3hg4Ed06kO0AAAAASUVORK5CYII=",E="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAWElEQVR42q1QQQ4AIAiC/z+6WodmWyPMuJSGhBBFULw1h0cxTFFbDvBLoMFc4US89hiaSAgsLrGnrdwdOV8cWGHdMniGysCanwID40Zkz00g/3UQqK5QQgcKSi4RSBgHpAAAAABJRU5ErkJggg==";export{A as _,a,g as b,m as c,s as d,M as e,o as f,t as g,B as h,Y as i,C as j,G as k,E as l}; diff --git a/assets/cy-simulation.html-0hk7J5DH.js b/assets/cy-simulation.html-0hk7J5DH.js new file mode 100644 index 00000000..704d3437 --- /dev/null +++ b/assets/cy-simulation.html-0hk7J5DH.js @@ -0,0 +1 @@ +const e=JSON.parse(`{"key":"v-7fd381e2","path":"/notes/cy-simulation.html","title":"港口AGV服务流程三维仿真思路","lang":"zh-CN","frontmatter":{"description":"本文思路仅供参考。 Banner 集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。 实现场桥对集装箱的抓取 问题1截图 总体思路 实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/cy-simulation.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/cy-simulation.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"港口AGV服务流程三维仿真思路"}],["meta",{"property":"og:description","content":"本文思路仅供参考。 Banner 集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。 实现场桥对集装箱的抓取 问题1截图 总体思路 实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"港口AGV服务流程三维仿真思路\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"实现场桥对集装箱的抓取","slug":"实现场桥对集装箱的抓取","link":"#实现场桥对集装箱的抓取","children":[{"level":3,"title":"总体思路","slug":"总体思路","link":"#总体思路","children":[]},{"level":3,"title":"对象结构","slug":"对象结构","link":"#对象结构","children":[]},{"level":3,"title":"实现方法","slug":"实现方法","link":"#实现方法","children":[]},{"level":3,"title":"运行结果","slug":"运行结果","link":"#运行结果","children":[]}]},{"level":2,"title":"实现AGV到达至服务的全流程","slug":"实现agv到达至服务的全流程","link":"#实现agv到达至服务的全流程","children":[{"level":3,"title":"问题描述","slug":"问题描述","link":"#问题描述","children":[]},{"level":3,"title":"What's New","slug":"what-s-new","link":"#what-s-new","children":[]},{"level":3,"title":"对象设计","slug":"对象设计","link":"#对象设计","children":[]},{"level":3,"title":"总体布局","slug":"总体布局","link":"#总体布局","children":[]},{"level":3,"title":"总体流程","slug":"总体流程","link":"#总体流程","children":[]},{"level":3,"title":"实现方法","slug":"实现方法-1","link":"#实现方法-1","children":[]},{"level":3,"title":"运行结果","slug":"运行结果-1","link":"#运行结果-1","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"notes/cy-simulation.md","autoDesc":true}`);export{e as data}; diff --git a/assets/cy-simulation.html-5ddk20cl.js b/assets/cy-simulation.html-5ddk20cl.js new file mode 100644 index 00000000..43e6503f --- /dev/null +++ b/assets/cy-simulation.html-5ddk20cl.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-46fd19f6","path":"/en/notes/cy-simulation.html","title":"Port AGV Service Process 3D Simulation Approach","lang":"en-US","frontmatter":{"description":"This train of thought is for reference only. Banner Simulating the process of a container terminal is a complex task that involves many factors and entities. This article mainly...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/cy-simulation.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/cy-simulation.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Port AGV Service Process 3D Simulation Approach"}],["meta",{"property":"og:description","content":"This train of thought is for reference only. Banner Simulating the process of a container terminal is a complex task that involves many factors and entities. This article mainly..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Port AGV Service Process 3D Simulation Approach\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Implementing Yard Crane Handling of Containers","slug":"implementing-yard-crane-handling-of-containers","link":"#implementing-yard-crane-handling-of-containers","children":[{"level":3,"title":"Overall Approach","slug":"overall-approach","link":"#overall-approach","children":[]},{"level":3,"title":"Object Structure","slug":"object-structure","link":"#object-structure","children":[]},{"level":3,"title":"Implementation Approach","slug":"implementation-approach","link":"#implementation-approach","children":[]},{"level":3,"title":"Overall Layout","slug":"overall-layout","link":"#overall-layout","children":[]},{"level":3,"title":"Overall Process","slug":"overall-process","link":"#overall-process","children":[]},{"level":3,"title":"Implementation Method","slug":"implementation-method","link":"#implementation-method","children":[]},{"level":3,"title":"Results","slug":"results-1","link":"#results-1","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/cy-simulation.md","autoDesc":true}');export{e as data}; diff --git a/assets/cy-simulation.html-YeLzi-Ut.js b/assets/cy-simulation.html-YeLzi-Ut.js deleted file mode 100644 index d6ea7379..00000000 --- a/assets/cy-simulation.html-YeLzi-Ut.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse(`{"key":"v-7fd381e2","path":"/notes/cy-simulation.html","title":"港口AGV服务流程三维仿真思路","lang":"zh-CN","frontmatter":{"description":"本文思路仅供参考。 Banner 集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。 实现场桥对集装箱的抓取 问题1截图 总体思路 实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/cy-simulation.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"港口AGV服务流程三维仿真思路"}],["meta",{"property":"og:description","content":"本文思路仅供参考。 Banner 集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。 实现场桥对集装箱的抓取 问题1截图 总体思路 实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-06-03T03:38:14.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"港口AGV服务流程三维仿真思路"}],["meta",{"property":"article:modified_time","content":"2023-06-03T03:38:14.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"港口AGV服务流程三维仿真思路\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-06-03T03:38:14.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"实现场桥对集装箱的抓取","slug":"实现场桥对集装箱的抓取","link":"#实现场桥对集装箱的抓取","children":[{"level":3,"title":"总体思路","slug":"总体思路","link":"#总体思路","children":[]},{"level":3,"title":"对象结构","slug":"对象结构","link":"#对象结构","children":[]},{"level":3,"title":"实现方法","slug":"实现方法","link":"#实现方法","children":[]},{"level":3,"title":"运行结果","slug":"运行结果","link":"#运行结果","children":[]}]},{"level":2,"title":"实现AGV到达至服务的全流程","slug":"实现agv到达至服务的全流程","link":"#实现agv到达至服务的全流程","children":[{"level":3,"title":"问题描述","slug":"问题描述","link":"#问题描述","children":[]},{"level":3,"title":"What's New","slug":"what-s-new","link":"#what-s-new","children":[]},{"level":3,"title":"对象设计","slug":"对象设计","link":"#对象设计","children":[]},{"level":3,"title":"总体布局","slug":"总体布局","link":"#总体布局","children":[]},{"level":3,"title":"总体流程","slug":"总体流程","link":"#总体流程","children":[]},{"level":3,"title":"实现方法","slug":"实现方法-1","link":"#实现方法-1","children":[]},{"level":3,"title":"运行结果","slug":"运行结果-1","link":"#运行结果-1","children":[]}]}],"git":{"updatedTime":1685763494000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/cy-simulation.md","autoDesc":true}`);export{e as data}; diff --git a/assets/cy-simulation.html-bcA0fx8Y.js b/assets/cy-simulation.html-bcA0fx8Y.js deleted file mode 100644 index b96caabe..00000000 --- a/assets/cy-simulation.html-bcA0fx8Y.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as i,r,o as c,c as n,a,b as s,d as o,w as d,e}from"./app-DaLjD81q.js";const h="/MicroCityNotes/assets/Banner-O--M2FyY.png",l="/MicroCityNotes/assets/Q1Banner-BxB6kPmr.png",p="/MicroCityNotes/assets/Q1ContainerProcessFlow-t0XYjgJ-.png",m="/MicroCityNotes/assets/RMG1-zXf9sSV8.png",g="/MicroCityNotes/assets/CY1-KhoqZKrQ.png",u="/MicroCityNotes/assets/CYLayout-XevrzO6A.jpg",_="/MicroCityNotes/assets/Q1Run-k0t0w3ny.gif",x="/MicroCityNotes/assets/Q2-hS2yYPEB.jpg",f="/MicroCityNotes/assets/CY2-uRljosmO.png",y="/MicroCityNotes/assets/RMG2-ea6huW81.png",A="/MicroCityNotes/assets/AGV2-cOVBigXf.png",b="/MicroCityNotes/assets/RMGQC2-BO9lyakQ.png",G="/MicroCityNotes/assets/SHIP2-pz8IHA_0.png",V="/MicroCityNotes/assets/Q2Layout-jXHR-iYn.png",M="/MicroCityNotes/assets/Q2ProcessFlow-x5H0zUKQ.png",k="/MicroCityNotes/assets/RMG-AGV-ProcessFlow-aQWltqys.png",v="/MicroCityNotes/assets/AGVQueueModel-VbkDUcno.png",C="/MicroCityNotes/assets/EventSchedulingRefresh-P9P75NgW.jpg",N="/MicroCityNotes/assets/Result-RMG1-JQinaQsa.gif",w="/MicroCityNotes/assets/Result-RMG2-5wsDxvrc.gif",B="/MicroCityNotes/assets/Result-RMGQC-2f3rMSxL.gif",R="/MicroCityNotes/assets/Result-All1-1lFQ9mTr.gif",Q="/MicroCityNotes/assets/Result-All2-nf5PPryC.gif",E={},P=e('

港口AGV服务流程三维仿真思路

本文思路仅供参考。

Banner

集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。

实现场桥对集装箱的抓取

问题1截图

总体思路

实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽象为对象。

总体结构

具体的想法是将堆场对象作为数据模型(DataModel),主要存放各种数据,如存放集装箱实体、对应位置(行、列、高度)的集装箱坐标等数据;将场桥对象作为操作器(Operator),主要实现场桥的三维动画、实现对堆场对象中数据的管理。

这样做的好处是可以将场桥和堆场解耦合,方便后续的扩展。此外,如果对象属性考虑得比较周全,可以方便地在同一个场景中创建多个对象,实现多个场桥对堆场的操作。

事件和任务

我打算为整体流程中涉及到需要移动的主要实体对象创建任务序列。这样可以做到在同一个场景中实现多个场桥的并行操作,各个场桥执行各自的任务,互不干扰。此外,还需要一个总控制程序控制每个时间节点的任务执行情况,并控制场桥的三维动画。

业务流程

在这部分的仿真中主要业务流程聚焦于集装箱的移动。因此,最重要的就是集装箱所有权的流转。集装箱的所有权流转流程如下图所示:

集装箱对象流转过程

集装箱对象流转过程

对象结构

以下是这个仿真中主要涉及到的对象的结构

问题1场桥对象结构图

问题1堆场对象结构图

实现方法

堆场规模

对于堆场对象,由于它的功能主要是存放集装箱对象及其相关数据(比如对应位置的坐标),那么就还会出现一个问题,堆场的规模有多大?因此确定堆场的规模是一个必要的步骤。在创建堆场对象时需要确定所创建的堆场的规模,即行数、列数、高度。这样可以在创建堆场对象时就确定堆场的规模,方便后续的操作。

我的做法是首先确定堆场对象的占地大小集装箱层数,然后由相关数据去计算最多能摆放几行几列的集装箱。

  • 堆场占地大小方面,通过在创建对象时输入两点坐标来确定,根据两点连成的对角线构成一个矩形,从而确定堆场的占地面积。
  • 集装箱层数方面,通过在创建对象时输入一个数字来确定。根据这两个输入就就可以确定堆场的规模。

堆场布局计算

事件和任务

由于在这个仿真中需要移动的对象主要是场桥,因此每次循环执行任务的时候只需要操作场桥即可。

因此,我打算将场桥的任务序列作为一个队列,每次循环执行任务的时候,从对象的任务序列中取出第一个任务执行,执行完毕后判断是否满足任务执行完毕的条件,如果满足则删除这个任务,执行下一个任务。这样可以保证每次循环执行任务的时候,场桥对象能够按照次序执行任务。

执行任务的方法为 executeTask(dt) ,对象根据推进时间的长短 dt 执行任务。在 executeTask(dt) 中存放了处理任务的逻辑,包括判断任务类型、执行任务、删除任务等。

如果场景中存在多个场桥,只需要将这些对象添加到执行任务对象的列表中即可。主控程序每次循环执行任务时,会遍历这个对象列表,依次执行每个对象的任务。

提示

注意此处任务执行虽然在时间点上看是同时执行的,但是其实和对象所处的序列位置有关。

一个例子就是:假设两个对象同时需要抢占位置A,那么按照任务序列的顺序,先执行的对象会抢占到位置A,后执行的对象会抢占失败,尽管它们在同一时刻都在抢占位置A。因此,此处不是严格的同时执行,而是同一时刻按照任务序列的顺序执行。

业务流程

  1. 场桥首先从堆场中获取对应位置(行、列、高度)集装箱的坐标,并将吊具移动到堆场指定集装箱位置,抓取集装箱。集装箱所有权从堆场(cy.containers)转移到场桥吊具(rmg.attached)(通过解除表引用实现,将值设为 nil)。
  2. 场桥将集装箱移动到过道并放下集装箱。以同样的方式将集装箱所有权从场桥吊具(rmg.attached)移动到过道(rmg.stash),表明集装箱可以被提取。
  3. 如果有车辆将集装箱接走,则可以进一步将集装箱所有权从场桥过道(rmg.stash)移动到车辆上。

运行结果

场桥仿真

实现AGV到达至服务的全流程

问题描述

问题2描述

使用事件调度法实现以上流程的三维化形式

What's New

上一个仿真的实现是实现这个仿真的基础。相比于上一个仿真,这个仿真最为显著的改进体现在:

  • 使用面向对象编程模式,创建场桥、堆场(数据模型)、AGV、岸桥、船(数据模型)共4个类型的对象,并实现对象本体和其各部件的移动方法。
',42),j=e('
  • 延续面向事件的仿真的思路,实现了总控制流程,实现同一时刻对多个对象同时进行控制(主要通过对象的 executeTask(dt)maxStep() 及相关函数实现)。在面向对象的编程模式中,可以将 executeTask(dt)maxStep() 视为接口,主程序通过实现这两个接口,实现对对象的控制。(尽管lua中似乎没有这部分的概念)
  • 使用任务序列实现各个对象的流程,实现场桥和AGV之间、AGV和岸桥之间的相互等待,实现不同对象之间的任务协同。
  • 尝试将流程从堆场至AGV延伸至岸桥、船,实现两级排队等待。

对象设计

由于属性和函数实在太多,因此使用思维导图的形式展示对象的设计。

提示

此处占用篇幅较大,您也可以直接跳转到下一部分总体布局

堆场

堆场仍然作为数据模型。 堆场

场桥

场桥

AGV

AGV

岸桥

岸桥的代码和涉及结构主要衍生自堆场,因此后面不详细叙述。 岸桥

船对象的主要作用也是作为数据模型,设计思路同堆场。

船

总体布局

总体布局

总体流程

总体流程图

集装箱流转流程

相比于之前的仿真,这个仿真在流程上更进了一步,添加了AGV到达、排队的流程,还添加了岸桥服务、集装箱装船的流程。

流程分析

AGV出现后,场桥、岸桥和AGV之间的流程也变得更加复杂。首先,AGV的到达是随机的,因此可能造成排队现象。其次,AGV的到达会触发场桥和AGV的流程,而场桥和AGV的流程又会触发岸桥的流程。因此,这个仿真的流程是一个多级流程,需要考虑多个对象之间的流程协同。

特别是AGV和场桥之间的流程,其中存在AGV和场桥的相互等待。AGV到达的时候需要通知场桥提取货物。在场桥提取的过程中:

  • 场桥需要等待AGV到达指定位置后,才能将货物移动到AGV上
  • AGV需要等待场桥的抓取并将集装箱放在AGV上以后,才能将集装箱的所有权从场桥转移到AGV上

因此,AGV和场桥之间的流程是一个相互等待的流程。具体流程可以参考下图。

AGV和场桥相互等待的流程图

而岸桥的流程和场桥的流程类似,也是一个相互等待的流程。主要体现在:

  • 当AGV到达指定位置时,岸桥可能在服务别的AGV,此时AGV要进行等待
  • 当AGV刚进入岸桥的服务区域时,通知岸桥到达指定位置,如果岸桥先到达指定位置,则此时岸桥要进行等待

实现方法

排队流程的实现

AGV排队的情况我选择使用元胞自动机作为停车位的数据模型。其中,停车位的长度为:

',31),S=a("p",{class:"katex-block"},[a("span",{class:"katex-display"},[a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[a("semantics",null,[a("mrow",null,[a("mtext",null,"停车位长度"),a("mo",null,"="),a("mtext",null,"对应数据模型中1个集装箱的长度"),a("mo",null,"+"),a("mtext",null,"集装箱间隔长度")]),a("annotation",{encoding:"application/x-tex"}," \\text{停车位长度}=\\text{对应数据模型中1个集装箱的长度}+\\text{集装箱间隔长度} ")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord text"},[a("span",{class:"mord cjk_fallback"},"停车位长度")]),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),a("span",{class:"mrel"},"="),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),a("span",{class:"mord text"},[a("span",{class:"mord cjk_fallback"},"对应数据模型中"),a("span",{class:"mord"},"1"),a("span",{class:"mord cjk_fallback"},"个集装箱的长度")]),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord text"},[a("span",{class:"mord cjk_fallback"},"集装箱间隔长度")])])])])])],-1),T=e('

由于AGV的长度比1个集装箱略长,因此需要占用2个停车位的长度。每次执行任务时,AGV会判断前方空间是否被阻塞,如果没被阻塞则向前移动。如果前方位置为目标bay,则前进后等待场桥作业,获取集装箱后继续以元胞为单位向前移动直到离开。场桥部分排队和岸桥部分排队原理也相同。

AGV排队示意图

AGV元胞自动机排队模型示意图

事件调度法的实现

在之前的仿真中,我使用了非固定步长的时间推进法来实现仿真。在这个仿真中,我使用了事件调度法来实现仿真。相比于时间推进法,事件调度法的特点是可以准确地将事件推进到发生的时刻,从而执行对应事件。

你可能注意到了对象设计部分我将 executeTask()maxstep() 标记为(interface),这是由于为了计算准确的推进时间,我需要在每个对象中实现 executeTask()maxstep() 方法。其中,executeTask() 方法用于执行任务,maxstep() 方法用于计算距离到达下一个事件的发生时间(当前任务还剩多久能执行完),然后得到最大能够推进的时间,再去跟系统运行得到的间隔时间dt进行比较得到最大的推进时间。

我认为课件中的下面这张图能够很好地表示如何使用事件调度法来进行仿真并刷新场景。其中,第一行指的是仿真的业务流程,第二行Refresh部分指的是刷新场景。

事件调度法示意图

运行结果

注意

由于以下部分内容均为动图且图片体积较大。由于本站托管于GitHubPage,因此如果您没有的特殊网络环境可能会造成动图加载缓慢甚至加载失败。

提示

如果您直接观看动图的时候动图区域出现了摩尔纹,可以尝试将动图点开放大看,再看看是否有改善。

场桥运行过程 场桥运行过程1

场桥运行过程2

岸桥运行过程 岸桥运行过程

总体运行过程 总体运行过程1

总体运行过程2

',15);function Y(F,L){const t=r("RouterLink");return c(),n("div",null,[P,a("blockquote",null,[a("p",null,[s("如果不了解面向对象编程,可以参考"),o(t,{to:"/notes/oop.html"},{default:d(()=>[s("通用知识-面向对象编程")]),_:1})])]),j,S,T])}const q=i(E,[["render",Y],["__file","cy-simulation.html.vue"]]);export{q as default}; diff --git a/assets/cy-simulation.html-ms-pVG5v.js b/assets/cy-simulation.html-ms-pVG5v.js new file mode 100644 index 00000000..e189867c --- /dev/null +++ b/assets/cy-simulation.html-ms-pVG5v.js @@ -0,0 +1 @@ +import{_ as i,a as r,b as d,c as n,d as c,e as h,f as l,g as p,h as o,i as m,j as g,k as u,l as _,m as x,n as b,o as f,p as A,q as V,r as G,s as v,t as k,u as y,v as w}from"./Result-All2-cnkq843b.js";import{_ as B,r as E,o as T,c as j,a,b as t,d as M,w as N,e}from"./app-LOf__QKq.js";const q={},S=e('

港口AGV服务流程三维仿真思路

本文思路仅供参考。

Banner

集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。

实现场桥对集装箱的抓取

问题1截图

总体思路

实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽象为对象。

总体结构

具体的想法是将堆场对象作为数据模型(DataModel),主要存放各种数据,如存放集装箱实体、对应位置(行、列、高度)的集装箱坐标等数据;将场桥对象作为操作器(Operator),主要实现场桥的三维动画、实现对堆场对象中数据的管理。

这样做的好处是可以将场桥和堆场解耦合,方便后续的扩展。此外,如果对象属性考虑得比较周全,可以方便地在同一个场景中创建多个对象,实现多个场桥对堆场的操作。

事件和任务

我打算为整体流程中涉及到需要移动的主要实体对象创建任务序列。这样可以做到在同一个场景中实现多个场桥的并行操作,各个场桥执行各自的任务,互不干扰。此外,还需要一个总控制程序控制每个时间节点的任务执行情况,并控制场桥的三维动画。

业务流程

在这部分的仿真中主要业务流程聚焦于集装箱的移动。因此,最重要的就是集装箱所有权的流转。集装箱的所有权流转流程如下图所示:

集装箱对象流转过程

集装箱对象流转过程

对象结构

以下是这个仿真中主要涉及到的对象的结构

问题1场桥对象结构图

问题1堆场对象结构图

实现方法

堆场规模

对于堆场对象,由于它的功能主要是存放集装箱对象及其相关数据(比如对应位置的坐标),那么就还会出现一个问题,堆场的规模有多大?因此确定堆场的规模是一个必要的步骤。在创建堆场对象时需要确定所创建的堆场的规模,即行数、列数、高度。这样可以在创建堆场对象时就确定堆场的规模,方便后续的操作。

我的做法是首先确定堆场对象的占地大小集装箱层数,然后由相关数据去计算最多能摆放几行几列的集装箱。

  • 堆场占地大小方面,通过在创建对象时输入两点坐标来确定,根据两点连成的对角线构成一个矩形,从而确定堆场的占地面积。
  • 集装箱层数方面,通过在创建对象时输入一个数字来确定。根据这两个输入就就可以确定堆场的规模。

堆场布局计算

事件和任务

由于在这个仿真中需要移动的对象主要是场桥,因此每次循环执行任务的时候只需要操作场桥即可。

因此,我打算将场桥的任务序列作为一个队列,每次循环执行任务的时候,从对象的任务序列中取出第一个任务执行,执行完毕后判断是否满足任务执行完毕的条件,如果满足则删除这个任务,执行下一个任务。这样可以保证每次循环执行任务的时候,场桥对象能够按照次序执行任务。

执行任务的方法为 executeTask(dt) ,对象根据推进时间的长短 dt 执行任务。在 executeTask(dt) 中存放了处理任务的逻辑,包括判断任务类型、执行任务、删除任务等。

如果场景中存在多个场桥,只需要将这些对象添加到执行任务对象的列表中即可。主控程序每次循环执行任务时,会遍历这个对象列表,依次执行每个对象的任务。

提示

注意此处任务执行虽然在时间点上看是同时执行的,但是其实和对象所处的序列位置有关。

一个例子就是:假设两个对象同时需要抢占位置A,那么按照任务序列的顺序,先执行的对象会抢占到位置A,后执行的对象会抢占失败,尽管它们在同一时刻都在抢占位置A。因此,此处不是严格的同时执行,而是同一时刻按照任务序列的顺序执行。

业务流程

  1. 场桥首先从堆场中获取对应位置(行、列、高度)集装箱的坐标,并将吊具移动到堆场指定集装箱位置,抓取集装箱。集装箱所有权从堆场(cy.containers)转移到场桥吊具(rmg.attached)(通过解除表引用实现,将值设为 nil)。
  2. 场桥将集装箱移动到过道并放下集装箱。以同样的方式将集装箱所有权从场桥吊具(rmg.attached)移动到过道(rmg.stash),表明集装箱可以被提取。
  3. 如果有车辆将集装箱接走,则可以进一步将集装箱所有权从场桥过道(rmg.stash)移动到车辆上。

运行结果

场桥仿真

实现AGV到达至服务的全流程

问题描述

问题2描述

使用事件调度法实现以上流程的三维化形式

What's New

上一个仿真的实现是实现这个仿真的基础。相比于上一个仿真,这个仿真最为显著的改进体现在:

  • 使用面向对象编程模式,创建场桥、堆场(数据模型)、AGV、岸桥、船(数据模型)共4个类型的对象,并实现对象本体和其各部件的移动方法。
',42),C=e('
  • 延续面向事件的仿真的思路,实现了总控制流程,实现同一时刻对多个对象同时进行控制(主要通过对象的 executeTask(dt)maxStep() 及相关函数实现)。在面向对象的编程模式中,可以将 executeTask(dt)maxStep() 视为接口,主程序通过实现这两个接口,实现对对象的控制。(尽管lua中似乎没有这部分的概念)
  • 使用任务序列实现各个对象的流程,实现场桥和AGV之间、AGV和岸桥之间的相互等待,实现不同对象之间的任务协同。
  • 尝试将流程从堆场至AGV延伸至岸桥、船,实现两级排队等待。

对象设计

由于属性和函数实在太多,因此使用思维导图的形式展示对象的设计。

提示

此处占用篇幅较大,您也可以直接跳转到下一部分总体布局

堆场

堆场仍然作为数据模型。 堆场

场桥

场桥

AGV

AGV

岸桥

岸桥的代码和涉及结构主要衍生自堆场,因此后面不详细叙述。 岸桥

船对象的主要作用也是作为数据模型,设计思路同堆场。

船

总体布局

总体布局

总体流程

总体流程图

集装箱流转流程

相比于之前的仿真,这个仿真在流程上更进了一步,添加了AGV到达、排队的流程,还添加了岸桥服务、集装箱装船的流程。

流程分析

AGV出现后,场桥、岸桥和AGV之间的流程也变得更加复杂。首先,AGV的到达是随机的,因此可能造成排队现象。其次,AGV的到达会触发场桥和AGV的流程,而场桥和AGV的流程又会触发岸桥的流程。因此,这个仿真的流程是一个多级流程,需要考虑多个对象之间的流程协同。

特别是AGV和场桥之间的流程,其中存在AGV和场桥的相互等待。AGV到达的时候需要通知场桥提取货物。在场桥提取的过程中:

  • 场桥需要等待AGV到达指定位置后,才能将货物移动到AGV上
  • AGV需要等待场桥的抓取并将集装箱放在AGV上以后,才能将集装箱的所有权从场桥转移到AGV上

因此,AGV和场桥之间的流程是一个相互等待的流程。具体流程可以参考下图。

AGV和场桥相互等待的流程图

而岸桥的流程和场桥的流程类似,也是一个相互等待的流程。主要体现在:

  • 当AGV到达指定位置时,岸桥可能在服务别的AGV,此时AGV要进行等待
  • 当AGV刚进入岸桥的服务区域时,通知岸桥到达指定位置,如果岸桥先到达指定位置,则此时岸桥要进行等待

实现方法

排队流程的实现

AGV排队的情况我选择使用元胞自动机作为停车位的数据模型。其中,停车位的长度为:

',31),L=a("p",{class:"katex-block"},[a("span",{class:"katex-display"},[a("span",{class:"katex"},[a("span",{class:"katex-mathml"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[a("semantics",null,[a("mrow",null,[a("mtext",null,"停车位长度"),a("mo",null,"="),a("mtext",null,"对应数据模型中1个集装箱的长度"),a("mo",null,"+"),a("mtext",null,"集装箱间隔长度")]),a("annotation",{encoding:"application/x-tex"}," \\text{停车位长度}=\\text{对应数据模型中1个集装箱的长度}+\\text{集装箱间隔长度} ")])])]),a("span",{class:"katex-html","aria-hidden":"true"},[a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord text"},[a("span",{class:"mord cjk_fallback"},"停车位长度")]),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),a("span",{class:"mrel"},"="),a("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.7667em","vertical-align":"-0.0833em"}}),a("span",{class:"mord text"},[a("span",{class:"mord cjk_fallback"},"对应数据模型中"),a("span",{class:"mord"},"1"),a("span",{class:"mord cjk_fallback"},"个集装箱的长度")]),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),a("span",{class:"mbin"},"+"),a("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),a("span",{class:"base"},[a("span",{class:"strut",style:{height:"0.6833em"}}),a("span",{class:"mord text"},[a("span",{class:"mord cjk_fallback"},"集装箱间隔长度")])])])])])],-1),R=e('

由于AGV的长度比1个集装箱略长,因此需要占用2个停车位的长度。每次执行任务时,AGV会判断前方空间是否被阻塞,如果没被阻塞则向前移动。如果前方位置为目标bay,则前进后等待场桥作业,获取集装箱后继续以元胞为单位向前移动直到离开。场桥部分排队和岸桥部分排队原理也相同。

AGV排队示意图

AGV元胞自动机排队模型示意图

事件调度法的实现

在之前的仿真中,我使用了非固定步长的时间推进法来实现仿真。在这个仿真中,我使用了事件调度法来实现仿真。相比于时间推进法,事件调度法的特点是可以准确地将事件推进到发生的时刻,从而执行对应事件。

你可能注意到了对象设计部分我将 executeTask()maxstep() 标记为(interface),这是由于为了计算准确的推进时间,我需要在每个对象中实现 executeTask()maxstep() 方法。其中,executeTask() 方法用于执行任务,maxstep() 方法用于计算距离到达下一个事件的发生时间(当前任务还剩多久能执行完),然后得到最大能够推进的时间,再去跟系统运行得到的间隔时间dt进行比较得到最大的推进时间。

我认为课件中的下面这张图能够很好地表示如何使用事件调度法来进行仿真并刷新场景。其中,第一行指的是仿真的业务流程,第二行Refresh部分指的是刷新场景。

事件调度法示意图

运行结果

注意

由于以下部分内容均为动图且图片体积较大。由于本站托管于GitHubPage,因此如果您没有的特殊网络环境可能会造成动图加载缓慢甚至加载失败。

提示

如果您直接观看动图的时候动图区域出现了摩尔纹,可以尝试将动图点开放大看,再看看是否有改善。

场桥运行过程 场桥运行过程1

场桥运行过程2

岸桥运行过程 岸桥运行过程

总体运行过程 总体运行过程1

总体运行过程2

',15);function D(W,F){const s=E("RouterLink");return T(),j("div",null,[S,a("blockquote",null,[a("p",null,[t("如果不了解面向对象编程,可以参考"),M(s,{to:"/notes/oop.html"},{default:N(()=>[t("通用知识-面向对象编程")]),_:1})])]),C,L,R])}const P=B(q,[["render",D],["__file","cy-simulation.html.vue"]]);export{P as default}; diff --git a/assets/cy-simulation.html-x04vq-Lr.js b/assets/cy-simulation.html-x04vq-Lr.js new file mode 100644 index 00000000..9cb8f68a --- /dev/null +++ b/assets/cy-simulation.html-x04vq-Lr.js @@ -0,0 +1 @@ +import{_ as r,a as h,b as c,c as d,d as l,e as p,f as m,g as u,h as f,i as g,j as b,k as y,l as v,m as w,n as x,o as _,p as k,q as G,r as j,s as T,t as A,u as q,v as V}from"./Result-All2-cnkq843b.js";import{_ as I,r as n,o as P,c as R,a as e,b as t,d as i,w as S,e as a}from"./app-LOf__QKq.js";const C={},M=a('

Port AGV Service Process 3D Simulation Approach

This train of thought is for reference only.

Banner

Simulating the process of a container terminal is a complex task that involves many factors and entities. This article mainly introduces the approach to simulate the process of AGV receiving services from the yard crane to accepting services from the quay crane using MicroCityWeb.

Implementing Yard Crane Handling of Containers

Problem 1 Screenshot

Overall Approach

Implementing the handling of containers by the yard crane is the first step in simulating the yard. I plan to use an object-oriented approach for this part, abstracting the yard crane and the yard as objects.

Overall Structure

The specific idea is to treat the yard as a data model that stores various data, such as container entities, coordinates of containers in corresponding positions (rows, columns, heights), etc. The yard crane is treated as an operator responsible for the yard crane's 3D animation and management of data in the yard object.

The benefit of doing this is to decouple the yard crane from the yard, making it easier to expand in the future. In addition, if the object's properties are well considered, multiple objects can be easily created in the same scene to simulate multiple yard cranes operating in the yard.

Events and Tasks

I plan to create task sequences for the main entity objects that require movement in the overall process. This allows for parallel operations of multiple yard cranes in the same scene, with each yard crane performing its own tasks without interfering with each other. In addition, a central control program is needed to control the execution of tasks at each time node and the 3D animation of the yard crane.

Business Process

In this simulation, the main focus of the business process is the movement of containers. Therefore, the most important aspect is the transfer of ownership of containers. The process flow of container ownership transfer is shown in the following diagram:

Container Object Process Flow

Container Object Process Flow

Object Structure

The following are the structures of the main objects involved in this simulation.

Structure of Yard Crane Object

Structure of Yard Object

Implementation Approach

Yard Size

For the yard object, since its main function is to store container objects and related data (such as coordinates of corresponding positions), we need to determine the size of the yard. Therefore, determining the size of the yard is a necessary step. When creating the yard object, we need to determine the size of the yard, including the number of rows, columns, and height. This facilitates subsequent operations.

My approach is to first determine the area occupied by the yard and the number of container layers. Based on the relevant data, we can calculate the maximum number of rows and columns that can be used to place containers.

  • Regarding the area occupied by the yard, it can be determined by inputting the coordinates of two points when creating the object. Based on the diagonal formed by connecting the two points, we can determine the area occupied by the yard.
  • As for the number of container layers, it can be determined by inputting a number when creating the object. Based on these two inputs, we can determine the size of the yard.

Yard Layout Calculation

Events and Tasks

Since the yard crane is the main object that needs to be moved in this simulation, we only need to operate the yard crane during each loop of task execution.

Therefore, I plan to treat the task sequence of the yard crane as a queue. During each loop of task execution, we take out the first task from the object's task sequence and execute it. After execution, we check if the task completion condition is met. If so, we delete the task and move on to the next one. This ensures that the yard crane objects execute tasks in order during each loop of task execution.

The method for executing tasks is executeTask(dt), where the object executes tasks based on the duration dt. The executeTask(dt) function contains the logic for processing tasks, including task type determination, task execution, and task deletion.

If there are multiple yard cranes in the scene, simply add these objects to the list of objects executing tasks. During each loop of task execution, the main control program will iterate through this list of objects and execute tasks for each object.

',30),O={class:"hint-container tip"},L=a('

Tips

Note that although the task execution appears to be simultaneous in terms of time, it actually depends on the sequence position of the objects.

One example is: suppose two objects need to occupy position A at the same time. According to the order of the task sequence, the object that is executed first will occupy position A, while the object that is executed later will fail to occupy it, even though they are both trying to occupy position A at the same moment. Therefore, it is not strictly simultaneous execution here, but sequential execution according to the task sequence at the same time.

Business Process

  1. The yard crane first obtains the coordinates of the corresponding position (row, column, height) of the container from the yard and moves the spreader to the designated position in the yard to grab the container. The ownership of the container is transferred from the yard (cy.containers) to the yard crane spreader (rmg.attached) (by removing the table reference, setting the value to nil).
  2. The yard crane moves the container to the aisle and releases it there. In the same way, the ownership of the container is transferred from the yard crane spreader (rmg.attached) to the aisle (rmg.stash), indicating that the container can be picked up.
  3. If there is a vehicle that takes away the container, the ownership of the container can be further transferred from the aisle of the yard crane (rmg.stash) to the vehicle.

Results

Yard Crane Simulation

Implementation of the Whole Process from AGV Arrival to Service

Problem Description

Problem 2 Description

Implement the three-dimensional representation of the process above using event scheduling method.

What's New

The implementation of the previous simulation serves as the foundation for this simulation. Compared to the previous simulation, the most significant improvement in this simulation is:

  • Using the object-oriented programming paradigm to create objects of four types: yard crane, yard (data model), AGV, quay crane, and ship (data model), and implement the movement methods for the objects and their components.
',14),D=a('
  • Continuing with the idea of event-driven simulation, the overall control process is implemented to control multiple objects simultaneously at the same time (primarily achieved through the object's executeTask(dt) and maxStep() functions). In the object-oriented programming paradigm, executeTask(dt) and maxStep() can be seen as interfaces. The main program controls the objects by implementing these two interfaces. (Although Lua seems to lack this concept.)
  • Using task sequences to implement the flow of each object, achieving mutual waiting between the yard crane and AGV, and between the AGV and quay crane, and coordinating tasks between different objects.
  • Attempting to extend the flow from the yard to the AGV, and then to the quay crane and ship, implementing two-level queuing and waiting.

Object Design

Due to the large number of attributes and functions, the design of objects is presented in the form of a mind map.

Tips

This section takes up a lot of space. You can also directly jump to the next section Overall Layout.

',4),Y=a('

Yard

The yard remains as the data model. Yard

Yard Crane

Yard Crane

AGV

AGV

Quay Crane

The code and structures involving the quay crane are derived mainly from the yard, so they will not be described in detail later. Quay Crane

Ship

The ship object also serves as a data model, designed similarly to the yard.

Ship

Overall Layout

Overall Layout

Overall Process

Overall Process Diagram

Container Flow Process

Compared to the previous simulation, this simulation goes further in terms of the process. It adds the flow of AGV arrival and queuing, as well as the service of the quay crane and container loading onto the ship.

Process Analysis

With the introduction of AGVs, the flow between the yard crane, quay crane, and AGV has becomes more complex. First, the arrival of AGVs is random, which may cause queuing. Second, the arrival of AGVs triggers the flows of the yard crane and AGV, which in turn trigger the flow of the quay crane. Therefore, the flow of this simulation is a multi-level flow that needs to consider the coordination between multiple objects.

Especially in the process between AGV and RMG, there is a mutual waiting between AGV and RMG. When the AGV arrives, it needs to notify the RMG to extract the cargo. In the process of extraction by the RMG:

  • The RMG needs to wait for the AGV to arrive at the designated position before it can move the cargo onto the AGV.
  • The AGV needs to wait for the RMG to grab the container and place it on the AGV before transferring the ownership of the container from the RMG to the AGV.

Therefore, the process between the AGV and the RMG is a mutually waiting process. The specific process can be referred to in the diagram below.

Process Diagram of Mutual Waiting between AGV and RMG

The process of the quay crane is similar to that of the RMG, which is also a mutually waiting process. The main points are:

  • When the AGV arrives at the designated position, the quay crane may be serving other AGVs, so the AGV has to wait.
  • When the AGV just enters the service area of the quay crane, it notifies the quay crane to reach the designated position. If the quay crane arrives at the designated position first, it has to wait.

Implementation Method

Implementation of Queuing Process

For AGV queuing, I chose to use cellular automaton as the data model of parking spaces. The length of each parking space is:

',27),W=e("p",{class:"katex-block"},[e("span",{class:"katex-display"},[e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[e("semantics",null,[e("mrow",null,[e("mtext",null,"Length of Parking Space"),e("mo",null,"="),e("mtext",null,"Length of 1 Container in the data model"),e("mo",null,"+"),e("mtext",null,"Gap between containers")]),e("annotation",{encoding:"application/x-tex"}," \\text{Length of Parking Space} = \\text{Length of 1 Container in the data model} + \\text{Gap between containers} ")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),e("span",{class:"mord text"},[e("span",{class:"mord"},"Length of Parking Space")]),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),e("span",{class:"mrel"},"="),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),e("span",{class:"mord text"},[e("span",{class:"mord"},"Length of 1 Container in the data model")]),e("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),e("span",{class:"mbin"},"+"),e("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.8889em","vertical-align":"-0.1944em"}}),e("span",{class:"mord text"},[e("span",{class:"mord"},"Gap between containers")])])])])])],-1),z=a('

Since the length of the AGV is slightly longer than that of 1 container, it needs to occupy the length of 2 parking spaces. When executing a task, the AGV checks if the space ahead is blocked, and if not, it moves forward. If the space ahead is the target bay, it moves forward and waits for the RMG operation, then continues to move forward in terms of cells until it leaves. The queuing principles for the RMG and quay crane are also the same.

AGV Queuing Diagram

Diagram of AGV Cellular Automaton Queuing Model

Implementation of Event Scheduling Method

In the previous simulation, I used a variable step size to advance the time for simulation. In this simulation, I used the event scheduling method to accurately advance the events to their occurrence time for execution.

You may have noticed that in the Object Design section, executeTask() and maxstep() are marked as (interface). This is because to calculate the accurate advancement time, I need to implement executeTask() and maxstep() methods in each object. The executeTask() method is used to execute the task, and the maxstep() method is used to calculate the time remaining for the current task to be completed and obtain the maximum advancement time based on that, and then compare it with the interval time dt obtained from the system execution to get the maximum advancement time.

I believe that the following diagram from the course can effectively represent how the event scheduling method is used for simulation and scene refreshing. The first row refers to the business process of simulation, and the Refresh part in the second row refers to refreshing the scene.

Event Scheduling Diagram

Results

Note

The following parts contain animated GIFs, and the images have a large file size. Since this site is hosted on GitHub Pages, if you don't have a special network environment, the animated GIFs may load slowly or even fail to load.

Tips

If you encounter moiré patterns in the animated GIFs while directly viewing them, you can try opening them to enlarge the view and see if there is any improvement.

RMG running process RMG Running Process 1

RMG Running Process 2

Quay crane running process Quay Crane Running Process

Overall running process Overall Running Process 1

Overall Running Process 2

',15),B={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},F=e("strong",null,"feedback",-1);function E(N,Q){const s=n("RouterLink"),o=n("ExternalLinkIcon");return P(),R("div",null,[M,e("div",O,[L,e("blockquote",null,[e("p",null,[t("If you are not familiar with object-oriented programming, you can refer to "),i(s,{to:"/en/notes/oop.html"},{default:S(()=>[t("General Knowledge - Object-Oriented Programming")]),_:1}),t(".")])]),D]),Y,W,z,e("blockquote",null,[e("p",null,[t("This post is translated using ChatGPT, please "),e("a",B,[F,i(o)]),t(" if any omissions.")])])])}const K=I(C,[["render",E],["__file","cy-simulation.html.vue"]]);export{K as default}; diff --git a/assets/data_visualization-NDO9FqTF.js b/assets/data_visualization-NDO9FqTF.js new file mode 100644 index 00000000..d68f8f64 --- /dev/null +++ b/assets/data_visualization-NDO9FqTF.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/world_countries-K0FhRM3K.png",t="/MicroCityNotes/assets/data_visualization-HBg0SLXW.png";export{s as _,t as a}; diff --git a/assets/debug.html-80fcUM2q.js b/assets/debug.html-80fcUM2q.js new file mode 100644 index 00000000..cef5ec30 --- /dev/null +++ b/assets/debug.html-80fcUM2q.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-3520e381","path":"/en/notes/debug.html","title":"Debugging","lang":"en-US","frontmatter":{"description":"This page introduces the functions and shortcuts related to debugging in MicroCity Web. Clearing Output Right-clicking on the output area allows you to enter commands. Entering ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/debug.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/debug.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Debugging"}],["meta",{"property":"og:description","content":"This page introduces the functions and shortcuts related to debugging in MicroCity Web. Clearing Output Right-clicking on the output area allows you to enter commands. Entering ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:54:45.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:54:45.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Debugging\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:54:45.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Clearing Output","slug":"clearing-output","link":"#clearing-output","children":[]},{"level":2,"title":"Debugger Shortcuts","slug":"debugger-shortcuts","link":"#debugger-shortcuts","children":[]},{"level":2,"title":"Debug Commands","slug":"debug-commands","link":"#debug-commands","children":[{"level":3,"title":"Watching Variables","slug":"watching-variables","link":"#watching-variables","children":[]},{"level":3,"title":"Stack Trace","slug":"stack-trace","link":"#stack-trace","children":[]},{"level":3,"title":"Running Status","slug":"running-status","link":"#running-status","children":[]}]},{"level":2,"title":"Other Debug Commands","slug":"other-debug-commands","link":"#other-debug-commands","children":[]}],"git":{"updatedTime":1701060885000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/debug.md","autoDesc":true}');export{t as data}; diff --git a/assets/debug.html-Pj0zKe-s.js b/assets/debug.html-Pj0zKe-s.js new file mode 100644 index 00000000..3047edb5 --- /dev/null +++ b/assets/debug.html-Pj0zKe-s.js @@ -0,0 +1,17 @@ +import{_ as i,r as s,o as c,c as u,a as n,b as e,d as t,w as r,e as l}from"./app-LOf__QKq.js";const d={},p=l(`

Debugging

This page introduces the functions and shortcuts related to debugging in MicroCity Web.

Clearing Output

Right-clicking on the output area allows you to enter commands. Entering print() clears the content of the output area.

Debugger Shortcuts

During the process of debugging a program, especially at breakpoints, you can use F9 (Step Over), F10 (Step Into), and F11 (Step Out) to control the program execution.

  • F9 Step Over: Skips the current line and executes the next line.
  • F10 Step Into: Enters the current line. If the current line is a function call, it enters the function body.
  • F11 Step Out: Exits the current function and executes the next line after the function call.

Debug Commands

Watching Variables

Use the debug.watch() command in the console to monitor variables.

For example, if you want to monitor the value of variable a during debugging, you can use the debug.watch('a') command.

Right-clicking on the output area allows you to enter commands.

Stack Trace

The debug.traceback() function can print the current stack trace information.

function myFunction()
+    -- Some code logic
+    print(debug.traceback("Stack trace"))
+    -- Other code logic
+end
+
+function anotherFunction()
+    myFunction()
+end
+
+anotherFunction()
+

Output:

Stack trace
+stack traceback:
+[string "function myFunction() ..."]:3: in function 'myFunction'
+[string "function myFunction() ..."]:8: in function 'anotherFunction'
+[string "function myFunction() ..."]:11: in main chunk
+

Running Status

`,18),h=n("code",null,"debug.debug()",-1),g=n("li",null,[n("code",null,"debug.pause()"),e(" pauses program execution. The Run button ▶️ at the top will light up, and the Pause button ⏸️ will turn off.")],-1),b=n("h2",{id:"other-debug-commands",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#other-debug-commands","aria-hidden":"true"},"#"),e(" Other Debug Commands")],-1),m=n("p",null,"Most of Lua's Debug functions are applicable to MicroCity Web. For reference, please see:",-1),k={href:"https://www.lua.org/manual/5.4/manual.html#6.10",target:"_blank",rel:"noopener noreferrer"},f={href:"https://www.runoob.com/lua/lua-debug.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},_=n("strong",null,"feedback",-1);function x(y,w){const o=s("RouterLink"),a=s("ExternalLinkIcon");return c(),u("div",null,[p,n("ul",null,[n("li",null,[h,e(" enters Debug mode. It is often used to enter Debug mode during program execution. If you want to start in Debug mode, you can right-click the top ▶️ button. See "),t(o,{to:"/en/notes/web-ui.html#program-control"},{default:r(()=>[e("User Interface Introduction - Running Status")]),_:1}),e(" for details.")]),g]),b,m,n("ul",null,[n("li",null,[n("a",k,[e("The Debug Library | Lua 5.4 Reference Manual"),t(a)])]),n("li",null,[n("a",f,[e("Lua Debugging | Runoob Tutorial"),t(a)])])]),n("blockquote",null,[n("p",null,[e("This post is translated using ChatGPT, please "),n("a",v,[_,t(a)]),e(" if any omissions.")])])])}const S=i(d,[["render",x],["__file","debug.html.vue"]]);export{S as default}; diff --git a/assets/debug.html-YQ27enDU.js b/assets/debug.html-YQ27enDU.js new file mode 100644 index 00000000..24a5e8b2 --- /dev/null +++ b/assets/debug.html-YQ27enDU.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-44b81126","path":"/notes/debug.html","title":"调试相关","lang":"zh-CN","frontmatter":{"description":"本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。 清除输出 右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。 调试器快捷键 在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。 F9 Step Over:跳过当前...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/debug.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/debug.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"调试相关"}],["meta",{"property":"og:description","content":"本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。 清除输出 右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。 调试器快捷键 在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。 F9 Step Over:跳过当前..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-20T15:27:43.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T15:27:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"调试相关\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T15:27:43.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"清除输出","slug":"清除输出","link":"#清除输出","children":[]},{"level":2,"title":"调试器快捷键","slug":"调试器快捷键","link":"#调试器快捷键","children":[]},{"level":2,"title":"Debug命令","slug":"debug命令","link":"#debug命令","children":[{"level":3,"title":"监视变量","slug":"监视变量","link":"#监视变量","children":[]},{"level":3,"title":"堆栈跟踪","slug":"堆栈跟踪","link":"#堆栈跟踪","children":[]},{"level":3,"title":"运行状态","slug":"运行状态","link":"#运行状态","children":[]}]},{"level":2,"title":"其他调试命令","slug":"其他调试命令","link":"#其他调试命令","children":[]}],"git":{"updatedTime":1700494063000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"notes/debug.md","autoDesc":true}');export{e as data}; diff --git a/assets/debug.html-mpPtl8CL.js b/assets/debug.html-mpPtl8CL.js deleted file mode 100644 index e6a9939e..00000000 --- a/assets/debug.html-mpPtl8CL.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-44b81126","path":"/notes/debug.html","title":"调试相关","lang":"zh-CN","frontmatter":{"description":"本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。 清除输出 右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。 调试器快捷键 在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。 F9 Step Over:跳过当前...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/debug.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"调试相关"}],["meta",{"property":"og:description","content":"本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。 清除输出 右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。 调试器快捷键 在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。 F9 Step Over:跳过当前..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-20T15:27:43.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T15:27:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"调试相关\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T15:27:43.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"清除输出","slug":"清除输出","link":"#清除输出","children":[]},{"level":2,"title":"调试器快捷键","slug":"调试器快捷键","link":"#调试器快捷键","children":[]},{"level":2,"title":"Debug命令","slug":"debug命令","link":"#debug命令","children":[{"level":3,"title":"监视变量","slug":"监视变量","link":"#监视变量","children":[]},{"level":3,"title":"堆栈跟踪","slug":"堆栈跟踪","link":"#堆栈跟踪","children":[]},{"level":3,"title":"运行状态","slug":"运行状态","link":"#运行状态","children":[]}]},{"level":2,"title":"其他调试命令","slug":"其他调试命令","link":"#其他调试命令","children":[]}],"git":{"updatedTime":1700494063000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"notes/debug.md","autoDesc":true}');export{e as data}; diff --git a/assets/debug.html-yFg7dMCo.js b/assets/debug.html-vC47hElk.js similarity index 98% rename from assets/debug.html-yFg7dMCo.js rename to assets/debug.html-vC47hElk.js index 4fa3d4e6..203deb93 100644 --- a/assets/debug.html-yFg7dMCo.js +++ b/assets/debug.html-vC47hElk.js @@ -1,4 +1,4 @@ -import{_ as o,r as t,o as c,c as u,a as n,b as e,d as a,w as d,e as l}from"./app-DaLjD81q.js";const r={},p=l(`

调试相关

本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。

清除输出

右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。

调试器快捷键

在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。

  • F9 Step Over:跳过当前行,执行下一行
  • F10 Step Into:进入当前行,如果当前行是函数调用,则进入函数内部
  • F11 Step Out:跳出当前函数,执行函数调用的下一行

Debug命令

监视变量

在控制台使用 debug.watch() 命令监视变量。

例如,在调试的过程中想要监视 a 变量的值,可以使用 debug.watch('a') 命令。

右键输出区域可以输入命令

堆栈跟踪

使用 debug.traceback() 函数可以打印出当前的堆栈跟踪信息

function myFunction()
+import{_ as o,r as t,o as c,c as u,a as n,b as e,d as a,w as d,e as l}from"./app-LOf__QKq.js";const r={},p=l(`

调试相关

本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。

清除输出

右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。

调试器快捷键

在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。

  • F9 Step Over:跳过当前行,执行下一行
  • F10 Step Into:进入当前行,如果当前行是函数调用,则进入函数内部
  • F11 Step Out:跳出当前函数,执行函数调用的下一行

Debug命令

监视变量

在控制台使用 debug.watch() 命令监视变量。

例如,在调试的过程中想要监视 a 变量的值,可以使用 debug.watch('a') 命令。

右键输出区域可以输入命令

堆栈跟踪

使用 debug.traceback() 函数可以打印出当前的堆栈跟踪信息

function myFunction()
     -- 某些代码逻辑
     print(debug.traceback("Stack trace"))
     -- 其他代码逻辑
diff --git a/assets/edit_point-Z0R1Z63o.js b/assets/edit_point-Z0R1Z63o.js
new file mode 100644
index 00000000..ab98259b
--- /dev/null
+++ b/assets/edit_point-Z0R1Z63o.js
@@ -0,0 +1 @@
+const A="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARUlEQVR42mNkoBAwDjYD/v9HkmIkLI7NgP8wUTQDsIpT3wUDH4iEAKZXSDcALTAZcSpEs4lEF+CONiLDAHe0URiIg9EAAKjsHBHhPhnUAAAAAElFTkSuQmCC",s="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASUlEQVR42mNkoBAw0sCA//+RpAnKY1fwH2Y0YXlauABuPtweHPI4A5EiA9A1EeJT1wBCTsYqTw0DSIs27AaQkHBo4QLKAMUGAAAloi4RJpgTVwAAAABJRU5ErkJggg==",t="/MicroCityNotes/assets/new_shapes-RVv9IgwR.png",o="/MicroCityNotes/assets/shapes_files-ShfoHRZo.png",e="/MicroCityNotes/assets/shapes_menu-aime3jTY.png",i="/MicroCityNotes/assets/close_save_shapes-bnfKINWq.png",a="/MicroCityNotes/assets/edit_shape-3r72h2cB.png",p="/MicroCityNotes/assets/edit_point-krh9tqYD.png";export{a as _,p as a,A as b,s as c,t as d,o as e,e as f,i as g};
diff --git a/assets/event-scheduling-en.html-gy_6i2Mu.js b/assets/event-scheduling-en.html-gy_6i2Mu.js
deleted file mode 100644
index c0abccdf..00000000
--- a/assets/event-scheduling-en.html-gy_6i2Mu.js
+++ /dev/null
@@ -1 +0,0 @@
-const e=JSON.parse('{"key":"v-1ae81571","path":"/notes/event-scheduling-en.html","title":"Discrete Event Simulation and Program Control","lang":"zh-CN","frontmatter":{"description":"Coroutines MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling. coroutine.queue Adds a function or coroutine to the ...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling-en.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"Discrete Event Simulation and Program Control"}],["meta",{"property":"og:description","content":"Coroutines MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling. coroutine.queue Adds a function or coroutine to the ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-06-03T03:38:14.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"Discrete Event Simulation and Program Control"}],["meta",{"property":"article:modified_time","content":"2023-06-03T03:38:14.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Discrete Event Simulation and Program Control\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-06-03T03:38:14.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Coroutines","slug":"coroutines","link":"#coroutines","children":[{"level":3,"title":"coroutine.queue","slug":"coroutine-queue","link":"#coroutine-queue","children":[]},{"level":3,"title":"coroutine.qtime","slug":"coroutine-qtime","link":"#coroutine-qtime","children":[]},{"level":3,"title":"Example","slug":"example","link":"#example","children":[]}]},{"level":2,"title":"Random Numbers","slug":"random-numbers","link":"#random-numbers","children":[{"level":3,"title":"Creating a Random Seed","slug":"creating-a-random-seed","link":"#creating-a-random-seed","children":[]},{"level":3,"title":"Example","slug":"example-1","link":"#example-1","children":[]}]},{"level":2,"title":"Program Control","slug":"program-control","link":"#program-control","children":[]}],"git":{"updatedTime":1685763494000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/event-scheduling-en.md","autoDesc":true}');export{e as data};
diff --git a/assets/event-scheduling.html-7ezvA1AX.js b/assets/event-scheduling.html-3ysZ_CTt.js
similarity index 99%
rename from assets/event-scheduling.html-7ezvA1AX.js
rename to assets/event-scheduling.html-3ysZ_CTt.js
index 36798c59..afec7087 100644
--- a/assets/event-scheduling.html-7ezvA1AX.js
+++ b/assets/event-scheduling.html-3ysZ_CTt.js
@@ -1,4 +1,4 @@
-import{_ as e}from"./CommandBar-jgj8yIQP.js";import{_ as t,r as o,o as p,c,a as n,b as i,d as l,e as s}from"./app-DaLjD81q.js";const u={},d=s(`

离散事件模拟和程序控制

本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。

协程

MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 部分了解相关概念。

coroutine.queue

将函数或协程添加到协程队列中等待

coroutine.queue(rt, f|co [, 参数列表...])
+import{_ as e}from"./CommandBar-jgj8yIQP.js";import{_ as t,r as o,o as p,c,a as n,b as i,d as l,e as s}from"./app-LOf__QKq.js";const u={},d=s(`

离散事件模拟和程序控制

本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。

协程

MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 部分了解相关概念。

coroutine.queue

将函数或协程添加到协程队列中等待

coroutine.queue(rt, f|co [, 参数列表...])
 

参数

参数含义
rt相对当前队列的时间,要求大于等于0。换句话说,也就是再过rt执行输入的函数或协程
f/co函数或协程。如果是函数,只需要输入函数名

coroutine.qtime

获取当前队列的时间

local time = coroutine.qtime()
 

示例

此处提供两个示例

  1. 协程添加任务:使用协程添加任务,并在函数中显示当前队列时间
  2. 车辆移动:使用协程实现以真实世界的时间刷新场景

协程添加任务

这个示例中展示了如何使用协程添加任务,并在函数中显示当前队列时间

function Show()
     print("当前时间:",coroutine.qtime())
diff --git a/assets/event-scheduling-en.html-gRProVKn.js b/assets/event-scheduling.html-UZg_AtmL.js
similarity index 99%
rename from assets/event-scheduling-en.html-gRProVKn.js
rename to assets/event-scheduling.html-UZg_AtmL.js
index 8fc170a8..ba1d67d0 100644
--- a/assets/event-scheduling-en.html-gRProVKn.js
+++ b/assets/event-scheduling.html-UZg_AtmL.js
@@ -1,4 +1,4 @@
-import{_ as e}from"./CommandBar-jgj8yIQP.js";import{_ as t,r as o,o as c,c as p,d as i,w as u,e as s,a as n}from"./app-DaLjD81q.js";const l={},r=s(`

Discrete Event Simulation and Program Control

Coroutines

MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling.

coroutine.queue

Adds a function or coroutine to the coroutine queue for execution after a specified relative time.

coroutine.queue(rt, f|co [, argument list...])
+import{_ as e}from"./CommandBar-jgj8yIQP.js";import{_ as t,r as o,o as c,c as p,d as i,w as u,e as s,a as n}from"./app-LOf__QKq.js";const l={},r=s(`

Discrete Event Simulation and Program Control

Coroutines

MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling.

coroutine.queue

Adds a function or coroutine to the coroutine queue for execution after a specified relative time.

coroutine.queue(rt, f|co [, argument list...])
 

Parameters

ParameterDescription
rtRelative time from the current queue. It should be greater than or equal to 0. In other words, it specifies the time after which the input function or coroutine will be executed.
f/coFunction or coroutine. If it's a function, you only need to input the function name.

coroutine.qtime

Retrieves the current time of the queue.

local time = coroutine.qtime()
 

Example

Here are two examples provided:

Adding Coroutines to the Queue

This example demonstrates how to add coroutines to the queue and display the current queue time within the function.

function Show()
     print("Current time:", coroutine.qtime())
@@ -59,4 +59,4 @@ coroutine.qu
 -- Output a random number
 print(seed:random())
 

Program Control

Program control, in this context, mainly refers to controlling the execution of a program using the buttons in the user interface, including pause, resume, and stop.

`,32),d=n("p",null,[n("img",{src:e,alt:"Command Bar"})],-1),m=n("p",null,"Command Bar",-1),k=s(`

This mainly refers to the first three buttons in the command bar.

In MicroCityWeb, program control refers to the pause, resume, and stop of the 3D interface rendering implemented through the scene object. The specific function is as follows:

local state = scene.render()
-

Here, the return value of scene.render() is stored in the state variable. The state variable can be either true or false, representing the running or terminated state of the program (button 3 in the command bar).

Pausing the rendering of 3D objects is also achieved by calling scene.render(). If the refresh of 3D objects is implemented by continuously calling the scene.render() function and the refresh interval is not controlled by os.sleep(), it is possible to pause the rendering of the 3D interface at a certain state. This is because if os.sleep() is used to control the speed of 3D object movement and the pause button is clicked while the program is in the os.sleep() process, the program may not respond immediately, resulting in the pause button becoming ineffective. Therefore, it is recommended not to use os.sleep() for controlling the speed of 3D object movement, but to use other parameters to control the duration of advancement in order to control the speed of 3D object movement.

`,5);function h(v,b){const a=o("center");return c(),p("div",null,[r,i(a,null,{default:u(()=>[d,m]),_:1}),k])}const w=t(l,[["render",h],["__file","event-scheduling-en.html.vue"]]);export{w as default}; +

Here, the return value of scene.render() is stored in the state variable. The state variable can be either true or false, representing the running or terminated state of the program (button 3 in the command bar).

Pausing the rendering of 3D objects is also achieved by calling scene.render(). If the refresh of 3D objects is implemented by continuously calling the scene.render() function and the refresh interval is not controlled by os.sleep(), it is possible to pause the rendering of the 3D interface at a certain state. This is because if os.sleep() is used to control the speed of 3D object movement and the pause button is clicked while the program is in the os.sleep() process, the program may not respond immediately, resulting in the pause button becoming ineffective. Therefore, it is recommended not to use os.sleep() for controlling the speed of 3D object movement, but to use other parameters to control the duration of advancement in order to control the speed of 3D object movement.

`,5);function h(v,b){const a=o("center");return c(),p("div",null,[r,i(a,null,{default:u(()=>[d,m]),_:1}),k])}const w=t(l,[["render",h],["__file","event-scheduling.html.vue"]]);export{w as default}; diff --git a/assets/event-scheduling.html-_wHScoNu.js b/assets/event-scheduling.html-_wHScoNu.js new file mode 100644 index 00000000..39480a82 --- /dev/null +++ b/assets/event-scheduling.html-_wHScoNu.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0ceacb2b","path":"/notes/event-scheduling.html","title":"离散事件模拟和程序控制","lang":"zh-CN","frontmatter":{"description":"本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。 协程 MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 (./timelapse#事件调度法) 部分了解相关概念。 coroutine.queue 将函数或协程添加...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/event-scheduling.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"离散事件模拟和程序控制"}],["meta",{"property":"og:description","content":"本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。 协程 MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 (./timelapse#事件调度法) 部分了解相关概念。 coroutine.queue 将函数或协程添加..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"离散事件模拟和程序控制\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"协程","slug":"协程","link":"#协程","children":[{"level":3,"title":"coroutine.queue","slug":"coroutine-queue","link":"#coroutine-queue","children":[]},{"level":3,"title":"coroutine.qtime","slug":"coroutine-qtime","link":"#coroutine-qtime","children":[]},{"level":3,"title":"示例","slug":"示例","link":"#示例","children":[]}]},{"level":2,"title":"随机数","slug":"随机数","link":"#随机数","children":[{"level":3,"title":"创建随机数种子","slug":"创建随机数种子","link":"#创建随机数种子","children":[]},{"level":3,"title":"示例","slug":"示例-1","link":"#示例-1","children":[]}]},{"level":2,"title":"程序控制","slug":"程序控制","link":"#程序控制","children":[]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":6}]},"filePathRelative":"notes/event-scheduling.md","autoDesc":true}');export{e as data}; diff --git a/assets/event-scheduling.html-o4tYPrMB.js b/assets/event-scheduling.html-o4tYPrMB.js deleted file mode 100644 index a45e8c3d..00000000 --- a/assets/event-scheduling.html-o4tYPrMB.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-0ceacb2b","path":"/notes/event-scheduling.html","title":"离散事件模拟和程序控制","lang":"zh-CN","frontmatter":{"description":"本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。 协程 MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 (./timelapse#事件调度法) 部分了解相关概念。 coroutine.queue 将函数或协程添加...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"离散事件模拟和程序控制"}],["meta",{"property":"og:description","content":"本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。 协程 MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 (./timelapse#事件调度法) 部分了解相关概念。 coroutine.queue 将函数或协程添加..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"离散事件模拟和程序控制"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"离散事件模拟和程序控制\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"协程","slug":"协程","link":"#协程","children":[{"level":3,"title":"coroutine.queue","slug":"coroutine-queue","link":"#coroutine-queue","children":[]},{"level":3,"title":"coroutine.qtime","slug":"coroutine-qtime","link":"#coroutine-qtime","children":[]},{"level":3,"title":"示例","slug":"示例","link":"#示例","children":[]}]},{"level":2,"title":"随机数","slug":"随机数","link":"#随机数","children":[{"level":3,"title":"创建随机数种子","slug":"创建随机数种子","link":"#创建随机数种子","children":[]},{"level":3,"title":"示例","slug":"示例-1","link":"#示例-1","children":[]}]},{"level":2,"title":"程序控制","slug":"程序控制","link":"#程序控制","children":[]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"notes/event-scheduling.md","autoDesc":true}');export{e as data}; diff --git a/assets/event-scheduling.html-py4kt8T8.js b/assets/event-scheduling.html-py4kt8T8.js new file mode 100644 index 00000000..976ff741 --- /dev/null +++ b/assets/event-scheduling.html-py4kt8T8.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-63796ad2","path":"/en/notes/event-scheduling.html","title":"Discrete Event Simulation and Program Control","lang":"en-US","frontmatter":{"description":"Coroutines MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling. coroutine.queue Adds a function or coroutine to the ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/event-scheduling.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Discrete Event Simulation and Program Control"}],["meta",{"property":"og:description","content":"Coroutines MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling. coroutine.queue Adds a function or coroutine to the ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Discrete Event Simulation and Program Control\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Coroutines","slug":"coroutines","link":"#coroutines","children":[{"level":3,"title":"coroutine.queue","slug":"coroutine-queue","link":"#coroutine-queue","children":[]},{"level":3,"title":"coroutine.qtime","slug":"coroutine-qtime","link":"#coroutine-qtime","children":[]},{"level":3,"title":"Example","slug":"example","link":"#example","children":[]}]},{"level":2,"title":"Random Numbers","slug":"random-numbers","link":"#random-numbers","children":[{"level":3,"title":"Creating a Random Seed","slug":"creating-a-random-seed","link":"#creating-a-random-seed","children":[]},{"level":3,"title":"Example","slug":"example-1","link":"#example-1","children":[]}]},{"level":2,"title":"Program Control","slug":"program-control","link":"#program-control","children":[]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/event-scheduling.md","autoDesc":true}');export{e as data}; diff --git a/assets/fixed_increment_advance-iwDvqivb.js b/assets/fixed_increment_advance-iwDvqivb.js new file mode 100644 index 00000000..9bc41829 --- /dev/null +++ b/assets/fixed_increment_advance-iwDvqivb.js @@ -0,0 +1 @@ +const e="/MicroCityNotes/assets/fixed_increment_advance-ufFIwQjw.png";export{e as _}; diff --git a/assets/grid_attributes-xxRYXyrC.js b/assets/grid_attributes-xxRYXyrC.js new file mode 100644 index 00000000..46361a27 --- /dev/null +++ b/assets/grid_attributes-xxRYXyrC.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/new_grid-4i1mP770.png",t="/MicroCityNotes/assets/grid_structure-vhTlEgf-.png",i="/MicroCityNotes/assets/grid_menu-7jPQkAi1.png",o="/MicroCityNotes/assets/close_save_grid-mxdTfyrH.png",e="/MicroCityNotes/assets/grid_selection-bdt61Cd7.png",r="/MicroCityNotes/assets/grid_attributes-e5wa0ZGb.png";export{e as _,r as a,s as b,t as c,i as d,o as e}; diff --git a/assets/index.html-2U8qpeQG.js b/assets/index.html-2U8qpeQG.js new file mode 100644 index 00000000..000d6f42 --- /dev/null +++ b/assets/index.html-2U8qpeQG.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-147825fb","path":"/docs/","title":"MicroCity Desktop 文档","lang":"zh-CN","frontmatter":{"description":"目录 1 Introduction; 1.1 MicroCity的功能 (1.1whatmicrocitycando.md); 2 入门指南; 2.1 显示世界地图 (2.1showingaworldmap.md); 2.2 搜索国家 (2.2searchingfor_countries.md); 3 用户界面; 3.1 UI概览 (3.1uiover...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"MicroCity Desktop 文档"}],["meta",{"property":"og:description","content":"目录 1 Introduction; 1.1 MicroCity的功能 (1.1whatmicrocitycando.md); 2 入门指南; 2.1 显示世界地图 (2.1showingaworldmap.md); 2.2 搜索国家 (2.2searchingfor_countries.md); 3 用户界面; 3.1 UI概览 (3.1uiover..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"MicroCity Desktop 文档\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"目录","slug":"目录","link":"#目录","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":7}]},"filePathRelative":"docs/readme.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-8_XflqQA.js b/assets/index.html-8_XflqQA.js deleted file mode 100644 index 018accb4..00000000 --- a/assets/index.html-8_XflqQA.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,r as i,o as r,c as _,a as t,b as l,d as e,w as n}from"./app-DaLjD81q.js";const d={},c=t("h1",{id:"microcity文档",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#microcity文档","aria-hidden":"true"},"#"),l(" MicroCity文档")],-1),u=t("h2",{id:"目录",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#目录","aria-hidden":"true"},"#"),l(" 目录")],-1),h={href:"http://microcity.github.io",target:"_blank",rel:"noopener noreferrer"};function m(f,p){const o=i("RouterLink"),a=i("ExternalLinkIcon");return r(),_("div",null,[c,u,t("ul",null,[t("li",null,[l("1 Introduction 介绍 "),t("ul",null,[t("li",null,[e(o,{to:"/docs/1.1_what_microcity_can_do.html"},{default:n(()=>[l("1.1 What MicroCity can Do")]),_:1}),l(" MicroCity能干什么")])])]),t("li",null,[l("2 Getting Started 开始使用 "),t("ul",null,[t("li",null,[e(o,{to:"/docs/2.1_showing_a_world_map.html"},{default:n(()=>[l("2.1 Showing a World Map")]),_:1}),l(" 展示世界地图")]),t("li",null,[e(o,{to:"/docs/2.2_searching_for_countries.html"},{default:n(()=>[l("2.2 Searching for Countries")]),_:1}),l(" 寻找国家")])])]),t("li",null,[l("3 User Interfaces 用户界面 "),t("ul",null,[t("li",null,[e(o,{to:"/docs/3.1_ui_overview.html"},{default:n(()=>[l("3.1 UI Overview")]),_:1}),l(" 用户界面概览")]),t("li",null,[e(o,{to:"/docs/3.2_vector_shapes.html"},{default:n(()=>[l("3.2 Vector Shapes")]),_:1}),l(" 矢量图")]),t("li",null,[e(o,{to:"/docs/3.3_raster_grids.html"},{default:n(()=>[l("3.3 Raster Grids")]),_:1}),l(" 栅格图")]),t("li",null,[e(o,{to:"/docs/3.4_3d_scenes.html"},{default:n(()=>[l("3.4 3D Scenes")]),_:1}),l(" 3D场景")]),t("li",null,[e(o,{to:"/docs/3.5_tables.html"},{default:n(()=>[l("3.5 Tables")]),_:1}),l(" 表格")]),t("li",null,[e(o,{to:"/docs/3.6_maps_and_layers.html"},{default:n(()=>[l("3.6 Maps and Layers")]),_:1}),l(" 地图和图层")]),t("li",null,[e(o,{to:"/docs/3.7_modules.html"},{default:n(()=>[l("3.7 Modules")]),_:1}),l(" 拓展模块")])])]),t("li",null,[l("4 Scripting Interfaces 脚本接口 "),t("ul",null,[t("li",null,[e(o,{to:"/docs/4.1_si_overview.html"},{default:n(()=>[l("4.1 SI Overview")]),_:1}),l(" 脚本概览")]),t("li",null,[e(o,{to:"/docs/4.2_ui_control.html"},{default:n(()=>[l("4.2 UI Control")]),_:1}),l(" 控制用户界面")]),t("li",null,[e(o,{to:"/docs/4.3_shapes_and_tables.html"},{default:n(()=>[l("4.3 Shapes and Tables")]),_:1}),l(" 矢量图形和表格")]),t("li",null,[e(o,{to:"/docs/4.4_grids.html"},{default:n(()=>[l("4.4 Grids")]),_:1}),l(" 栅格图形")]),t("li",null,[e(o,{to:"/docs/4.5_3d_scenes.html"},{default:n(()=>[l("4.5 3D Scenes")]),_:1}),l(" 3D场景")]),t("li",null,[e(o,{to:"/docs/4.6_networks.html"},{default:n(()=>[l("4.6 Networks")]),_:1}),l(" 网络")]),t("li",null,[e(o,{to:"/docs/4.7_des_simulations.html"},{default:n(()=>[l("4.7 Discrete Event Simulations")]),_:1}),l(" 离散事件模拟")]),t("li",null,[e(o,{to:"/docs/4.8_mixed_integer_programming.html"},{default:n(()=>[l("4.8 Mixed Integer Programming")]),_:1}),l(" 混合整数线性规划")])])])]),t("blockquote",null,[t("p",null,[l("声明:本网站文档部分内容来自"),t("a",h,[l("microcity.github.io"),e(a)]),l(",版权归原作者所有。")])])])}const v=s(d,[["render",m],["__file","index.html.vue"]]);export{v as default}; diff --git a/assets/index.html-92lUUdK6.js b/assets/index.html-92lUUdK6.js new file mode 100644 index 00000000..b5d7636c --- /dev/null +++ b/assets/index.html-92lUUdK6.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-31b53ad6","path":"/images/doc/","title":"","lang":"zh-CN","frontmatter":{"description":"This folder contains images used by documentation pages.","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/images/doc/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:description","content":"This folder contains images used by documentation pages."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"images/doc/readme.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-HwGLrUxL.js b/assets/index.html-HwGLrUxL.js deleted file mode 100644 index c5484972..00000000 --- a/assets/index.html-HwGLrUxL.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,r as i,o as u,c as d,a as e,d as l,w as n,b as t}from"./app-DaLjD81q.js";const r={},h=e("h1",{id:"笔记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#笔记","aria-hidden":"true"},"#"),t(" 笔记")],-1),c=e("h2",{id:"通用知识",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#通用知识","aria-hidden":"true"},"#"),t(" 通用知识")],-1),_=e("h2",{id:"microcity-桌面版",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity-桌面版","aria-hidden":"true"},"#"),t(" MicroCity(桌面版)")],-1),m=e("h2",{id:"microcityweb",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcityweb","aria-hidden":"true"},"#"),t(" MicroCityWeb")],-1),f=e("h2",{id:"思路",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#思路","aria-hidden":"true"},"#"),t(" 思路")],-1),b={href:"https://github.com/sunzhuo",target:"_blank",rel:"noopener noreferrer"};function p(x,y){const o=i("RouterLink"),a=i("ExternalLinkIcon");return u(),d("div",null,[h,c,e("ul",null,[e("li",null,[l(o,{to:"/notes/lua.html"},{default:n(()=>[t("Lua语言快速上手")]),_:1})]),e("li",null,[l(o,{to:"/notes/versions.html"},{default:n(()=>[t("MicroCity的版本")]),_:1})]),e("li",null,[l(o,{to:"/notes/timelapse.html"},{default:n(()=>[t("时间推进法")]),_:1})]),e("li",null,[l(o,{to:"/notes/oop.html"},{default:n(()=>[t("面向对象编程")]),_:1})]),e("li",null,[l(o,{to:"/notes/tools.html"},{default:n(()=>[t("有关工具")]),_:1})])]),_,e("ul",null,[e("li",null,[l(o,{to:"/notes/visualization.html"},{default:n(()=>[t("结果可视化")]),_:1})]),e("li",null,[l(o,{to:"/notes/network.html"},{default:n(()=>[t("操作网络")]),_:1})]),e("li",null,[l(o,{to:"/notes/lp.html"},{default:n(()=>[t("模型求解")]),_:1})])]),m,e("ul",null,[e("li",null,[l(o,{to:"/notes/web-ui.html"},{default:n(()=>[t("用户界面简介")]),_:1}),t(" ["),l(o,{to:"/notes/web-ui-en.html"},{default:n(()=>[t("EN")]),_:1}),t("]")]),e("li",null,[l(o,{to:"/notes/3d-scene.html"},{default:n(()=>[t("3D 场景")]),_:1}),t(" ["),l(o,{to:"/notes/3d-scene-en.html"},{default:n(()=>[t("EN")]),_:1}),t("]")]),e("li",null,[l(o,{to:"/notes/3d-objects.html"},{default:n(()=>[t("3D 对象")]),_:1}),t(" ["),l(o,{to:"/notes/3d-objects-en.html"},{default:n(()=>[t("EN")]),_:1}),t("]")]),e("li",null,[l(o,{to:"/notes/event-scheduling.html"},{default:n(()=>[t("离散事件模拟和程序控制")]),_:1}),t(" ["),l(o,{to:"/notes/event-scheduling-en.html"},{default:n(()=>[t("EN")]),_:1}),t("]")]),e("li",null,[l(o,{to:"/notes/mip.html"},{default:n(()=>[t("混合整数规划")]),_:1}),t(" ["),l(o,{to:"/notes/mip-en.html"},{default:n(()=>[t("EN")]),_:1}),t("]")]),e("li",null,[l(o,{to:"/notes/debug.html"},{default:n(()=>[t("调试相关")]),_:1})])]),f,e("ul",null,[e("li",null,[l(o,{to:"/notes/warehouse-simulation.html"},{default:n(()=>[t("仓库仿真")]),_:1})]),e("li",null,[l(o,{to:"/notes/plots.html"},{default:n(()=>[t("通用绘图代码")]),_:1})]),e("li",null,[l(o,{to:"/notes/cy-simulation.html"},{default:n(()=>[t("港口AGV服务流程三维仿真思路")]),_:1})])]),e("blockquote",null,[e("p",null,[t("本页目录所指的笔记内容适用于相应版本的MicroCity。特别感谢在编写和整理的过程中 "),e("a",b,[t("孙卓老师(MicroCity作者)"),l(a)]),t(" 给予的指导和帮助。")])])])}const w=s(r,[["render",p],["__file","index.html.vue"]]);export{w as default}; diff --git a/assets/index.html-IqC-sAFX.js b/assets/index.html-IqC-sAFX.js new file mode 100644 index 00000000..0afb2233 --- /dev/null +++ b/assets/index.html-IqC-sAFX.js @@ -0,0 +1 @@ +import{_ as s,r as i,o as u,c as r,a as t,d as l,w as n,b as e}from"./app-LOf__QKq.js";const d={},h=t("h1",{id:"笔记",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#笔记","aria-hidden":"true"},"#"),e(" 笔记")],-1),c=t("h2",{id:"通用知识",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#通用知识","aria-hidden":"true"},"#"),e(" 通用知识")],-1),_=t("h2",{id:"microcity-桌面版",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#microcity-桌面版","aria-hidden":"true"},"#"),e(" MicroCity(桌面版)")],-1),m=t("h2",{id:"microcityweb",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#microcityweb","aria-hidden":"true"},"#"),e(" MicroCityWeb")],-1),f=t("h2",{id:"思路",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#思路","aria-hidden":"true"},"#"),e(" 思路")],-1),b={href:"https://github.com/sunzhuo",target:"_blank",rel:"noopener noreferrer"};function p(x,y){const o=i("RouterLink"),a=i("ExternalLinkIcon");return u(),r("div",null,[h,c,t("ul",null,[t("li",null,[l(o,{to:"/notes/lua.html"},{default:n(()=>[e("Lua语言快速上手")]),_:1})]),t("li",null,[l(o,{to:"/notes/versions.html"},{default:n(()=>[e("MicroCity的版本")]),_:1})]),t("li",null,[l(o,{to:"/notes/timelapse.html"},{default:n(()=>[e("时间推进法")]),_:1})]),t("li",null,[l(o,{to:"/notes/oop.html"},{default:n(()=>[e("面向对象编程")]),_:1})]),t("li",null,[l(o,{to:"/notes/tools.html"},{default:n(()=>[e("有关工具")]),_:1})])]),_,t("ul",null,[t("li",null,[l(o,{to:"/notes/visualization.html"},{default:n(()=>[e("结果可视化")]),_:1})]),t("li",null,[l(o,{to:"/notes/network.html"},{default:n(()=>[e("操作网络")]),_:1})]),t("li",null,[l(o,{to:"/notes/lp.html"},{default:n(()=>[e("模型求解")]),_:1})])]),m,t("ul",null,[t("li",null,[l(o,{to:"/notes/web-ui.html"},{default:n(()=>[e("用户界面简介")]),_:1})]),t("li",null,[l(o,{to:"/notes/3d-scene.html"},{default:n(()=>[e("3D 场景")]),_:1})]),t("li",null,[l(o,{to:"/notes/3d-objects.html"},{default:n(()=>[e("3D 对象")]),_:1})]),t("li",null,[l(o,{to:"/notes/event-scheduling.html"},{default:n(()=>[e("离散事件模拟和程序控制")]),_:1})]),t("li",null,[l(o,{to:"/notes/mip.html"},{default:n(()=>[e("混合整数规划")]),_:1})]),t("li",null,[l(o,{to:"/notes/debug.html"},{default:n(()=>[e("调试相关")]),_:1})])]),f,t("ul",null,[t("li",null,[l(o,{to:"/notes/warehouse-simulation.html"},{default:n(()=>[e("仓库仿真")]),_:1})]),t("li",null,[l(o,{to:"/notes/plots.html"},{default:n(()=>[e("通用绘图代码")]),_:1})]),t("li",null,[l(o,{to:"/notes/cy-simulation.html"},{default:n(()=>[e("港口AGV服务流程三维仿真思路")]),_:1})])]),t("blockquote",null,[t("p",null,[e("本页目录所指的笔记内容适用于相应版本的MicroCity。特别感谢在编写和整理的过程中 "),t("a",b,[e("孙卓老师(MicroCity作者)"),l(a)]),e(" 给予的指导和帮助。")])])])}const w=s(d,[["render",p],["__file","index.html.vue"]]);export{w as default}; diff --git a/assets/index.html-NfP7JmCD.js b/assets/index.html-NfP7JmCD.js new file mode 100644 index 00000000..ad7b8f7f --- /dev/null +++ b/assets/index.html-NfP7JmCD.js @@ -0,0 +1 @@ +import{_ as a,r as s,o as r,c,a as e,b as t,d as l,w as o}from"./app-LOf__QKq.js";const d={},_=e("h1",{id:"microcity-desktop-documents",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity-desktop-documents","aria-hidden":"true"},"#"),t(" MicroCity Desktop Documents")],-1),u=e("h2",{id:"contents",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contents","aria-hidden":"true"},"#"),t(" Contents")],-1),h={href:"https://github.com/microcity/Desktop",target:"_blank",rel:"noopener noreferrer"};function m(f,p){const n=s("RouterLink"),i=s("ExternalLinkIcon");return r(),c("div",null,[_,u,e("ul",null,[e("li",null,[t("1 Introduction "),e("ul",null,[e("li",null,[l(n,{to:"/en/docs/1.1_what_microcity_can_do.html"},{default:o(()=>[t("1.1 What MicroCity can Do")]),_:1})])])]),e("li",null,[t("2 Getting Started "),e("ul",null,[e("li",null,[l(n,{to:"/en/docs/2.1_showing_a_world_map.html"},{default:o(()=>[t("2.1 Showing a World Map")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/2.2_searching_for_countries.html"},{default:o(()=>[t("2.2 Searching for Countries")]),_:1})])])]),e("li",null,[t("3 User Interfaces "),e("ul",null,[e("li",null,[l(n,{to:"/en/docs/3.1_ui_overview.html"},{default:o(()=>[t("3.1 UI Overview")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/3.2_vector_shapes.html"},{default:o(()=>[t("3.2 Vector Shapes")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/3.3_raster_grids.html"},{default:o(()=>[t("3.3 Raster Grids")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/3.4_3d_scenes.html"},{default:o(()=>[t("3.4 3D Scenes")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/3.5_tables.html"},{default:o(()=>[t("3.5 Tables")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/3.6_maps_and_layers.html"},{default:o(()=>[t("3.6 Maps and Layers")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/3.7_modules.html"},{default:o(()=>[t("3.7 Modules")]),_:1})])])]),e("li",null,[t("4 Scripting Interfaces "),e("ul",null,[e("li",null,[l(n,{to:"/en/docs/4.1_si_overview.html"},{default:o(()=>[t("4.1 SI Overview")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.2_ui_control.html"},{default:o(()=>[t("4.2 UI Control")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.3_shapes_and_tables.html"},{default:o(()=>[t("4.3 Shapes and Tables")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.4_grids.html"},{default:o(()=>[t("4.4 Grids")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.5_3d_scenes.html"},{default:o(()=>[t("4.5 3D Scenes")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.6_networks.html"},{default:o(()=>[t("4.6 Networks")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.7_des_simulations.html"},{default:o(()=>[t("4.7 Discrete Event Simulations")]),_:1})]),e("li",null,[l(n,{to:"/en/docs/4.8_mixed_integer_programming.html"},{default:o(()=>[t("4.8 Mixed Integer Programming")]),_:1})])])])]),e("blockquote",null,[e("p",null,[t("Statement: Part of the content of the documents on this website comes from "),e("a",h,[t("MicroCity Desktop"),l(i)]),t(", and the copyright belongs to the original author.")])])])}const k=a(d,[["render",m],["__file","index.html.vue"]]);export{k as default}; diff --git a/assets/index.html-WLZyFhZW.js b/assets/index.html-WLZyFhZW.js new file mode 100644 index 00000000..2cdf2383 --- /dev/null +++ b/assets/index.html-WLZyFhZW.js @@ -0,0 +1 @@ +import{_ as i,r as _,o as u,c as a,a as l,b as t,d as e,w as n}from"./app-LOf__QKq.js";const d={},c=l("h1",{id:"microcity-desktop-文档",tabindex:"-1"},[l("a",{class:"header-anchor",href:"#microcity-desktop-文档","aria-hidden":"true"},"#"),t(" MicroCity Desktop 文档")],-1),r=l("h2",{id:"目录",tabindex:"-1"},[l("a",{class:"header-anchor",href:"#目录","aria-hidden":"true"},"#"),t(" 目录")],-1),h={href:"https://github.com/microcity/Desktop",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},f=l("strong",null,"反馈",-1);function p(k,g){const o=_("RouterLink"),s=_("ExternalLinkIcon");return u(),a("div",null,[c,r,l("ul",null,[l("li",null,[t("1 Introduction "),l("ul",null,[l("li",null,[e(o,{to:"/docs/1.1_what_microcity_can_do.html"},{default:n(()=>[t("1.1 MicroCity的功能")]),_:1})])])]),l("li",null,[t("2 入门指南 "),l("ul",null,[l("li",null,[e(o,{to:"/docs/2.1_showing_a_world_map.html"},{default:n(()=>[t("2.1 显示世界地图")]),_:1})]),l("li",null,[e(o,{to:"/docs/2.2_searching_for_countries.html"},{default:n(()=>[t("2.2 搜索国家")]),_:1})])])]),l("li",null,[t("3 用户界面 "),l("ul",null,[l("li",null,[e(o,{to:"/docs/3.1_ui_overview.html"},{default:n(()=>[t("3.1 UI概览")]),_:1})]),l("li",null,[e(o,{to:"/docs/3.2_vector_shapes.html"},{default:n(()=>[t("3.2 矢量形状")]),_:1})]),l("li",null,[e(o,{to:"/docs/3.3_raster_grids.html"},{default:n(()=>[t("3.3 栅格图层")]),_:1})]),l("li",null,[e(o,{to:"/docs/3.4_3d_scenes.html"},{default:n(()=>[t("3.4 3D场景")]),_:1})]),l("li",null,[e(o,{to:"/docs/3.5_tables.html"},{default:n(()=>[t("3.5 表格")]),_:1})]),l("li",null,[e(o,{to:"/docs/3.6_maps_and_layers.html"},{default:n(()=>[t("3.6 地图和图层")]),_:1})]),l("li",null,[e(o,{to:"/docs/3.7_modules.html"},{default:n(()=>[t("3.7 模块")]),_:1})])])]),l("li",null,[t("4 脚本接口 "),l("ul",null,[l("li",null,[e(o,{to:"/docs/4.1_si_overview.html"},{default:n(()=>[t("4.1 接口概览")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.2_ui_control.html"},{default:n(()=>[t("4.2 UI控制")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.3_shapes_and_tables.html"},{default:n(()=>[t("4.3 形状和表格")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.4_grids.html"},{default:n(()=>[t("4.4 栅格图层")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.5_3d_scenes.html"},{default:n(()=>[t("4.5 3D场景")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.6_networks.html"},{default:n(()=>[t("4.6 网络")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.7_des_simulations.html"},{default:n(()=>[t("4.7 离散事件仿真")]),_:1})]),l("li",null,[e(o,{to:"/docs/4.8_mixed_integer_programming.html"},{default:n(()=>[t("4.8 混合整数规划")]),_:1})])])])]),l("blockquote",null,[l("p",null,[t("声明:本网站文档中的部分内容来源于"),l("a",h,[t("MicroCity Desktop"),e(s)]),t(",版权归原作者所有。")])]),l("blockquote",null,[l("p",null,[t("这篇文章使用ChatGPT翻译自其他语言,如果有问题请在"),l("a",m,[f,e(s)]),t("页面提交反馈。")])])])}const b=i(d,[["render",p],["__file","index.html.vue"]]);export{b as default}; diff --git a/assets/index.html-WsgEQayQ.js b/assets/index.html-WsgEQayQ.js new file mode 100644 index 00000000..6dbab05b --- /dev/null +++ b/assets/index.html-WsgEQayQ.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-8daa1a0e","path":"/","title":"首页","lang":"zh-CN","frontmatter":{"home":true,"title":"首页","actions":[{"text":"桌面版 文档","link":"/docs/","type":"secondary"},{"text":"学习笔记","link":"/notes/","type":"primary"}],"features":[{"title":"文档和搜索 🔍","details":"桌面版文档内容搬运自 MicroCity 项目文档并稍作适应性修改,在这里可以使用网站提供的搜索功能快速查找并跳转至内容"},{"title":"学习笔记 📔","details":"除了文档,还有 MicroCity Web/Desktop 使用和学习过程中的一些踩坑总结和记录,帮助你尽可能多地避开天坑"},{"title":"高颜值,流畅 ✨","details":"VuePress 驱动的独立网站,提供流畅阅读和文档参考体验。支持以 PWA 方式安装为应用,随时查阅,不受网络限制"}],"head":[["meta",{"name":"description","content":"MicroCity学习笔记,提供流畅舒适的文档搜索和学习体验。可以使用网站提供的搜索功能快速查找并跳转至内容。除了文档,还有MicroCity使用和学习过程中的一些踩坑总结和记录,帮助你尽可能多地避坑。"}],["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"首页"}],["meta",{"property":"og:description","content":"开始使用MicroCity Web 1. 打开MicroCity Web (https://microcity.gitee.io/),默认加载方块旋转的示例代码。 2. 点击运行!Play (./images/note/play.svg)按钮运行代码 3. 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用技..."}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:49:40.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"首页"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:49:40.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"首页\\",\\"description\\":\\"开始使用MicroCity Web 1. 打开MicroCity Web (https://microcity.gitee.io/),默认加载方块旋转的示例代码。 2. 点击运行!Play (./images/note/play.svg)按钮运行代码 3. 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用技...\\"}"]],"description":"开始使用MicroCity Web 1. 打开MicroCity Web (https://microcity.gitee.io/),默认加载方块旋转的示例代码。 2. 点击运行!Play (./images/note/play.svg)按钮运行代码 3. 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用技..."},"headers":[{"level":2,"title":"开始使用MicroCity Web","slug":"开始使用microcity-web","link":"#开始使用microcity-web","children":[]},{"level":2,"title":"开始使用MicroCity Desktop","slug":"开始使用microcity-desktop","link":"#开始使用microcity-desktop","children":[]},{"level":2,"title":"MicroCityNotes 仓库","slug":"microcitynotes-仓库","link":"#microcitynotes-仓库","children":[]}],"git":{"updatedTime":1701060580000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":30}]},"filePathRelative":"README.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-YVKYSuDE.js b/assets/index.html-YVKYSuDE.js new file mode 100644 index 00000000..bde118d9 --- /dev/null +++ b/assets/index.html-YVKYSuDE.js @@ -0,0 +1 @@ +const t=JSON.parse(`{"key":"v-2d0a870d","path":"/en/","title":"Home Page","lang":"en-US","frontmatter":{"home":true,"title":"Home Page","actions":[{"text":"Desktop docs","link":"./docs/","type":"secondary"},{"text":"Learning notes","link":"./notes/","type":"primary"}],"features":[{"title":"Doc and Search 🔍","details":"The desktop documentation is adapted from MicroCity's project docs with slight modifications. Quickly search and navigate content using the website's search functionality."},{"title":"Learning Notes 📔","details":"In addition to docs, find summaries of pitfalls in using and learning MicroCity Web/Desktop. These notes aim to help you avoid as many pitfalls as possible."},{"title":"Stylish and Smooth ✨","details":"VuePress powers this standalone site for a seamless reading and documentation reference. Install it as a Progressive Web App (PWA) for anytime access, irrespective of network constraints."}],"head":[["meta",{"name":"description","content":"MicroCity learning notes provide a smooth and comfortable documentation search and learning experience. You can use the website's search functionality to quickly find and navigate to content. In addition to the documentation, there are also summaries and records of pitfalls encountered during the use and learning of MicroCity, helping you navigate as smoothly as possible."}],["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Home Page"}],["meta",{"property":"og:description","content":"Getting Started with MicroCity Web 1. Open MicroCity Web (https://microcity.gitee.io/), and the example code for rotating blocks will load by default. 2. Click the !Play (../ima..."}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:45:10.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:45:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"Home Page\\",\\"description\\":\\"Getting Started with MicroCity Web 1. Open MicroCity Web (https://microcity.gitee.io/), and the example code for rotating blocks will load by default. 2. Click the !Play (../ima...\\"}"]],"description":"Getting Started with MicroCity Web 1. Open MicroCity Web (https://microcity.gitee.io/), and the example code for rotating blocks will load by default. 2. Click the !Play (../ima..."},"headers":[{"level":2,"title":"Getting Started with MicroCity Web","slug":"getting-started-with-microcity-web","link":"#getting-started-with-microcity-web","children":[]},{"level":2,"title":"Getting Started with MicroCity Desktop","slug":"getting-started-with-microcity-desktop","link":"#getting-started-with-microcity-desktop","children":[]},{"level":2,"title":"MicroCityNotes Repository","slug":"microcitynotes-repository","link":"#microcitynotes-repository","children":[]}],"git":{"updatedTime":1701060310000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"en/README.md","autoDesc":true}`);export{t as data}; diff --git a/assets/index.html-a5Ef1Ykb.js b/assets/index.html-a5Ef1Ykb.js new file mode 100644 index 00000000..19c915c6 --- /dev/null +++ b/assets/index.html-a5Ef1Ykb.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-39540332","path":"/en/docs/","title":"MicroCity Desktop Documents","lang":"en-US","frontmatter":{"description":"Contents 1 Introduction; 1.1 What MicroCity can Do (1.1whatmicrocitycando.md); 2 Getting Started; 2.1 Showing a World Map (2.1showingaworldmap.md); 2.2 Searching for Countries (...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/docs/"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/docs/"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"MicroCity Desktop Documents"}],["meta",{"property":"og:description","content":"Contents 1 Introduction; 1.1 What MicroCity can Do (1.1whatmicrocitycando.md); 2 Getting Started; 2.1 Showing a World Map (2.1showingaworldmap.md); 2.2 Searching for Countries (..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-25T03:41:16.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-25T03:41:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"MicroCity Desktop Documents\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-25T03:41:16.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Contents","slug":"contents","link":"#contents","children":[]}],"git":{"updatedTime":1700883676000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/docs/readme.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-b5l2JDLj.js b/assets/index.html-b5l2JDLj.js new file mode 100644 index 00000000..8fd6677c --- /dev/null +++ b/assets/index.html-b5l2JDLj.js @@ -0,0 +1 @@ +import{_ as s,r as a,o as r,c as u,a as e,d as n,w as l,b as t}from"./app-LOf__QKq.js";const d={},c=e("h1",{id:"notes",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#notes","aria-hidden":"true"},"#"),t(" Notes")],-1),h=e("h2",{id:"general-knowledge",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#general-knowledge","aria-hidden":"true"},"#"),t(" General Knowledge")],-1),_=e("h2",{id:"microcity-desktop-version",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity-desktop-version","aria-hidden":"true"},"#"),t(" MicroCity (Desktop Version)")],-1),m=e("h2",{id:"microcityweb",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcityweb","aria-hidden":"true"},"#"),t(" MicroCityWeb")],-1),f=e("h2",{id:"ideas",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#ideas","aria-hidden":"true"},"#"),t(" Ideas")],-1),g={href:"https://github.com/sunzhuo",target:"_blank",rel:"noopener noreferrer"},p={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},b=e("strong",null,"feedback",-1);function k(w,x){const o=a("RouterLink"),i=a("ExternalLinkIcon");return r(),u("div",null,[c,h,e("ul",null,[e("li",null,[n(o,{to:"/en/notes/lua.html"},{default:l(()=>[t("Quick Start with Lua Language")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/versions.html"},{default:l(()=>[t("Versions of MicroCity")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/timelapse.html"},{default:l(()=>[t("Time Advancement Methods")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/oop.html"},{default:l(()=>[t("Object-oriented Programming")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/tools.html"},{default:l(()=>[t("Regarding Tools")]),_:1})])]),_,e("ul",null,[e("li",null,[n(o,{to:"/en/notes/visualization.html"},{default:l(()=>[t("Visualization of Results")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/network.html"},{default:l(()=>[t("Operating Networks")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/lp.html"},{default:l(()=>[t("Model Solving")]),_:1})])]),m,e("ul",null,[e("li",null,[n(o,{to:"/en/notes/web-ui.html"},{default:l(()=>[t("Introduction to User Interface")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/3d-scene.html"},{default:l(()=>[t("3D Scene")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/3d-objects.html"},{default:l(()=>[t("3D Objects")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/event-scheduling.html"},{default:l(()=>[t("Discrete Event Simulation and Program Control")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/mip.html"},{default:l(()=>[t("Mixed Integer Programming")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/debug.html"},{default:l(()=>[t("Debugging")]),_:1})])]),f,e("ul",null,[e("li",null,[n(o,{to:"/en/notes/warehouse-simulation.html"},{default:l(()=>[t("Warehouse Simulation")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/plots.html"},{default:l(()=>[t("General Drawing Code")]),_:1})]),e("li",null,[n(o,{to:"/en/notes/cy-simulation.html"},{default:l(()=>[t("Simulation Ideas for Port AGV Service Process")]),_:1})])]),e("blockquote",null,[e("p",null,[t("The notes referenced in this page directory apply to the corresponding versions of MicroCity. Special thanks to "),e("a",g,[t("Sun Zhuo (MicroCity author)"),n(i)]),t(" for the guidance and assistance during the writing and organizing process.")])]),e("blockquote",null,[e("p",null,[t("This post is translated using ChatGPT, please "),e("a",p,[b,n(i)]),t(" if any omissions.")])])])}const v=s(d,[["render",k],["__file","index.html.vue"]]);export{v as default}; diff --git a/assets/index.html-ciQEBxId.js b/assets/index.html-c3NKfYSn.js similarity index 76% rename from assets/index.html-ciQEBxId.js rename to assets/index.html-c3NKfYSn.js index 0f8baa48..ac5e5443 100644 --- a/assets/index.html-ciQEBxId.js +++ b/assets/index.html-c3NKfYSn.js @@ -1 +1 @@ -import{_ as e,o as t,c as n,a as o}from"./app-DaLjD81q.js";const s={},c=o("p",null,"This folder contains images used by documentation pages.",-1),a=[c];function _(i,r){return t(),n("div",null,a)}const l=e(s,[["render",_],["__file","index.html.vue"]]);export{l as default}; +import{_ as e,o as t,c as n,a as o}from"./app-LOf__QKq.js";const s={},c=o("p",null,"This folder contains images used by documentation pages.",-1),a=[c];function _(i,r){return t(),n("div",null,a)}const l=e(s,[["render",_],["__file","index.html.vue"]]);export{l as default}; diff --git a/assets/index.html-dxC6HmKS.js b/assets/index.html-dxC6HmKS.js new file mode 100644 index 00000000..c7ee4ee2 --- /dev/null +++ b/assets/index.html-dxC6HmKS.js @@ -0,0 +1,2 @@ +import{_ as l}from"./play-RaBYbg3m.js";import{_ as c}from"./icon_script_editor-ibm_2NsU.js";import{_ as h}from"./icon_microcity-Je85-7MO.js";import{_ as u,a as d}from"./icon_module-AxwvBQMt.js";import{_ as p,r as n,o as g,c as _,a as t,b as e,d as o,w as r,e as m}from"./app-LOf__QKq.js";const f={},y=t("h2",{id:"getting-started-with-microcity-web",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#getting-started-with-microcity-web","aria-hidden":"true"},"#"),e(" Getting Started with MicroCity Web")],-1),b={href:"https://microcity.gitee.io/",target:"_blank",rel:"noopener noreferrer"},k=t("li",null,[t("p",null,[e("Click the "),t("img",{src:l,alt:"Play"}),e(" button to run the code.")])],-1),w=t("li",null,[t("p",null,"The program will run, and you will see the blocks rotating in the right-hand view.")],-1),C=t("strong",null,"Learning Notes",-1),v=t("h2",{id:"getting-started-with-microcity-desktop",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#getting-started-with-microcity-desktop","aria-hidden":"true"},"#"),e(" Getting Started with MicroCity Desktop")],-1),M=t("p",null,[t("img",{src:"https://img.shields.io/github/v/release/microcity/Desktop",alt:"GitHub release (latest by date)"}),e(),t("img",{src:"https://img.shields.io/github/downloads/microcity/Desktop/latest/total",alt:"GitHub release (by tag)"})],-1),x={href:"https://github.com/microcity/Desktop/releases/latest",target:"_blank",rel:"noopener noreferrer"},N=t("strong",null,"Latest Version of MicroCity",-1),G=t("li",null,[t("p",null,[e("Open the "),t("img",{src:c,alt:"icon"}),t("strong",null,"ScriptEditor"),e(" and type:")])],-1),S=m(`
Print("hello, world!")
+
  1. Save the script as test.mcs and drag it into iconMicroCity.

  2. In the main interface of the program, go to the Modules tab on the left side, open icontest, and double-click on iconmain to execute the script you just wrote.

  3. The information about the execution of the script will be displayed in the Messages panel at the bottom of the program interface.

',2),H=t("strong",null,"MicroCity Documentation",-1),I={href:"https://microcity.github.io/",target:"_blank",rel:"noopener noreferrer"},D=t("h2",{id:"microcitynotes-repository",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#microcitynotes-repository","aria-hidden":"true"},"#"),e(" MicroCityNotes Repository")],-1),L=t("img",{src:"https://img.shields.io/github/last-commit/huuhghhgyg/MicroCityNotes",alt:"GitHub last commit"},null,-1),P=t("img",{src:"https://img.shields.io/github/actions/workflow/status/huuhghhgyg/MicroCityNotes/DeployPage.yml?branch=main",alt:"GitHub Workflow Status"},null,-1),T={href:"https://mcn.zhhuu.top",target:"_blank",rel:"noopener noreferrer"},V=t("img",{src:"https://api.netlify.com/api/v1/badges/fe05238c-93ee-44db-84cf-7f805d43520a/deploy-status",alt:"Netlify Status"},null,-1),q={href:"https://mcn.zhhuu.top",target:"_blank",rel:"noopener noreferrer"},E=t("strong",null,"Synchronized Site",-1),R={href:"https://github.com/huuhghhgyg/MicroCityNotes/pulls",target:"_blank",rel:"noopener noreferrer"},W={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues",target:"_blank",rel:"noopener noreferrer"},z={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},B=t("strong",null,"feedback",-1);function A(O,$){const i=n("ExternalLinkIcon"),s=n("RouterLink"),a=n("A2hs");return g(),_("div",null,[y,t("ol",null,[t("li",null,[t("p",null,[e("Open "),t("a",b,[e("MicroCity Web"),o(i)]),e(", and the example code for rotating blocks will load by default.")])]),k,w]),t("p",null,[e("If you want to learn more about how to use MicroCity Web and its advanced features, you can refer to the "),o(s,{to:"/en/notes/"},{default:r(()=>[C]),_:1}),e(" provided on this site.")]),v,M,t("ol",null,[t("li",null,[t("p",null,[e("Go to the MicroCity documentation repository to download the "),t("a",x,[N,o(i)]),e(".")])]),G]),S,t("p",null,[e("For more information on how to use MicroCity, you can refer to the documentation found on this site, which is a mirror of the documentation provided on GitHub: "),o(s,{to:"/en/docs/"},{default:r(()=>[H]),_:1}),e(". You can also refer to the documentation of MicroCtiy on GitHub at "),t("a",I,[e("MicroCity"),o(i)]),e(".")]),D,t("p",null,[L,e(),P,e(),t("a",T,[V,o(i)])]),o(a),t("p",null,[e("If users in China have difficulty accessing GitHub, they can also visit the "),t("a",q,[E,o(i)]),e(" hosted on Netlify.")]),t("p",null,[e("If you find any issues with the documentation or notes, please feel free to submit a "),t("a",R,[e("Pull Request"),o(i)]),e(" or provide "),t("a",W,[e("Issues"),o(i)]),e(" to help make it better😋.")]),t("blockquote",null,[t("p",null,[e("This post is translated using ChatGPT, please "),t("a",z,[B,o(i)]),e(" if any omissions.")])])])}const Q=p(f,[["render",A],["__file","index.html.vue"]]);export{Q as default}; diff --git a/assets/index.html-hYpF9QHg.js b/assets/index.html-hYpF9QHg.js new file mode 100644 index 00000000..a0d8c3fd --- /dev/null +++ b/assets/index.html-hYpF9QHg.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-cefc5a4a","path":"/en/notes/","title":"Notes","lang":"en-US","frontmatter":{"description":"General Knowledge Quick Start with Lua Language (./lua.md); Versions of MicroCity (./versions.md); Time Advancement Methods (./timelapse.md); Object-oriented Programming (./oop....","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Notes"}],["meta",{"property":"og:description","content":"General Knowledge Quick Start with Lua Language (./lua.md); Versions of MicroCity (./versions.md); Time Advancement Methods (./timelapse.md); Object-oriented Programming (./oop...."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:54:45.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:54:45.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Notes\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:54:45.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"General Knowledge","slug":"general-knowledge","link":"#general-knowledge","children":[]},{"level":2,"title":"MicroCity (Desktop Version)","slug":"microcity-desktop-version","link":"#microcity-desktop-version","children":[]},{"level":2,"title":"MicroCityWeb","slug":"microcityweb","link":"#microcityweb","children":[]},{"level":2,"title":"Ideas","slug":"ideas","link":"#ideas","children":[]}],"git":{"updatedTime":1701060885000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"en/notes/README.md","autoDesc":true}');export{e as data}; diff --git a/assets/index.html-hph7Dv3o.js b/assets/index.html-hph7Dv3o.js deleted file mode 100644 index 371700aa..00000000 --- a/assets/index.html-hph7Dv3o.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-67bbbff8","path":"/docs/imgs/","title":"","lang":"zh-CN","frontmatter":{"description":"This folder contains images used by documentation pages.","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/imgs/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:description","content":"This folder contains images used by documentation pages."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-11-25T05:19:50.000Z"}],["meta",{"property":"article:modified_time","content":"2022-11-25T05:19:50.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2022-11-25T05:19:50.000Z\\",\\"author\\":[]}"]]},"headers":[],"git":{"updatedTime":1669353590000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"docs/imgs/readme.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-ijEhgMTC.js b/assets/index.html-ijEhgMTC.js deleted file mode 100644 index c8fa3a2e..00000000 --- a/assets/index.html-ijEhgMTC.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-8daa1a0e","path":"/","title":"首页","lang":"zh-CN","frontmatter":{"home":true,"title":"首页","actions":[{"text":"桌面版 文档","link":"/docs/","type":"secondary"},{"text":"学习笔记","link":"/notes/","type":"primary"}],"features":[{"title":"文档和搜索 🔍","details":"桌面版文档内容搬运自 MicroCity 项目文档并稍作适应性修改,在这里可以使用网站提供的搜索功能快速查找并跳转至内容"},{"title":"学习笔记 📔","details":"除了文档,还有 MicroCity Web/Desktop 使用和学习过程中的一些踩坑总结和记录,帮助你尽可能多地避开天坑"},{"title":"高颜值,流畅 ✨","details":"VuePress 驱动的独立网站,提供流畅阅读和文档参考体验。支持以 PWA 方式安装为应用,随时查阅,不受网络限制"}],"head":[["meta",{"name":"description","content":"MicroCity学习笔记,提供流畅舒适的文档搜索和学习体验。可以使用网站提供的搜索功能快速查找并跳转至内容。除了文档,还有MicroCity使用和学习过程中的一些踩坑总结和记录,帮助你尽可能多地避坑。"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"首页"}],["meta",{"property":"og:description","content":"开始使用MicroCity Web 1. 打开MicroCity Web (https://microcity.gitee.io/),默认加载方块旋转的示例代码。 2. 点击运行!Play (./notes/images/play.svg)按钮运行代码 3. 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用..."}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-20T16:01:42.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"首页"}],["meta",{"property":"article:modified_time","content":"2023-11-20T16:01:42.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"首页\\",\\"description\\":\\"开始使用MicroCity Web 1. 打开MicroCity Web (https://microcity.gitee.io/),默认加载方块旋转的示例代码。 2. 点击运行!Play (./notes/images/play.svg)按钮运行代码 3. 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用...\\"}"]],"description":"开始使用MicroCity Web 1. 打开MicroCity Web (https://microcity.gitee.io/),默认加载方块旋转的示例代码。 2. 点击运行!Play (./notes/images/play.svg)按钮运行代码 3. 程序运行,看到右侧视图中方块旋转。 如果想要深入了解 MicroCity Web 的用法和使用..."},"headers":[{"level":2,"title":"开始使用MicroCity Web","slug":"开始使用microcity-web","link":"#开始使用microcity-web","children":[]},{"level":2,"title":"开始使用MicroCity Desktop","slug":"开始使用microcity-desktop","link":"#开始使用microcity-desktop","children":[]},{"level":2,"title":"MicroCityNotes 仓库","slug":"microcitynotes-仓库","link":"#microcitynotes-仓库","children":[]}],"git":{"updatedTime":1700496102000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":27}]},"filePathRelative":"README.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-lZExp6Yz.js b/assets/index.html-lZExp6Yz.js deleted file mode 100644 index 211476b4..00000000 --- a/assets/index.html-lZExp6Yz.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as a}from"./icon_script_editor-ibm_2NsU.js";import{_ as l}from"./icon_microcity-Je85-7MO.js";import{_ as d,a as p}from"./icon_module-AxwvBQMt.js";import{_ as h,r as i,o as g,c as u,a as t,b as e,d as o,w as r,e as _}from"./app-DaLjD81q.js";const m="data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='utf-8'?%3e%3c!--%20Generator:%20Adobe%20Illustrator%2016.0.0,%20SVG%20Export%20Plug-In%20.%20SVG%20Version:%206.00%20Build%200)%20--%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20version='1.1'%20id='图层_1'%20xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'%20xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'%20xmlns:svg='http://www.w3.org/2000/svg'%20inkscape:version='1.2.2%20(732a01da63,%202022-12-09)'%20sodipodi:docname='play.svg'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20x='0px'%20y='0px'%20width='24px'%20height='24px'%20viewBox='0%200%2024%2024'%20enable-background='new%200%200%2024%2024'%20xml:space='preserve'%3e%3csodipodi:namedview%20inkscape:cy='12.014337'%20inkscape:cx='8.0860215'%20inkscape:zoom='34.875'%20showgrid='false'%20borderopacity='0.25'%20bordercolor='%23000000'%20pagecolor='%23ffffff'%20id='namedview255'%20inkscape:current-layer='图层_1'%20inkscape:window-width='1920'%20inkscape:window-y='-8'%20inkscape:deskcolor='%23d1d1d1'%20inkscape:pagecheckerboard='0'%20inkscape:window-maximized='1'%20inkscape:pageopacity='0.0'%20inkscape:showpageshadow='2'%20inkscape:window-x='-8'%20inkscape:window-height='1017'%3e%3c/sodipodi:namedview%3e%3ctitle%20id='title249'%3eic_fluent_play_24_regular%3c/title%3e%3cdesc%20id='desc251'%3eCreated%20with%20Sketch.%3c/desc%3e%3cpath%20id='_xD83C__xDFA8_-Color'%20inkscape:highlight-color='%23000000'%20d='M6.34,2.275C5.253,1.673,3.884,2.066,3.282,3.153%20C3.097,3.487,3,3.862,3,4.243V19.76c0,1.242,1.007,2.25,2.25,2.25c0.381,0,0.756-0.098,1.09-0.281l14.008-7.76%20c1.088-0.603,1.479-1.972,0.879-3.059c-0.205-0.37-0.51-0.674-0.879-0.878L6.34,2.275z%20M19.914,11.637%20c0.201,0.362,0.07,0.819-0.293,1.02L5.613,20.415C5.502,20.477,5.377,20.51,5.25,20.51c-0.414,0-0.75-0.336-0.75-0.75V4.243%20c0-0.127,0.032-0.252,0.094-0.363c0.201-0.362,0.657-0.493,1.02-0.292l14.008,7.757C19.744,11.412,19.846,11.514,19.914,11.637z'/%3e%3c/svg%3e",y={},f=t("h2",{id:"开始使用microcity-web",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#开始使用microcity-web","aria-hidden":"true"},"#"),e(" 开始使用MicroCity Web")],-1),k={href:"https://microcity.gitee.io/",target:"_blank",rel:"noopener noreferrer"},w=t("li",null,[t("p",null,[e("点击运行"),t("img",{src:m,alt:"Play"}),e("按钮运行代码")])],-1),b=t("li",null,[t("p",null,"程序运行,看到右侧视图中方块旋转。")],-1),x=t("strong",null,"学习笔记",-1),v=t("h2",{id:"开始使用microcity-desktop",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#开始使用microcity-desktop","aria-hidden":"true"},"#"),e(" 开始使用MicroCity Desktop")],-1),C=t("p",null,[t("img",{src:"https://img.shields.io/github/v/release/microcity/Desktop",alt:"GitHub release (latest by date)"}),e(),t("img",{src:"https://img.shields.io/github/downloads/microcity/Desktop/latest/total",alt:"GitHub release (by tag)"})],-1),M={href:"https://github.com/microcity/Desktop/releases/latest",target:"_blank",rel:"noopener noreferrer"},D=t("strong",null,"MicroCity的最新版本",-1),G=t("li",null,[t("p",null,[e("打开 "),t("img",{src:a,alt:"icon"}),t("strong",null,"ScriptEditor"),e(" 并输入:")])],-1),N=_(`
Print("hello, world!")
-
  1. 将脚本另存为 test.mcs 并将其拖入 iconMicroCity

  2. 在程序主界面左侧转到 Modules 标签页,打开 icontest ,双击其中的 iconmain ,执行刚刚编写的脚本。

  3. 程序界面下方的 Messages 栏中会输出执行脚本的信息。

',2),V=t("strong",null,"MicroCity文档",-1),S={href:"https://microcity.github.io/",target:"_blank",rel:"noopener noreferrer"},E={id:"microcitynotes-仓库",tabindex:"-1"},H=t("a",{class:"header-anchor",href:"#microcitynotes-仓库","aria-hidden":"true"},"#",-1),L={href:"https://github.com/huuhghhgyg/MicroCityNotes",target:"_blank",rel:"noopener noreferrer"},P=t("img",{src:"https://img.shields.io/github/last-commit/huuhghhgyg/MicroCityNotes",alt:"GitHub last commit"},null,-1),B=t("img",{src:"https://img.shields.io/github/actions/workflow/status/huuhghhgyg/MicroCityNotes/DeployPage.yml?branch=main",alt:"GitHub Workflow Status"},null,-1),I={href:"https://app.netlify.com/sites/microcitynotes/deploys",target:"_blank",rel:"noopener noreferrer"},z=t("img",{src:"https://api.netlify.com/api/v1/badges/fe05238c-93ee-44db-84cf-7f805d43520a/deploy-status",alt:"Netlify Status"},null,-1),T={href:"https://mcn.zhhuu.top",target:"_blank",rel:"noopener noreferrer"},W=t("strong",null,"同步站点",-1),A={href:"https://github.com/huuhghhgyg/MicroCityNotes/pulls",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues",target:"_blank",rel:"noopener noreferrer"};function R($,F){const s=i("ExternalLinkIcon"),n=i("RouterLink"),c=i("A2hs");return g(),u("div",null,[f,t("ol",null,[t("li",null,[t("p",null,[e("打开"),t("a",k,[e("MicroCity Web"),o(s)]),e(",默认加载方块旋转的示例代码。")])]),w,b]),t("p",null,[e("如果想要深入了解 MicroCity Web 的用法和使用技巧,可以参阅本站提供的 "),o(n,{to:"/notes/"},{default:r(()=>[x]),_:1})]),v,C,t("ol",null,[t("li",null,[t("p",null,[e("转到MicroCity的文档仓库下载 "),t("a",M,[D,o(s)])])]),G]),N,t("p",null,[e("更多MicroCity的使用方法可以参考本站搬运自GitHub的文档:"),o(n,{to:"/docs/"},{default:r(()=>[V]),_:1}),e(",也可以参考 "),t("a",S,[e("MicroCtiy"),o(s)]),e(" 在GitHub上的文档。")]),t("h2",E,[H,e(),t("a",L,[e("MicroCityNotes"),o(s)]),e(" 仓库")]),t("p",null,[P,e(),B,e(),t("a",I,[z,o(s)])]),o(c),t("p",null,[e("国内用户如果不方便访问 GitHub 也可以访问本站在 Netlify 上搭建的 "),t("a",T,[W,o(s)])]),t("p",null,[e("如果发现文档或笔记有问题,欢迎 "),t("a",A,[e("Pull Request"),o(s)]),e(" 或者提供 "),t("a",q,[e("Issues"),o(s)]),e(" 让它变得更完善😋")])])}const J=h(y,[["render",R],["__file","index.html.vue"]]);export{J as default}; diff --git a/assets/index.html-nFm7KTWc.js b/assets/index.html-nFm7KTWc.js deleted file mode 100644 index c67ca61b..00000000 --- a/assets/index.html-nFm7KTWc.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-e8b6c472","path":"/notes/","title":"笔记","lang":"zh-CN","frontmatter":{"description":"通用知识 Lua语言快速上手 (./lua.md); MicroCity的版本 (./versions.md); 时间推进法 (./timelapse.md); 面向对象编程 (./oop.md); 有关工具 (./tools.md); MicroCity(桌面版) 结果可视化 (./visualization.md); 操作网络 (./network...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"笔记"}],["meta",{"property":"og:description","content":"通用知识 Lua语言快速上手 (./lua.md); MicroCity的版本 (./versions.md); 时间推进法 (./timelapse.md); 面向对象编程 (./oop.md); 有关工具 (./tools.md); MicroCity(桌面版) 结果可视化 (./visualization.md); 操作网络 (./network..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-20T15:27:43.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T15:27:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"笔记\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T15:27:43.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"通用知识","slug":"通用知识","link":"#通用知识","children":[]},{"level":2,"title":"MicroCity(桌面版)","slug":"microcity-桌面版","link":"#microcity-桌面版","children":[]},{"level":2,"title":"MicroCityWeb","slug":"microcityweb","link":"#microcityweb","children":[]},{"level":2,"title":"思路","slug":"思路","link":"#思路","children":[]}],"git":{"updatedTime":1700494063000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":18}]},"filePathRelative":"notes/README.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-nYDcqjx5.js b/assets/index.html-nYDcqjx5.js new file mode 100644 index 00000000..90de8891 --- /dev/null +++ b/assets/index.html-nYDcqjx5.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-e8b6c472","path":"/notes/","title":"笔记","lang":"zh-CN","frontmatter":{"description":"通用知识 Lua语言快速上手 (./lua.md); MicroCity的版本 (./versions.md); 时间推进法 (./timelapse.md); 面向对象编程 (./oop.md); 有关工具 (./tools.md); MicroCity(桌面版) 结果可视化 (./visualization.md); 操作网络 (./network...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"笔记"}],["meta",{"property":"og:description","content":"通用知识 Lua语言快速上手 (./lua.md); MicroCity的版本 (./versions.md); 时间推进法 (./timelapse.md); 面向对象编程 (./oop.md); 有关工具 (./tools.md); MicroCity(桌面版) 结果可视化 (./visualization.md); 操作网络 (./network..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:49:40.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:49:40.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"笔记\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:49:40.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"通用知识","slug":"通用知识","link":"#通用知识","children":[]},{"level":2,"title":"MicroCity(桌面版)","slug":"microcity-桌面版","link":"#microcity-桌面版","children":[]},{"level":2,"title":"MicroCityWeb","slug":"microcityweb","link":"#microcityweb","children":[]},{"level":2,"title":"思路","slug":"思路","link":"#思路","children":[]}],"git":{"updatedTime":1701060580000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":20}]},"filePathRelative":"notes/README.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-ps9YKXkA.js b/assets/index.html-ps9YKXkA.js deleted file mode 100644 index c357896a..00000000 --- a/assets/index.html-ps9YKXkA.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-147825fb","path":"/docs/","title":"MicroCity文档","lang":"zh-CN","frontmatter":{"description":"目录 1 Introduction 介绍; 1.1 What MicroCity can Do (1.1whatmicrocitycando.md) MicroCity能干什么; 2 Getting Started 开始使用; 2.1 Showing a World Map (2.1showingaworldmap.md) 展示世界地图; 2.2 Se...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/docs/"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"MicroCity文档"}],["meta",{"property":"og:description","content":"目录 1 Introduction 介绍; 1.1 What MicroCity can Do (1.1whatmicrocitycando.md) MicroCity能干什么; 2 Getting Started 开始使用; 2.1 Showing a World Map (2.1showingaworldmap.md) 展示世界地图; 2.2 Se..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-19T14:44:21.000Z"}],["meta",{"property":"article:modified_time","content":"2022-12-19T14:44:21.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"MicroCity文档\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2022-12-19T14:44:21.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"目录","slug":"目录","link":"#目录","children":[]}],"git":{"updatedTime":1671461061000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"docs/readme.md","autoDesc":true}');export{t as data}; diff --git a/assets/index.html-rmW5MKDv.js b/assets/index.html-rmW5MKDv.js new file mode 100644 index 00000000..49eabb48 --- /dev/null +++ b/assets/index.html-rmW5MKDv.js @@ -0,0 +1,2 @@ +import{_ as a}from"./play-RaBYbg3m.js";import{_ as c}from"./icon_script_editor-ibm_2NsU.js";import{_ as h}from"./icon_microcity-Je85-7MO.js";import{_ as u,a as _}from"./icon_module-AxwvBQMt.js";import{_ as p,r as i,o as d,c as g,a as t,b as e,d as o,w as n,e as m}from"./app-LOf__QKq.js";const y={},f=t("h2",{id:"开始使用microcity-web",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#开始使用microcity-web","aria-hidden":"true"},"#"),e(" 开始使用MicroCity Web")],-1),b={href:"https://microcity.gitee.io/",target:"_blank",rel:"noopener noreferrer"},k=t("li",null,[t("p",null,[e("点击运行"),t("img",{src:a,alt:"Play"}),e("按钮运行代码")])],-1),C=t("li",null,[t("p",null,"程序运行,看到右侧视图中方块旋转。")],-1),M=t("strong",null,"学习笔记",-1),x=t("h2",{id:"开始使用microcity-desktop",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#开始使用microcity-desktop","aria-hidden":"true"},"#"),e(" 开始使用MicroCity Desktop")],-1),N=t("p",null,[t("img",{src:"https://img.shields.io/github/v/release/microcity/Desktop",alt:"GitHub release (latest by date)"}),e(),t("img",{src:"https://img.shields.io/github/downloads/microcity/Desktop/latest/total",alt:"GitHub release (by tag)"})],-1),v={href:"https://github.com/microcity/Desktop/releases/latest",target:"_blank",rel:"noopener noreferrer"},w=t("strong",null,"MicroCity的最新版本",-1),G=t("li",null,[t("p",null,[e("打开 "),t("img",{src:c,alt:"icon"}),t("strong",null,"ScriptEditor"),e(" 并输入:")])],-1),H=m(`
Print("hello, world!")
+
  1. 将脚本另存为 test.mcs 并将其拖入 iconMicroCity

  2. 在程序主界面左侧转到 Modules 标签页,打开 icontest ,双击其中的 iconmain ,执行刚刚编写的脚本。

  3. 程序界面下方的 Messages 栏中会输出执行脚本的信息。

',2),D=t("strong",null,"MicroCity文档",-1),E={href:"https://microcity.github.io/",target:"_blank",rel:"noopener noreferrer"},L={id:"microcitynotes-仓库",tabindex:"-1"},P=t("a",{class:"header-anchor",href:"#microcitynotes-仓库","aria-hidden":"true"},"#",-1),S={href:"https://github.com/huuhghhgyg/MicroCityNotes",target:"_blank",rel:"noopener noreferrer"},V=t("img",{src:"https://img.shields.io/github/last-commit/huuhghhgyg/MicroCityNotes",alt:"GitHub last commit"},null,-1),W=t("img",{src:"https://img.shields.io/github/actions/workflow/status/huuhghhgyg/MicroCityNotes/DeployPage.yml?branch=main",alt:"GitHub Workflow Status"},null,-1),q={href:"https://app.netlify.com/sites/microcitynotes/deploys",target:"_blank",rel:"noopener noreferrer"},B=t("img",{src:"https://api.netlify.com/api/v1/badges/fe05238c-93ee-44db-84cf-7f805d43520a/deploy-status",alt:"Netlify Status"},null,-1),I={href:"https://mcn.zhhuu.top",target:"_blank",rel:"noopener noreferrer"},R=t("strong",null,"同步站点",-1),A={href:"https://github.com/huuhghhgyg/MicroCityNotes/pulls",target:"_blank",rel:"noopener noreferrer"},$={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues",target:"_blank",rel:"noopener noreferrer"};function z(T,j){const s=i("ExternalLinkIcon"),r=i("RouterLink"),l=i("A2hs");return d(),g("div",null,[f,t("ol",null,[t("li",null,[t("p",null,[e("打开"),t("a",b,[e("MicroCity Web"),o(s)]),e(",默认加载方块旋转的示例代码。")])]),k,C]),t("p",null,[e("如果想要深入了解 MicroCity Web 的用法和使用技巧,可以参阅本站提供的 "),o(r,{to:"/notes/"},{default:n(()=>[M]),_:1})]),x,N,t("ol",null,[t("li",null,[t("p",null,[e("转到MicroCity的文档仓库下载 "),t("a",v,[w,o(s)])])]),G]),H,t("p",null,[e("更多MicroCity的使用方法可以参考本站搬运自GitHub的文档:"),o(r,{to:"/docs/"},{default:n(()=>[D]),_:1}),e(",也可以参考 "),t("a",E,[e("MicroCtiy"),o(s)]),e(" 在GitHub上的文档。")]),t("h2",L,[P,e(),t("a",S,[e("MicroCityNotes"),o(s)]),e(" 仓库")]),t("p",null,[V,e(),W,e(),t("a",q,[B,o(s)])]),o(l),t("p",null,[e("国内用户如果不方便访问 GitHub 也可以访问本站在 Netlify 上搭建的 "),t("a",I,[R,o(s)])]),t("p",null,[e("如果发现文档或笔记有问题,欢迎 "),t("a",A,[e("Pull Request"),o(s)]),e(" 或者提供 "),t("a",$,[e("Issues"),o(s)]),e(" 让它变得更完善😋")])])}const U=p(y,[["render",z],["__file","index.html.vue"]]);export{U as default}; diff --git a/assets/lp.html-BGRyuCz8.js b/assets/lp.html-BGRyuCz8.js new file mode 100644 index 00000000..71126f9d --- /dev/null +++ b/assets/lp.html-BGRyuCz8.js @@ -0,0 +1,145 @@ +import{_ as h,r,o as p,c,a as s,b as a,d as i,w as n,e as t}from"./app-LOf__QKq.js";const d={},g=s("h1",{id:"model-solving",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#model-solving","aria-hidden":"true"},"#"),a(" Model Solving")],-1),v=s("p",null,"In MicroCity, mathematical models can be solved. In this article, we will introduce the common process of solving mathematical models in MicroCity and provide some tips to help you better build models.",-1),b={class:"hint-container tip"},y=s("p",{class:"hint-container-title"},"Tips",-1),k=t(`

Creating Model Objects

Create a planning model object and store it in the variable lp.

local lp = CreateLP()
+

The mathematical model object created in the official documentation is stored in the variable LPModel, which has the same function as lp in this article.

Writing Mathematical Models

At this point, the object of the mathematical model has been created and stored in the variable lp, and further operations can be performed on it. A mathematical model generally consists of two parts:

Next, let's introduce how to create the objective function.

Creating the Objective Function

In MicroCity, SetObjectFunction() is used to set the objective function of the model object. It allows you to choose whether to optimize for maximum or minimum. The specific usage is as follows:

`,10),x=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token function"},"SetObjFunction"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"max"'),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"-- Optimize for maximum"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),f=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token function"},"SetObjFunction"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"min"'),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"-- Optimize for minimum"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),_=t('

"min" and "max" are case-insensitive, so "MIN" and "MAX" can also be used.

Parameter Description and Example

ParameterDescription
lpMathematical model object. Input the mathematical model into the function to set the objective function.
coeffObjective function coefficients, which is a table type variable. Used to determine the coefficients of the objective function in the model.
"min" or "max"Determine whether to optimize for the maximum or the minimum of the objective function.
',3),w=s("p",null,[s("code",null,"coeff"),a(" is a coefficient list for the objective function, which is a "),s("code",null,"table"),a(" type variable. Suppose you want to minimize the function "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"12"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"4x_1+12x_2+18x_3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"12"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(", the procedure to add the objective function is as follows:")],-1),z=t(`
-- Suppose you have already created the model object and stored it in the variable lp
+
+-- 4*x1 + 12*x2 + 18*x3
+local coeff = {4, 12, 18}
+
+-- Set the objective function: minimize
+SetObjFunction(lp, coeff, "min")
+

Adding Constraint Equations

In MicroCity, the function for adding model constraints is AddConstraint(), used as follows:

`,3),j=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token comment"},"-- Use symbols to express"),a(` +`),s("span",{class:"token function"},"AddConstraint"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" cons"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"<="'),s("span",{class:"token punctuation"},","),a(" b"),s("span",{class:"token punctuation"},")"),a(` + +`),s("span",{class:"token comment"},"-- Alternatively, you can use abbreviations"),a(` +`),s("span",{class:"token function"},"AddConstraint"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" cons"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"le"'),s("span",{class:"token punctuation"},","),a(" b"),s("span",{class:"token punctuation"},")"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),M=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token comment"},"-- Use symbols to express"),a(` +`),s("span",{class:"token function"},"AddConstraint"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" cons"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'">="'),s("span",{class:"token punctuation"},","),a(" b"),s("span",{class:"token punctuation"},")"),a(` + +`),s("span",{class:"token comment"},"-- Alternatively, you can use abbreviations"),a(` +`),s("span",{class:"token function"},"AddConstraint"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" cons"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"ge"'),s("span",{class:"token punctuation"},","),a(" b"),s("span",{class:"token punctuation"},")"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),q=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token comment"},"-- Use symbols to express"),a(` +`),s("span",{class:"token function"},"AddConstraint"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" cons"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"=="'),s("span",{class:"token punctuation"},","),a(" b"),s("span",{class:"token punctuation"},")"),a(` + +`),s("span",{class:"token comment"},"-- Or you can use abbreviations to express it"),a(` + +`),s("span",{class:"token function"},"AddConstraint"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" cons"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"eq"'),s("span",{class:"token punctuation"},","),a(" b"),s("span",{class:"token punctuation"},")"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),A=t('

Parameter Description

ParameterDescription
lpMathematical model object. Input the mathematical model into the function to add constraints to it.
consConstraint equation coefficients. Similar to cons in setting the objective function, it is also a table type variable used to determine the coefficients of each variable in the constraint equation.
"<=" or ">=" or "==", or their corresponding alphabetic expressionsDetermines the relationship between the constraint equation and the right-hand side.
bA number representing the right-hand side of the constraint equation. It can be a variable or a constant.

Example

',3),C=s("p",null,[a("The objective function "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"12"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"4x_1+12x_2+18x_3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"12"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" has been set above. Suppose you want to add two constraint equations for this function:")],-1),S=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mo",{fence:"true"},"{"),s("mtable",{rowspacing:"0.16em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"3"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mo",null,"≥"),s("mn",null,"3")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"2"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mo",null,"≥"),s("mn",null,"5")])])])])])]),s("annotation",{encoding:"application/x-tex"}," \\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\end{matrix}\\right. ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"2.4em","vertical-align":"-0.95em"}}),s("span",{class:"minner"},[s("span",{class:"mopen delimcenter",style:{top:"0em"}},[s("span",{class:"delimsizing size3"},"{")]),s("span",{class:"mord"},[s("span",{class:"mtable"},[s("span",{class:"col-align-c"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.45em"}},[s("span",{style:{top:"-3.61em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"3")])]),s("span",{style:{top:"-2.41em"}},[s("span",{class:"pstrut",style:{height:"3em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mord"},"2"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"≥"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mord"},"5")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.95em"}},[s("span")])])])])])]),s("span",{class:"mclose nulldelimiter"})])])])])])],-1),L=t(`

Add corresponding constraint equations:

-- Add constraint: x1+3*x3≥3
+cons = { 1, 0, 3 }
+AddConstraint(lp, cons, ">=", 3)
+
+-- Add constraint: 2*x2+2*x3≥5
+cons = { 0, 2, 2 }
+AddConstraint(lp, cons, ">=", 5)
+

It is not difficult to notice that the number of coefficients is consistent with the number of variables in the objective function. Therefore, before programming the solution, you need to first determine the total number of variables and arrange the positions of each variable.

Set Variable Types

MicroCity's mathematical programming supports integer programming. If no SetUnbounded() is set for the variables, the default value range for the variables is non-negative real numbers (≥0). The following describes in detail how to set variable types.

You can set the integer variable or 0-1 variable for the i-th variable in the model. If the variable is not set to these types, the default variable is non-negative real number.

`,6),O=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token function"},"SetInteger"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" i"),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"-- Integer variable"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),I=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token function"},"SetBinary"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" i"),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"--0-1 variable"),a(` +`)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),T=t(`

To allow the value of the i-th variable to be negative (by default, it cannot be negative):

SetUnbounded(lp, i)
+

Model Solving and Output

Model Solving

Since both the objective function and the constraint equations have been added, solving the model is simple, just one step:

SolveLP(lp)
+

After executing this statement, the mathematical model stored in the variable lp is solved.

Output

After solving the problem, it still needs to be output to understand the result of the solution. The following are commonly used functions for outputting the solution result.

Obtain the objective function value:

GetObjective(lp)
+

Obtain the value of the i-th variable:

GetVariable(lp, i)
+

SolveLP

The SolveLP() function also has output after the solution is obtained, the meaning of the output code is as follows:

Output CodeMeaning
0Success
-1Invalid LP Model
-2Out of Memory
1Suboptimal
2Infeasible
3Unbounded
4Degenerate
5Numerical Error
6User Termination
7Timeout Error
`,16),P=s("code",null,"SolveLP()",-1),V=s("h2",{id:"model-solution-example",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#model-solution-example","aria-hidden":"true"},"#"),a(" Model Solution Example")],-1),H=s("p",null,"Here is a simple example of modeling and solving for reference. (Actually it just strings together the previous content)",-1),$=s("p",null,"Example:",-1),B={class:"katex-block"},D={class:"katex-display"},F={class:"katex"},E=s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"m"),s("mi",null,"i"),s("mi",null,"n"),s("mi",null,"f"),s("mo",null,"="),s("mn",null,"4"),s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"12"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mspace",{linebreak:"newline"}),s("mi",null,"s"),s("mi",{mathvariant:"normal"},"."),s("mi",null,"t"),s("mi",{mathvariant:"normal"},"."),s("mrow",null,[s("mo",{fence:"true"},"{"),s("mtable",{rowspacing:"0.16em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"3"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mo",null,"≥"),s("mn",null,"3")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("mn",null,"2"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"2"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mo",null,"≥"),s("mn",null,"5")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mo",null,"∈"),s("mi",null,"N")])])])])])])]),s("annotation",{encoding:"application/x-tex"}," minf=4x_1+12x_2+18x_3\\\\ s.t.\\left\\{\\begin{matrix} x_1+3x_3\\ge3 \\\\ 2x_2+2x_3\\ge5 \\\\ x_1,x_2,x_3\\in N \\end{matrix}\\right. ")])])],-1),N={class:"katex-html","aria-hidden":"true"},U=t('minf=4x1+12x2+18x3',5),G={class:"base"},R=t('s.t.',6),Y={class:"minner"},W={class:"mopen"},Z={class:"delimsizing mult"},X={class:"vlist-t vlist-t2"},J={class:"vlist-r"},K={class:"vlist",style:{height:"2.05em"}},Q=s("span",{style:{top:"-2.5em"}},[s("span",{class:"pstrut",style:{height:"3.15em"}}),s("span",{class:"delimsizinginner delim-size4"},[s("span",null,"⎩")])],-1),ss={style:{top:"-2.492em"}},as=s("span",{class:"pstrut",style:{height:"3.15em"}},null,-1),ns={style:{height:"0.016em",width:"0.8889em"}},ts={xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"0.016em",style:{width:"0.8889em"},viewBox:"0 0 888.89 16",preserveAspectRatio:"xMinYMin"},es=s("path",{d:"M384 0 H504 V16 H384z M384 0 H504 V16 H384z"},null,-1),ls=[es],is=s("span",{style:{top:"-3.15em"}},[s("span",{class:"pstrut",style:{height:"3.15em"}}),s("span",{class:"delimsizinginner delim-size4"},[s("span",null,"⎨")])],-1),ps={style:{top:"-4.292em"}},cs=s("span",{class:"pstrut",style:{height:"3.15em"}},null,-1),ms={style:{height:"0.016em",width:"0.8889em"}},os={xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"0.016em",style:{width:"0.8889em"},viewBox:"0 0 888.89 16",preserveAspectRatio:"xMinYMin"},rs=s("path",{d:"M384 0 H504 V16 H384z M384 0 H504 V16 H384z"},null,-1),us=[rs],hs=s("span",{style:{top:"-4.3em"}},[s("span",{class:"pstrut",style:{height:"3.15em"}}),s("span",{class:"delimsizinginner delim-size4"},[s("span",null,"⎧")])],-1),ds=s("span",{class:"vlist-s"},"​",-1),gs=s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.55em"}},[s("span")])],-1),vs=t('x1+3x332x2+2x35x1,x2,x3N',2),bs=t(`

N represents the set of natural numbers (non-negative integers)

Script:

-- Create linear programming object
+local lp = CreateLP()
+
+local n = 3 -- Set the number of objective functions
+
+-- Objective function: 4*x1 + 12*x2 + 18*x3
+-- Set the coefficients of the objective function, and the objective function is minimized
+local coeff = { 4, 12, 18 }
+SetObjFunction(lp, coeff, "min")
+
+-- Add constraint 1: x1 + 3*x3 ≥ 3
+cons = { 1, 0, 3 }
+AddConstraint(lp, cons, ">=", 3)
+
+-- Add constraint 2: 2*x2 + 2*x3 ≥ 5
+cons = { 0, 2, 2 }
+AddConstraint(lp, cons, ">=", 5)
+
+-- Since SetUnbounded() is not set,
+-- by default, all variables are non-negative,
+-- so there is no need to add constraints for non-negative variables.
+
+-- Set all variables to integers
+for i = 1, n do
+    SetInteger(lp, i)
+end
+
+-- Solve the model
+SolveLP(lp)
+
+-- Output the objective function value
+print("Objective function value:", GetObjective(lp))
+
+-- Output the values of each variable
+for i = 1, n do
+    print("x", i, "=", GetVariable(lp, i))
+end
+

Output:

Objective function value: 42
+x1=0
+x2=2
+x3=1
+

Some Techniques for Modeling

Linearization

`,7),ys=s("p",null,[a("Sometimes we encounter modeling problems with multiple subscripts, such as the decision variable "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])])]),s("annotation",{encoding:"application/x-tex"},"x_{ij}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"ij")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(", which needs to be linearized.")],-1),ks=s("p",null,"Let's assume that the shape of the decision variable itself is 3 rows and 4 columns, that is:",-1),xs=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Column 1"),s("th",null,"Column 2"),s("th",null,"Column 3"),s("th",null,"Column 4")])]),s("tbody",null,[s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"11")])]),s("annotation",{encoding:"application/x-tex"},"x_{11}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"11")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"12")])]),s("annotation",{encoding:"application/x-tex"},"x_{12}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"12")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"13")])]),s("annotation",{encoding:"application/x-tex"},"x_{13}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"13")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"14")])]),s("annotation",{encoding:"application/x-tex"},"x_{14}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"14")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"21")])]),s("annotation",{encoding:"application/x-tex"},"x_{21}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"21")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"22")])]),s("annotation",{encoding:"application/x-tex"},"x_{22}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"22")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"23")])]),s("annotation",{encoding:"application/x-tex"},"x_{23}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"23")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"24")])]),s("annotation",{encoding:"application/x-tex"},"x_{24}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"24")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"31")])]),s("annotation",{encoding:"application/x-tex"},"x_{31}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"31")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"32")])]),s("annotation",{encoding:"application/x-tex"},"x_{32}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"32")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"33")])]),s("annotation",{encoding:"application/x-tex"},"x_{33}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"33")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])]),s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"34")])]),s("annotation",{encoding:"application/x-tex"},"x_{34}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"34")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])])])],-1),fs=s("p",null,[a("Assuming that the objective function is to sum up these decision variables, which is "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"F"),s("mo",null,"="),s("msubsup",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"3")]),s("msubsup",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"j"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"4")]),s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])])]),s("annotation",{encoding:"application/x-tex"},"F=\\sum_{i=1}^3\\sum_{j=1}^4x_{ij}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.13889em"}},"F"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.3898em","vertical-align":"-0.4358em"}}),s("span",{class:"mop"},[s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-2.4003em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2997em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mop"},[s("span",{class:"mop op-symbol small-op",style:{position:"relative",top:"0em"}},"∑"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.954em"}},[s("span",{style:{top:"-2.4003em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"j"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.2029em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.4358em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"ij")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])])])])]),a(", if we want to input it into the objective function, we can linearize it as "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"11")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"x"),s("mn",null,"12")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mo",null,"+"),s("msub",null,[s("mi",null,"x"),s("mn",null,"14")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"x"),s("mn",null,"21")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mo",null,"+"),s("msub",null,[s("mi",null,"x"),s("mn",null,"24")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"x"),s("mn",null,"31")]),s("mo",null,"+"),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mo",null,"+"),s("msub",null,[s("mi",null,"x"),s("mn",null,"34")])]),s("annotation",{encoding:"application/x-tex"},"x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"11")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"12")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"..."),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"14")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"21")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"..."),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"24")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7333em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"31")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6667em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"..."),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"34")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(".")],-1),_s=t(`

Since there are only two dimensions, we can use two for loops to achieve this:

local cons = {}
+for i = 1, 3 do -- the first dimension
+    for j = 1, 4 do -- the second dimension
+        cons[4 * (i - 1) + j] = 1 -- fill in the coefficients
+        -- the idea of 4 * (i - 1) + j is similar to carrying
+    end
+end
+
+-- result:
+-- cons has a length of 12, and all values are 1
+

Example: Assignment Model

Let's take a look at the specific usage and convenience of multidimensional linearization using an actual example.

Four people, A, B, C, and D, are assigned to deliver four types of goods, A, B, C, and D, with the corresponding delivery times shown in the table. If each person delivers only one type of goods, who should be assigned to deliver which type of goods to minimize the total time?

Person\\GoodsABCD
A149415
B117910
C132105
D1791513
`,6),ws=s("p",null,[a("Let's assume that the numbers corresponding to goods A, B, C, D are 1, 2, 3, 4 respectively, and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("mo",null,"="),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"x_{ij}=1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"ij")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])]),a(" represents person "),s("code",null,"i"),a(" delivering goods "),s("code",null,"j"),a(", and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("mo",null,"="),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"x_{ij}=0")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7167em","vertical-align":"-0.2861em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05724em"}},"ij")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.2861em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"0")])])]),a(" represents person "),s("code",null,"i"),a(" not delivering goods "),s("code",null,"j"),a(".")],-1),zs=s("p",null,"The mathematical model of the above problem can be represented as",-1),js={class:"katex-block"},Ms={class:"katex-display"},qs={class:"katex"},As=s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"m"),s("mi",null,"i"),s("mi",null,"n"),s("mi",null,"Z"),s("mo",null,"="),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"4")]),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"j"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"4")]),s("msub",null,[s("mi",null,"c"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("mspace",{linebreak:"newline"}),s("mi",null,"s"),s("mi",{mathvariant:"normal"},"."),s("mi",null,"t"),s("mi",{mathvariant:"normal"},"."),s("mrow",null,[s("mo",{fence:"true"},"{"),s("mtable",{rowspacing:"0.16em",columnalign:"center",columnspacing:"1em"},[s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("msubsup",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"j"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"4")]),s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("mo",null,"="),s("mn",null,"1"),s("mo",{separator:"true"},","),s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mo",{separator:"true"},","),s("mn",null,"4")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("msubsup",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"4")]),s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("mo",null,"="),s("mn",null,"1"),s("mo",{separator:"true"},","),s("mi",null,"j"),s("mo",null,"="),s("mn",null,"1"),s("mo",{separator:"true"},","),s("mn",null,"2"),s("mo",{separator:"true"},","),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mi",{mathvariant:"normal"},"."),s("mo",{separator:"true"},","),s("mn",null,"4")])])])]),s("mtr",null,[s("mtd",null,[s("mstyle",{scriptlevel:"0",displaystyle:"false"},[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mrow",null,[s("mi",null,"i"),s("mi",null,"j")])]),s("mo",null,"="),s("mn",null,"0"),s("mo",{separator:"true"},","),s("mn",null,"1")])])])])])])]),s("annotation",{encoding:"application/x-tex"}," minZ=\\sum_{i=1}^4\\sum_{j=1}^4c_{ij}x_{ij}\\\\ s.t.\\left\\{\\begin{matrix} \\sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\\\ \\sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\\\ x_{ij}=0,1 \\end{matrix}\\right. ")])])],-1),Cs={class:"katex-html","aria-hidden":"true"},Ss=t('minZ=i=14j=14cijxij',3),Ls={class:"base"},Os=t('s.t.',6),Is={class:"minner"},Ts={class:"mopen"},Ps={class:"delimsizing mult"},Vs={class:"vlist-t vlist-t2"},Hs={class:"vlist-r"},$s={class:"vlist",style:{height:"2.05em"}},Bs=s("span",{style:{top:"-2.5em"}},[s("span",{class:"pstrut",style:{height:"3.15em"}}),s("span",{class:"delimsizinginner delim-size4"},[s("span",null,"⎩")])],-1),Ds={style:{top:"-2.492em"}},Fs=s("span",{class:"pstrut",style:{height:"3.15em"}},null,-1),Es={style:{height:"0.016em",width:"0.8889em"}},Ns={xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"0.016em",style:{width:"0.8889em"},viewBox:"0 0 888.89 16",preserveAspectRatio:"xMinYMin"},Us=s("path",{d:"M384 0 H504 V16 H384z M384 0 H504 V16 H384z"},null,-1),Gs=[Us],Rs=s("span",{style:{top:"-3.15em"}},[s("span",{class:"pstrut",style:{height:"3.15em"}}),s("span",{class:"delimsizinginner delim-size4"},[s("span",null,"⎨")])],-1),Ys={style:{top:"-4.292em"}},Ws=s("span",{class:"pstrut",style:{height:"3.15em"}},null,-1),Zs={style:{height:"0.016em",width:"0.8889em"}},Xs={xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"0.016em",style:{width:"0.8889em"},viewBox:"0 0 888.89 16",preserveAspectRatio:"xMinYMin"},Js=s("path",{d:"M384 0 H504 V16 H384z M384 0 H504 V16 H384z"},null,-1),Ks=[Js],Qs=s("span",{style:{top:"-4.3em"}},[s("span",{class:"pstrut",style:{height:"3.15em"}}),s("span",{class:"delimsizinginner delim-size4"},[s("span",null,"⎧")])],-1),sa=s("span",{class:"vlist-s"},"​",-1),aa=s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.55em"}},[s("span")])],-1),na=t('j=14xij=1,i=1,2,...,4i=14xij=1,j=1,2,...,4xij=0,1',2),ta=t(`

Solution code:

-- efficiency matrix
+local cost = {
+    { 14, 9, 4, 15 },
+    { 11, 7, 9, 10 },
+    { 13, 2, 10, 5 },
+    { 17, 9, 15, 13 }
+}
+
+local lp = CreateLP()
+
+-- create the objective function
+local coeff = {}
+for i = 1, 4 do
+    for j = 1, 4 do
+        -- it is easy to convert a two-dimensional array to a one-dimensional array here
+        coeff[4 * (i - 1) + j] = cost[i][j]
+    end
+end
+
+SetObjFunction(lp, coeff, "min")
+
+-- add constraints
+for k = 1, 4 do -- control the value of the i dimension
+    local cons = {}
+    for i = 1, 4 do
+        for j = 1, 4 do
+            if i == k then -- sum up j, check i
+                cons[4 * (i - 1) + j] = 1
+            else
+                cons[4 * (i - 1) + j] = 0
+            end
+        end
+    end
+    AddConstraint(lp, cons, "==", 1)
+end
+

for k = 1, 4 do -- Control the value of the jth dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then -- Sum i and check j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) end

-- Solve the model SolveLP(lp)

-- Output the objective function value print("Objective function value:", GetObjective(lp))

-- Output the decision variables for i = 1, 4 do -- First dimension for j = 1, 4 do -- Second dimension local x = GetVariable(lp, 4 * (i - 1) + j) if x ~= 0 then print("x[", i, "][", j, "]=", x) end end end


+Output
+

Objective function value: 29 x[1][3]=1 x[2][1]=1 x[3][4]=1 x[4][2]=1

| Result      | Person | Item |
+| ----------  | :---: | :------: |
+| $x_{13}=1$  |   A   |    C     |
+| $x_{21}=1$  |   B   |    A     |
+| $x_{34}=1$  |   C   |    D     |
+| $x_{42}=1$  |   D   |    B     |
+
+### Handling Intermediate Variables
+Sometimes there may be intermediate variables in the model that need to have corresponding positions in the matrix in order to be solved, but these intermediate variables do not participate in the calculation of the objective function value. **You can set the coefficients of these intermediate variables to 0 at their corresponding positions.**
+
+Let $x_1, x_2, x_3, x_4$ be the decision variables and $y_1, y_2$ be the intermediate variables. The objective function is:
+$$
+z = \\sum_{i=1}^4 x_i
+$$
+Then the coefficients of the objective function can be set as:
+\`\`\`lua
+local fcons = {1, 1, 1, 1, 0, 0}
+

After that, you can proceed with the general process 😎

`,10),ea={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},la=s("strong",null,"feedback",-1);function ia(pa,ca){const m=r("RouterLink"),o=r("CodeTabs"),u=r("ExternalLinkIcon");return p(),c("div",null,[g,v,s("p",null,[a("The detailed usage of all functions in the planning model can be found in the document "),i(m,{to:"/en/docs/4.8_mixed_integer_programming.html"},{default:n(()=>[a("4.8 Mixed Integer Linear Programming")]),_:1}),a(".")]),s("div",b,[y,s("p",null,[a("The content on this page is based on MicroCity Desktop version. If you are looking for a solution for mixed integer programming in MicroCity Web version, please refer to the corresponding "),i(m,{to:"/en/notes/mip.html"},{default:n(()=>[a("Mixed Integer Programming")]),_:1}),a(" section in the MicroCity Web notes.")])]),k,i(o,{id:"53",data:[{id:"Maximum"},{id:"Minimum"}],active:0,"tab-id":"shell"},{title0:n(({value:e,isActive:l})=>[a("Maximum")]),title1:n(({value:e,isActive:l})=>[a("Minimum")]),tab0:n(({value:e,isActive:l})=>[x]),tab1:n(({value:e,isActive:l})=>[f]),_:1}),_,w,z,i(o,{id:"117",data:[{id:"≤"},{id:"≥"},{id:"="}],active:0,"tab-id":"shell"},{title0:n(({value:e,isActive:l})=>[a("≤")]),title1:n(({value:e,isActive:l})=>[a("≥")]),title2:n(({value:e,isActive:l})=>[a("=")]),tab0:n(({value:e,isActive:l})=>[j]),tab1:n(({value:e,isActive:l})=>[M]),tab2:n(({value:e,isActive:l})=>[q]),_:1}),A,C,S,L,i(o,{id:"200",data:[{id:"Integer Variables"},{id:"0-1 Variables"}],"tab-id":"shell"},{title0:n(({value:e,isActive:l})=>[a("Integer Variables")]),title1:n(({value:e,isActive:l})=>[a("0-1 Variables")]),tab0:n(({value:e,isActive:l})=>[O]),tab1:n(({value:e,isActive:l})=>[I]),_:1}),T,s("p",null,[a("For the meaning of other return values, please refer to the documentation "),i(m,{to:"/en/docs/4.8_mixed_integer_programming.html"},{default:n(()=>[a("4.8 Mixed Integer Linear Programming")]),_:1}),a(" for the "),P,a(" function.")]),V,H,$,s("p",B,[s("span",D,[s("span",F,[E,s("span",N,[U,s("span",G,[R,s("span",Y,[s("span",W,[s("span",Z,[s("span",X,[s("span",J,[s("span",K,[Q,s("span",ss,[as,s("span",ns,[(p(),c("svg",ts,ls))])]),is,s("span",ps,[cs,s("span",ms,[(p(),c("svg",os,us))])]),hs]),ds]),gs])])]),vs])])])])])]),bs,ys,ks,xs,fs,_s,ws,zs,s("p",js,[s("span",Ms,[s("span",qs,[As,s("span",Cs,[Ss,s("span",Ls,[Os,s("span",Is,[s("span",Ts,[s("span",Ps,[s("span",Vs,[s("span",Hs,[s("span",$s,[Bs,s("span",Ds,[Fs,s("span",Es,[(p(),c("svg",Ns,Gs))])]),Rs,s("span",Ys,[Ws,s("span",Zs,[(p(),c("svg",Xs,Ks))])]),Qs]),sa]),aa])])]),na])])])])])]),ta,s("blockquote",null,[s("p",null,[a("This post is translated using ChatGPT, please "),s("a",ea,[la,i(u)]),a(" if any omissions.")])])])}const oa=h(d,[["render",ia],["__file","lp.html.vue"]]);export{oa as default}; diff --git a/assets/lp.html-NKzjcq8T.js b/assets/lp.html-NKzjcq8T.js deleted file mode 100644 index 52354506..00000000 --- a/assets/lp.html-NKzjcq8T.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-8138aba4","path":"/notes/lp.html","title":"模型求解","lang":"zh-CN","frontmatter":{"description":"在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。 规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划 (../docs/4.8mixedinteger_programming.md) 本页内容基于 MicroCity 桌面版。如果你在寻找 Mic...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/lp.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"模型求解"}],["meta",{"property":"og:description","content":"在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。 规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划 (../docs/4.8mixedinteger_programming.md) 本页内容基于 MicroCity 桌面版。如果你在寻找 Mic..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-19T10:07:10.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-19T10:07:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"模型求解\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-19T10:07:10.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"创建模型对象","slug":"创建模型对象","link":"#创建模型对象","children":[]},{"level":2,"title":"写入数学模型","slug":"写入数学模型","link":"#写入数学模型","children":[{"level":3,"title":"创建目标函数","slug":"创建目标函数","link":"#创建目标函数","children":[]},{"level":3,"title":"添加约束方程","slug":"添加约束方程","link":"#添加约束方程","children":[]},{"level":3,"title":"设置变量类型","slug":"设置变量类型","link":"#设置变量类型","children":[]}]},{"level":2,"title":"模型求解和输出","slug":"模型求解和输出","link":"#模型求解和输出","children":[{"level":3,"title":"模型求解","slug":"模型求解-1","link":"#模型求解-1","children":[]},{"level":3,"title":"输出","slug":"输出","link":"#输出","children":[]}]},{"level":2,"title":"模型求解示例","slug":"模型求解示例","link":"#模型求解示例","children":[]},{"level":2,"title":"建模的一些技巧","slug":"建模的一些技巧","link":"#建模的一些技巧","children":[{"level":3,"title":"线性化","slug":"线性化","link":"#线性化","children":[]},{"level":3,"title":"中间变量的处理","slug":"中间变量的处理","link":"#中间变量的处理","children":[]}]}],"git":{"updatedTime":1700388430000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"notes/lp.md","autoDesc":true}');export{e as data}; diff --git a/assets/lp.html-jETCO9wn.js b/assets/lp.html-jETCO9wn.js new file mode 100644 index 00000000..79155513 --- /dev/null +++ b/assets/lp.html-jETCO9wn.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-8138aba4","path":"/notes/lp.html","title":"模型求解","lang":"zh-CN","frontmatter":{"description":"在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。 规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划 (../docs/4.8mixedinteger_programming.md) 本页内容基于 MicroCity 桌面版。如果你在寻找 Mic...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/lp.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/lp.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"模型求解"}],["meta",{"property":"og:description","content":"在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。 规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划 (../docs/4.8mixedinteger_programming.md) 本页内容基于 MicroCity 桌面版。如果你在寻找 Mic..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-19T10:07:10.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-19T10:07:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"模型求解\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-19T10:07:10.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"创建模型对象","slug":"创建模型对象","link":"#创建模型对象","children":[]},{"level":2,"title":"写入数学模型","slug":"写入数学模型","link":"#写入数学模型","children":[{"level":3,"title":"创建目标函数","slug":"创建目标函数","link":"#创建目标函数","children":[]},{"level":3,"title":"添加约束方程","slug":"添加约束方程","link":"#添加约束方程","children":[]},{"level":3,"title":"设置变量类型","slug":"设置变量类型","link":"#设置变量类型","children":[]}]},{"level":2,"title":"模型求解和输出","slug":"模型求解和输出","link":"#模型求解和输出","children":[{"level":3,"title":"模型求解","slug":"模型求解-1","link":"#模型求解-1","children":[]},{"level":3,"title":"输出","slug":"输出","link":"#输出","children":[]}]},{"level":2,"title":"模型求解示例","slug":"模型求解示例","link":"#模型求解示例","children":[]},{"level":2,"title":"建模的一些技巧","slug":"建模的一些技巧","link":"#建模的一些技巧","children":[{"level":3,"title":"线性化","slug":"线性化","link":"#线性化","children":[]},{"level":3,"title":"中间变量的处理","slug":"中间变量的处理","link":"#中间变量的处理","children":[]}]}],"git":{"updatedTime":1700388430000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":5}]},"filePathRelative":"notes/lp.md","autoDesc":true}');export{e as data}; diff --git a/assets/lp.html-I7wRJlfF.js b/assets/lp.html-m-tLdpGS.js similarity index 99% rename from assets/lp.html-I7wRJlfF.js rename to assets/lp.html-m-tLdpGS.js index e5128cce..a897a9c6 100644 --- a/assets/lp.html-I7wRJlfF.js +++ b/assets/lp.html-m-tLdpGS.js @@ -1,4 +1,4 @@ -import{_ as u,r,o as i,c,a as s,b as a,d as p,w as n,e as t}from"./app-DaLjD81q.js";const h={},d=s("h1",{id:"模型求解",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#模型求解","aria-hidden":"true"},"#"),a(" 模型求解")],-1),g=s("p",null,"在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。",-1),v={class:"hint-container tip"},k=s("p",{class:"hint-container-title"},"提示",-1),y=t(`

创建模型对象

创建规划模型对象,存入变量lp中。

local lp = CreateLP()
+import{_ as u,r,o as i,c,a as s,b as a,d as p,w as n,e as t}from"./app-LOf__QKq.js";const h={},d=s("h1",{id:"模型求解",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#模型求解","aria-hidden":"true"},"#"),a(" 模型求解")],-1),g=s("p",null,"在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。",-1),v={class:"hint-container tip"},k=s("p",{class:"hint-container-title"},"提示",-1),y=t(`

创建模型对象

创建规划模型对象,存入变量lp中。

local lp = CreateLP()
 

官方文档中将创建的数学模型对象存入变量LPModel中,作用同本文的lp

写入数学模型

此时,数学模型的对象已经创建并存入了变量lp中,可以对其进行更进一步的操作。数学模型一般分为两个部分:

接下来,先介绍创建目标函数的具体做法。

创建目标函数

MicroCity中,使用SetObjectFunction()设置模型对象的目标函数。允许选择目标函数求最大值最小值。具体用法如下:

`,10),b=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token function"},"SetObjFunction"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"max"'),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"--求最大值"),a(` `)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),x=s("div",{class:"language-lua line-numbers-mode","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[s("span",{class:"token function"},"SetObjFunction"),s("span",{class:"token punctuation"},"("),a("lp"),s("span",{class:"token punctuation"},","),a(" coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},'"min"'),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"--求最小值"),a(` `)])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),_=t('

"min"和"max"不区分大小写,写"MIN"和"MAX"也可以

参数说明及示例

参数作用
lp数学模型对象。将数学模型输入函数中,为模型设置目标函数
coeff目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。
"min""max"确定目标函数求最大还是求最小。
',3),w=s("p",null,[s("code",null,"coeff"),a("是目标函数的系数列表,是一个"),s("code",null,"table"),a("类型的变量。假设你要求函数"),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"12"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"4x_1+12x_2+18x_3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"12"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a("的"),s("strong",null,"最小值"),a(",则添加目标函数的做法如下:")],-1),z=t(`
-- 假设你已经创建了模型对象,并存入变量lp中
diff --git a/assets/lp.html-yx0HpcA2.js b/assets/lp.html-yx0HpcA2.js
new file mode 100644
index 00000000..df227df7
--- /dev/null
+++ b/assets/lp.html-yx0HpcA2.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-a86f52cc","path":"/en/notes/lp.html","title":"Model Solving","lang":"en-US","frontmatter":{"description":"In MicroCity, mathematical models can be solved. In this article, we will introduce the common process of solving mathematical models in MicroCity and provide some tips to help ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/lp.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/lp.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Model Solving"}],["meta",{"property":"og:description","content":"In MicroCity, mathematical models can be solved. In this article, we will introduce the common process of solving mathematical models in MicroCity and provide some tips to help ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Model Solving\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Creating Model Objects","slug":"creating-model-objects","link":"#creating-model-objects","children":[]},{"level":2,"title":"Writing Mathematical Models","slug":"writing-mathematical-models","link":"#writing-mathematical-models","children":[{"level":3,"title":"Creating the Objective Function","slug":"creating-the-objective-function","link":"#creating-the-objective-function","children":[]},{"level":3,"title":"Adding Constraint Equations","slug":"adding-constraint-equations","link":"#adding-constraint-equations","children":[]},{"level":3,"title":"Set Variable Types","slug":"set-variable-types","link":"#set-variable-types","children":[]}]},{"level":2,"title":"Model Solving and Output","slug":"model-solving-and-output","link":"#model-solving-and-output","children":[{"level":3,"title":"Model Solving","slug":"model-solving-1","link":"#model-solving-1","children":[]},{"level":3,"title":"Output","slug":"output","link":"#output","children":[]}]},{"level":2,"title":"Model Solution Example","slug":"model-solution-example","link":"#model-solution-example","children":[]},{"level":2,"title":"Some Techniques for Modeling","slug":"some-techniques-for-modeling","link":"#some-techniques-for-modeling","children":[{"level":3,"title":"Linearization","slug":"linearization","link":"#linearization","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/lp.md","autoDesc":true}');export{e as data};
diff --git a/assets/lua.html--q1iToUD.js b/assets/lua.html--q1iToUD.js
new file mode 100644
index 00000000..5028592a
--- /dev/null
+++ b/assets/lua.html--q1iToUD.js
@@ -0,0 +1 @@
+const e=JSON.parse(`{"key":"v-29921fbc","path":"/en/notes/lua.html","title":"Quick Start with Lua Language","lang":"en-US","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,编程,脚本,lua"}],["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/lua.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/lua.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Quick Start with Lua Language"}],["meta",{"property":"og:description","content":"Since MicroCity uses the Lua scripting language, it is necessary to familiarize yourself with the basic usage of Lua before starting to write scripts with MicroCity. This articl..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Quick Start with Lua Language\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]],"description":"Since MicroCity uses the Lua scripting language, it is necessary to familiarize yourself with the basic usage of Lua before starting to write scripts with MicroCity. This articl..."},"headers":[{"level":2,"title":"Variable and Function Definition","slug":"variable-and-function-definition","link":"#variable-and-function-definition","children":[]},{"level":2,"title":"Condition","slug":"condition","link":"#condition","children":[]},{"level":2,"title":"Loop","slug":"loop","link":"#loop","children":[{"level":3,"title":"for","slug":"for","link":"#for","children":[]},{"level":3,"title":"while","slug":"while","link":"#while","children":[]},{"level":3,"title":"Loop Operators","slug":"loop-operators","link":"#loop-operators","children":[]}]},{"level":2,"title":"Lua's Small Feature: Tables","slug":"lua-s-small-feature-tables","link":"#lua-s-small-feature-tables","children":[{"level":3,"title":"Indexing","slug":"indexing","link":"#indexing","children":[]},{"level":3,"title":"Adding Elements","slug":"adding-elements","link":"#adding-elements","children":[]},{"level":3,"title":"Removing Elements","slug":"removing-elements","link":"#removing-elements","children":[]},{"level":3,"title":"Sorting a Table","slug":"sorting-a-table","link":"#sorting-a-table","children":[]},{"level":3,"title":"Reference of table","slug":"reference-of-table","link":"#reference-of-table","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/lua.md","autoDesc":true}`);export{e as data};
diff --git a/assets/lua.html-B6d7gWD8.js b/assets/lua.html-B6d7gWD8.js
new file mode 100644
index 00000000..0e40d3e3
--- /dev/null
+++ b/assets/lua.html-B6d7gWD8.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-ed3d82b0","path":"/notes/lua.html","title":"Lua语言快速上手","lang":"zh-CN","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,编程,脚本,lua"}],["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/lua.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/lua.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"Lua语言快速上手"}],["meta",{"property":"og:description","content":"由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。 变量和函数定义 lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。 函数..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:29:55.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:29:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Lua语言快速上手\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-14T13:29:55.000Z\\",\\"author\\":[]}"]],"description":"由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。 变量和函数定义 lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。 函数..."},"headers":[{"level":2,"title":"变量和函数定义","slug":"变量和函数定义","link":"#变量和函数定义","children":[]},{"level":2,"title":"条件","slug":"条件","link":"#条件","children":[]},{"level":2,"title":"循环","slug":"循环","link":"#循环","children":[{"level":3,"title":"for","slug":"for","link":"#for","children":[]},{"level":3,"title":"while","slug":"while","link":"#while","children":[]},{"level":3,"title":"循环操作符","slug":"循环操作符","link":"#循环操作符","children":[]}]},{"level":2,"title":"Lua的小特性:表","slug":"lua的小特性-表","link":"#lua的小特性-表","children":[{"level":3,"title":"索引","slug":"索引","link":"#索引","children":[]},{"level":3,"title":"添加元素","slug":"添加元素","link":"#添加元素","children":[]},{"level":3,"title":"删除元素","slug":"删除元素","link":"#删除元素","children":[]},{"level":3,"title":"table的排序","slug":"table的排序","link":"#table的排序","children":[]},{"level":3,"title":"table的引用","slug":"table的引用","link":"#table的引用","children":[]}]}],"git":{"updatedTime":1699968595000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":11}]},"filePathRelative":"notes/lua.md","autoDesc":true}');export{e as data};
diff --git a/assets/lua.html-x5twFLDp.js b/assets/lua.html-JK5rP34K.js
similarity index 99%
rename from assets/lua.html-x5twFLDp.js
rename to assets/lua.html-JK5rP34K.js
index 4c4dbcb3..4bd7ce32 100644
--- a/assets/lua.html-x5twFLDp.js
+++ b/assets/lua.html-JK5rP34K.js
@@ -1,4 +1,4 @@
-import{_ as n,o as s,c as a,e}from"./app-DaLjD81q.js";const t={},p=e(`

Lua语言快速上手

由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。

变量和函数定义

lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。

a = 1.5
+import{_ as n,o as s,c as a,e}from"./app-LOf__QKq.js";const t={},p=e(`

Lua语言快速上手

由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。

变量和函数定义

lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。

a = 1.5
 b = "string"
 c = {} -- c为表,见下文介绍
 

函数的定义

function add(a, b)
diff --git a/assets/lua.html-bIzYAnJl.js b/assets/lua.html-bIzYAnJl.js
new file mode 100644
index 00000000..2d2d1e3d
--- /dev/null
+++ b/assets/lua.html-bIzYAnJl.js
@@ -0,0 +1,209 @@
+import{_ as e,r as t,o,c as p,a as n,b as s,d as i,e as l}from"./app-LOf__QKq.js";const c={},u=l(`

Quick Start with Lua Language

Since MicroCity uses the Lua scripting language, it is necessary to familiarize yourself with the basic usage of Lua before starting to write scripts with MicroCity. This article introduces the commonly used syntax for writing Lua scripts in MicroCity, which can help you quickly understand the overall approach to writing MicroCity scripts based on concepts from other programming languages.

Variable and Function Definition

Lua automatically recognizes variable types, so there is no need to define variable types before variable names. You can assign values directly.

a = 1.5
+b = "string"
+c = {} -- c is a table, explained below
+

Function definition

function add(a, b)
+    return a + b
+end
+

Above is a simple definition of the add() function, which aims to add the two input variables and return the result.

Variables can be global or local, and functions are the same. Here is how to define local variables and functions.

-- Define a local function
+local function show(msg)
+    print(msg)
+end
+
+-- Define a local variable
+local a = 1
+

If there is a conflict between locally defined content (function or variable) and globally defined content, the locally defined content takes precedence. When such a conflict exists, the content you are operating on is the local content.

If there is no explicit need to manipulate global variables, it is recommended to define variables as local variables as much as possible. This practice may reduce the occurrence of bugs and is a safer approach.

Condition

It's all about if, and there are several specific forms of implementation:

  1. Normal form
if condition then
+    print("condition==true")
+end
+
  1. Form with else
if condition then
+    print("condition==true")
+else
+    print("condition==false")
+end
+
  1. Form with elseif
if number > 0 then
+    print("number>0")
+elseif number < 0 then
+    print("number<0")
+else
+    print("number==0")
+end
+

In Lua, the equality operator is ==, and the inequality operator is ~=. You can apply these operators to conditional expressions. Here is a simple example:

print(1==1) -- true
+print(1~=1) -- false
+

Loop

Here are two most commonly used loops: for and while.

for

The simplest form

-- Output numbers from 1 to 10, a total of 10 numbers
+for i = 1,10 do
+    print(i)
+end
+

If you are familiar with C or C-like languages, the corresponding form of the above code is as follows:

for(int i=1; i<=10; i++){
+    printf("%d\\n",i);
+}
+

Taking step size into consideration

-- Output numbers from 10 to 1, a total of 10 numbers with a step size of -1
+for i = 10,1,-1 do
+    print(i)
+end
+

When the step size is negative, it is important to note that the starting and ending numbers should be in reverse order.

Generic loop You can directly traverse all elements in a table. i is the index of the table element, starting from 1; v is the value of the table element.

a = {4,7,9}
+for i,v in ipairs(a) do
+    print("index=",i,"\\tvalue=",v)
+end
+

ipairs is used for arrays (guessing i stands for integer), and pairs is used for objects. Since arrays are also objects, pairs can be used for arrays as well.

while

There is only one commonly used method for while.

local condition = true
+while condition do
+    print("while==true")
+    condition = false
+end
+

Similar to C-like languages. As long as condition is true, while will continue to run. When condition is set to false, the while loop will end.

Loop Operators

Just like in other languages, the break keyword is used to exit a loop. In Lua, there is no continue, only break. However, the continue functionality can be achieved by using the if + break structure.

Lua's Small Feature: Tables

Although Lua refers to its arrays as tables, I think this data structure is more similar to Python sets or JSON, as it can store anything without any structural constraints.

collection = {{"a", 1, 2}, "abc", {2, 3}}
+

To find the length of an array, simply prepend # before the array name.

list = {1, 2, 3, 4, 5}
+for i=1,#list do
+    print(list[i])
+end
+

In Lua, array (table) indices start from 1, unlike C-like languages where they start from 0. Taking the previously defined collection as an example:

-- collection = {{"a", 1, 2}, "abc", {2, 3}}
+print(collection[1][1]) -- a
+print(collection[2]) -- abc
+print(collection[3][2]) -- 3
+

Indexing

Lua table indexing is very flexible and can be done with numbers, strings, or even other types of data.

Here are some simple examples:

local list = {}
+
+-- Indexing with numbers
+list[1] = "a"
+
+-- Indexing with strings
+list["b"] = 2
+list.message = "hello world" -- Equivalent to list["message"] = "hello world"
+
+print(list[1]) -- a
+print(list["b"]) -- 2
+print(list.message) -- hello world
+

Adding Elements

Adding to a specific position

table.insert(table, pos, value) -- Inserts an element at a specific position (pos)
+

Or

table.insert(table, value) -- Appends an element at the end
+

Example

list = {1, 2, 3, 4, 5}
+table.insert(list, 6)
+-- {1, 2, 3, 4, 5, 6}
+

Removing Elements

table.remove(table, pos) -- Removes an element at a specific position
+

Example

list = {1, 2, 3, 4, 5}
+table.remove(list, 2)
+-- {1, 3, 4, 5}
+

Sorting a Table

Default Sorting Method

You can use a function to sort a list, and the simplest usage is as follows:

table.sort(list) -- Sorts the list in ascending order
+

Here is an example:

-- Function: Print List
+function PrintList(list)
+    -- Output the list
+    local listStr = ""
+    for i = 1, #list do
+        listStr = listStr .. list[i] .. " "
+    end
+    print(listStr)
+end
+
+local list = { 3, 7, 2, 5, 4 } -- Original list
+
+PrintList(list) -- Output the original list
+table.sort(list) -- Sort the list
+PrintList(list) -- Output the sorted list
+
+-- Result:
+-- 3 7 2 5 4 (Original list)
+-- 2 3 4 5 7 (Sorted list)
+

Custom Sorting Method

The table.sort function can also use a custom sorting rule, but this rule needs to be written in a function.

table.sort(list, function(a, b))
+

The function(a, b) is the custom sorting rule, which requires returning a boolean value (true or false) in the end. a and b are any two items in the list, and if the function returns true, then a comes before b, otherwise b comes before a.

Below are two examples for reference.

Example 1: Changing the code above to output in descending order
-- The PrintList() function is omitted here, with the same code as above
+
+local list = { 3, 7, 2, 5, 4 } -- Original list
+
+PrintList(list) -- Output the original list
+table.sort(list, function(a, b) -- Sort the list
+    return a > b -- Sort in descending order, if a > b, then a comes before b
+end)
+PrintList(list) -- Output the sorted list
+
+-- Output:
+-- 3 7 2 5 4 (Original list)
+-- 7 5 4 3 2 (Sorted list)
+
Example 2: Sorting in a two-dimensional array
-- Function: Print the list
+function PrintList(list)
+    -- Output the list
+    local listStr = ""
+    for i = 1, #list do
+        listStr = listStr .. "\\n" .. list[i][1] .. ", " .. list[i][2]
+    end
+    print(listStr)
+end
+
+ -- Original list
+local list = { { 3, 5 }, { 7, 6 }, { 2, 2 }, { 5, 1 }, { 4, 3 } }
+
+PrintList(list) -- Output the original list
+
+-- Sort in descending order based on the first dimension of each item in the list
+table.sort(list, function(a, b)
+    return a[1] > b[1]
+end)
+PrintList(list) -- Output the sorted list
+
+-- Sort in descending order based on the second dimension of each item in the list
+table.sort(list, function(a, b)
+    return a[2] > b[2] 
+end)
+PrintList(list) -- Output the sorted list
+
+-- Output:
+-- Original list:
+-- 3, 5
+-- 7, 6
+-- 2, 2
+-- 5, 1
+-- 4, 3
+
+-- Sorted based on the first dimension:
+-- 7, 6
+-- 5, 1
+-- 4, 3
+-- 3, 5
+-- 2, 2
+
+-- Sorted based on the second dimension:
+-- 7, 6
+-- 3, 5
+-- 4, 3
+-- 2, 2
+-- 5, 1
+

Reference of table

When there is no deep copy of a table, and it is directly copied, the newly obtained list2 is equivalent to a reference to the original list1, known as shallow copy. When you modify the elements in list2 obtained from shallow copy, the elements in list1 will also change because the two tables are referenced.

The above example code also follows this principle. Below is a new example to highlight this characteristic.

Example: Shallow Copy

function PrintList(list)
+    -- Output the list
+    local listStr = ""
+    for i = 1, #list do
+        listStr = listStr .. list[i] .. " "
+    end
+    print(listStr)
+end
+
+list1 = { 1, 2, 3, 4, 5 }
+PrintList(list1)
+-- 1 2 3 4 5
+
+list2 = list1
+PrintList(list2)
+-- 1 2 3 4 5
+
+-- Modify the second element in list2
+list2[2] = 10
+PrintList(list2)
+-- 1 10 3 4 5
+
+PrintList(list1)
+-- 1 10 3 4 5
+

Example: Deep Copy

And what if you want to create a completely new list list2? Then you need to copy each element in the table one by one, also known as deep copy.

-- PrintList function code remains the same as above
+
+list1 = { 1, 2, 3, 4, 5 }
+PrintList(list1)
+-- 1 2 3 4 5
+
+list2 = {} -- Create a new empty list
+
+-- Copy elements from list1 to list2
+for index, value in pairs(list1) do
+    table.insert(list2, value)
+end
+PrintList(list2)
+-- 1 2 3 4 5
+
+-- Modify the 2nd element of list2
+list2[2] = 10
+PrintList(list2)
+-- 1 10 3 4 5
+
+PrintList(list1)
+-- 1 2 3 4 5 (no changes occurred)
+

In this example, modifying the elements in the deep copy list2 does not affect the original list1.

`,87),r={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},d=n("strong",null,"feedback",-1);function k(m,v){const a=t("ExternalLinkIcon");return o(),p("div",null,[u,n("blockquote",null,[n("p",null,[s("This post is translated using ChatGPT, please "),n("a",r,[d,i(a)]),s(" if any omissions.")])])])}const h=e(c,[["render",k],["__file","lua.html.vue"]]);export{h as default}; diff --git a/assets/lua.html-zCkaxI4j.js b/assets/lua.html-zCkaxI4j.js deleted file mode 100644 index b2e764b0..00000000 --- a/assets/lua.html-zCkaxI4j.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-ed3d82b0","path":"/notes/lua.html","title":"Lua语言快速上手","lang":"zh-CN","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,编程,脚本,lua"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/lua.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"Lua语言快速上手"}],["meta",{"property":"og:description","content":"由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。 变量和函数定义 lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。 函数..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:29:55.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:29:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Lua语言快速上手\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-14T13:29:55.000Z\\",\\"author\\":[]}"]],"description":"由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。 变量和函数定义 lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。 函数..."},"headers":[{"level":2,"title":"变量和函数定义","slug":"变量和函数定义","link":"#变量和函数定义","children":[]},{"level":2,"title":"条件","slug":"条件","link":"#条件","children":[]},{"level":2,"title":"循环","slug":"循环","link":"#循环","children":[{"level":3,"title":"for","slug":"for","link":"#for","children":[]},{"level":3,"title":"while","slug":"while","link":"#while","children":[]},{"level":3,"title":"循环操作符","slug":"循环操作符","link":"#循环操作符","children":[]}]},{"level":2,"title":"Lua的小特性:表","slug":"lua的小特性-表","link":"#lua的小特性-表","children":[{"level":3,"title":"索引","slug":"索引","link":"#索引","children":[]},{"level":3,"title":"添加元素","slug":"添加元素","link":"#添加元素","children":[]},{"level":3,"title":"删除元素","slug":"删除元素","link":"#删除元素","children":[]},{"level":3,"title":"table的排序","slug":"table的排序","link":"#table的排序","children":[]},{"level":3,"title":"table的引用","slug":"table的引用","link":"#table的引用","children":[]}]}],"git":{"updatedTime":1699968595000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":11}]},"filePathRelative":"notes/lua.md","autoDesc":true}');export{e as data}; diff --git a/assets/main_window-T08x4hNs.js b/assets/main_window-T08x4hNs.js new file mode 100644 index 00000000..6f6286f8 --- /dev/null +++ b/assets/main_window-T08x4hNs.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/main_window-kvL2HSJd.png";export{s as _}; diff --git a/assets/mip-en.html-23DYx6JR.js b/assets/mip-en.html-23DYx6JR.js deleted file mode 100644 index 68801d10..00000000 --- a/assets/mip-en.html-23DYx6JR.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-6eb109a0","path":"/notes/mip-en.html","title":"Mixed integer programming","lang":"zh-CN","frontmatter":{"description":"Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This a...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/mip-en.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"Mixed integer programming"}],["meta",{"property":"og:description","content":"Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This a..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Mixed integer programming\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Creating a Mixed-Integer Programming Model","slug":"creating-a-mixed-integer-programming-model","link":"#creating-a-mixed-integer-programming-model","children":[]},{"level":2,"title":"Setting the Objective Function","slug":"setting-the-objective-function","link":"#setting-the-objective-function","children":[]},{"level":2,"title":"Adding Constraints","slug":"adding-constraints","link":"#adding-constraints","children":[{"level":3,"title":"Adding Constraint Equations","slug":"adding-constraint-equations","link":"#adding-constraint-equations","children":[]},{"level":3,"title":"Setting Variable Types","slug":"setting-variable-types","link":"#setting-variable-types","children":[]}]},{"level":2,"title":"Model Solution and Output","slug":"model-solution-and-output","link":"#model-solution-and-output","children":[{"level":3,"title":"Model Solution","slug":"model-solution","link":"#model-solution","children":[]},{"level":3,"title":"Output","slug":"output","link":"#output","children":[]}]},{"level":2,"title":"Some Modeling Techniques","slug":"some-modeling-techniques","link":"#some-modeling-techniques","children":[{"level":3,"title":"Linearization","slug":"linearization","link":"#linearization","children":[]},{"level":3,"title":"Handling Intermediate Variables","slug":"handling-intermediate-variables","link":"#handling-intermediate-variables","children":[]}]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/mip-en.md","autoDesc":true}');export{e as data}; diff --git a/assets/mip.html-6_WAczY6.js b/assets/mip.html-6_WAczY6.js new file mode 100644 index 00000000..0a64640a --- /dev/null +++ b/assets/mip.html-6_WAczY6.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-dfdf5468","path":"/notes/mip.html","title":"混合整数规划","lang":"zh-CN","frontmatter":{"description":"本文档介绍MicroCity Web中混合整数规划的建模方法。 创建混合整数规划模型 创建整数规划模型对象 设置目标函数 MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。 允许选择目标函数求最大值或最小值。具体用法如下: tab:active 最大值@tab 最小值 参数说明及示例 参数 作用 -------...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/mip.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/mip.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"混合整数规划"}],["meta",{"property":"og:description","content":"本文档介绍MicroCity Web中混合整数规划的建模方法。 创建混合整数规划模型 创建整数规划模型对象 设置目标函数 MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。 允许选择目标函数求最大值或最小值。具体用法如下: tab:active 最大值@tab 最小值 参数说明及示例 参数 作用 -------..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"混合整数规划\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"创建混合整数规划模型","slug":"创建混合整数规划模型","link":"#创建混合整数规划模型","children":[]},{"level":2,"title":"设置目标函数","slug":"设置目标函数","link":"#设置目标函数","children":[]},{"level":2,"title":"添加约束","slug":"添加约束","link":"#添加约束","children":[{"level":3,"title":"添加约束方程","slug":"添加约束方程","link":"#添加约束方程","children":[]},{"level":3,"title":"设置变量类型","slug":"设置变量类型","link":"#设置变量类型","children":[]}]},{"level":2,"title":"模型求解和输出","slug":"模型求解和输出","link":"#模型求解和输出","children":[{"level":3,"title":"模型求解","slug":"模型求解","link":"#模型求解","children":[]},{"level":3,"title":"输出","slug":"输出","link":"#输出","children":[]}]},{"level":2,"title":"建模的一些技巧","slug":"建模的一些技巧","link":"#建模的一些技巧","children":[{"level":3,"title":"线性化","slug":"线性化","link":"#线性化","children":[]},{"level":3,"title":"中间变量的处理","slug":"中间变量的处理","link":"#中间变量的处理","children":[]}]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/mip.md","autoDesc":true}');export{e as data}; diff --git a/assets/mip-en.html-IS2AhQjv.js b/assets/mip.html-7cWhLBPI.js similarity index 99% rename from assets/mip-en.html-IS2AhQjv.js rename to assets/mip.html-7cWhLBPI.js index 96eb4e89..f3434a85 100644 --- a/assets/mip-en.html-IS2AhQjv.js +++ b/assets/mip.html-7cWhLBPI.js @@ -1,4 +1,4 @@ -import{_ as u,r,o as p,c as i,d as m,w as t,b as a,a as s,e as n}from"./app-DaLjD81q.js";const h={},d=n(`

Mixed integer programming

Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web.

Translate info

This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.

Creating a Mixed-Integer Programming Model

Creating an integer programming model object.

local mip = math.newmip() -- Assign the created model object to mip
+import{_ as u,r,o as p,c as i,d as m,w as t,b as a,a as s,e as n}from"./app-LOf__QKq.js";const h={},d=n(`

Mixed integer programming

Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web.

Translate info

This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.

Creating a Mixed-Integer Programming Model

Creating an integer programming model object.

local mip = math.newmip() -- Assign the created model object to mip
 

Setting the Objective Function

In MicroCity Web, the first line of the model is the objective function, added using the mip:addrow() function.

You can choose to maximize or minimize the objective function. The usage is as follows:

`,9),g=s("div",{class:"language-lua","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[a("mip"),s("span",{class:"token punctuation"},":"),s("span",{class:"token function"},"addrow"),s("span",{class:"token punctuation"},"("),a("coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},"'max'"),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"-- Maximize the objective function"),a(` `)])])],-1),v=s("div",{class:"language-lua","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[a("mip"),s("span",{class:"token punctuation"},":"),s("span",{class:"token function"},"addrow"),s("span",{class:"token punctuation"},"("),a("coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},"'min'"),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"-- Minimize the objective function"),a(` `)])])],-1),k=n('

Parameter Description and Examples

ParameterPurpose
mipMathematical model object. Sets the objective function for the model
coeffCoefficients of the objective function, a table variable. Determines the coefficients of the objective function in the model.
"min" or "max"Determines whether to minimize or maximize the objective function.

coeff is a list of coefficients for the objective function, a table variable. Suppose you want to minimize the function

',3),y=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"12"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"}," 4x_1+12x_2+18x_3 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"12"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])],-1),b=n(`

the approach to adding the objective function is as follows:

-- Assuming you have already created the model object and stored it in the variable mip
@@ -126,4 +126,4 @@ x[4][2]= 1.0
 
`,4),$s={class:"hint-container tip"},sa=s("p",{class:"hint-container-title"},"Online Execution",-1),aa={href:"https://microcity.gitee.io/#s445tk",target:"_blank",rel:"noopener noreferrer"},na=s("table",null,[s("thead",null,[s("tr",null,[s("th",null,"Result"),s("th",null,"Person"),s("th",null,"Item")])]),s("tbody",null,[s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"13")]),s("mo",null,"="),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"x_{13}=1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"13")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])])]),s("td",null,"A"),s("td",null,"C")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"21")]),s("mo",null,"="),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"x_{21}=1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"21")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])])]),s("td",null,"B"),s("td",null,"A")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"34")]),s("mo",null,"="),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"x_{34}=1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"34")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])])]),s("td",null,"C"),s("td",null,"D")]),s("tr",null,[s("td",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"42")]),s("mo",null,"="),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"x_{42}=1")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.5806em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mtight"},"42")])])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1")])])])]),s("td",null,"D"),s("td",null,"B")])])],-1),ta=s("h3",{id:"handling-intermediate-variables",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#handling-intermediate-variables","aria-hidden":"true"},"#"),a(" Handling Intermediate Variables")],-1),la=s("p",null,[a("Sometimes, there are intermediate variables in a model that must have corresponding positions in the matrix to be solved, and these intermediate variables do not participate in the calculation of the objective function value. "),s("strong",null,"The coefficients of the intermediate variables at their corresponding positions can be set to 0.")],-1),ea=s("p",null,[a("Suppose "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"x"),s("mn",null,"4")])]),s("annotation",{encoding:"application/x-tex"},"x_1, x_2, x_3, x_4")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" are decision variables, and "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msub",null,[s("mi",null,"y"),s("mn",null,"1")]),s("mo",{separator:"true"},","),s("msub",null,[s("mi",null,"y"),s("mn",null,"2")])]),s("annotation",{encoding:"application/x-tex"},"y_1, y_2")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])]),a(" are intermediate variables. The objective function is:")],-1),pa=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"z"),s("mo",null,"="),s("munderover",null,[s("mo",null,"∑"),s("mrow",null,[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"1")]),s("mn",null,"4")]),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")])]),s("annotation",{encoding:"application/x-tex"}," z=\\sum_{i=1}^4x_i ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.04398em"}},"z"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"3.0788em","vertical-align":"-1.2777em"}}),s("span",{class:"mop op-limits"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.8011em"}},[s("span",{style:{top:"-1.8723em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},[s("span",{class:"mord mathnormal mtight"},"i"),s("span",{class:"mrel mtight"},"="),s("span",{class:"mord mtight"},"1")])])]),s("span",{style:{top:"-3.05em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",null,[s("span",{class:"mop op-symbol large-op"},"∑")])]),s("span",{style:{top:"-4.3em","margin-left":"0em"}},[s("span",{class:"pstrut",style:{height:"3.05em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"4")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"1.2777em"}},[s("span")])])])]),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3117em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"i")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])],-1),ia=n(`

The coefficients of the objective function can be set as follows:

local fcons = {1, 1, 1, 1, 0, 0}
 -- The first 4 elements correspond to decision variables,
 -- and the last 2 elements correspond to intermediate variables
-

Afterward, you can proceed with the general process 😎

`,3);function ma(ca,oa){const c=r("CodeTabs"),o=r("ExternalLinkIcon");return p(),i("div",null,[d,m(c,{id:"27",data:[{id:"Maximize"},{id:"Minimize"}],active:0,"tab-id":"shell"},{title0:t(({value:l,isActive:e})=>[a("Maximize")]),title1:t(({value:l,isActive:e})=>[a("Minimize")]),tab0:t(({value:l,isActive:e})=>[g]),tab1:t(({value:l,isActive:e})=>[v]),_:1}),k,y,b,m(c,{id:"93",data:[{id:"≥"},{id:"="}],"tab-id":"shell @tab:active ≤"},{title0:t(({value:l,isActive:e})=>[a("≥")]),title1:t(({value:l,isActive:e})=>[a("=")]),tab0:t(({value:l,isActive:e})=>[x]),tab1:t(({value:l,isActive:e})=>[w]),_:1}),f,_,z,M,m(c,{id:"174",data:[{id:"Integer Variable"},{id:"0-1 Variable"}],"tab-id":"shell"},{title0:t(({value:l,isActive:e})=>[a("Integer Variable")]),title1:t(({value:l,isActive:e})=>[a("0-1 Variable")]),tab0:t(({value:l,isActive:e})=>[j]),tab1:t(({value:l,isActive:e})=>[q]),_:1}),A,s("p",L,[s("span",C,[s("span",S,[T,s("span",I,[H,s("span",V,[B,s("span",D,[s("span",O,[s("span",P,[s("span",E,[s("span",N,[s("span",F,[Y,s("span",R,[W,s("span",G,[(p(),i("svg",Z,K))])]),Q,s("span",U,[X,s("span",$,[(p(),i("svg",ss,ns))])]),ts]),ls]),es])])]),ps])])])])])]),is,s("div",ms,[cs,s("p",null,[a("Check this "),s("a",os,[a("example"),m(o)]),a(" in MicroCityWeb")])]),rs,us,hs,ds,gs,vs,ks,ys,bs,s("p",xs,[s("span",ws,[s("span",fs,[_s,s("span",zs,[Ms,s("span",js,[qs,s("span",As,[s("span",Ls,[s("span",Cs,[s("span",Ss,[s("span",Ts,[s("span",Is,[Hs,s("span",Vs,[Bs,s("span",Ds,[(p(),i("svg",Os,Es))])]),Ns,s("span",Fs,[Ys,s("span",Rs,[(p(),i("svg",Ws,Zs))])]),Js]),Ks]),Qs])])]),Us])])])])])]),Xs,s("div",$s,[sa,s("p",null,[a("Check this "),s("a",aa,[a("example"),m(o)]),a(" in MicroCityWeb")])]),na,ta,la,ea,pa,ia])}const ua=u(h,[["render",ma],["__file","mip-en.html.vue"]]);export{ua as default}; +

Afterward, you can proceed with the general process 😎

`,3);function ma(ca,oa){const c=r("CodeTabs"),o=r("ExternalLinkIcon");return p(),i("div",null,[d,m(c,{id:"27",data:[{id:"Maximize"},{id:"Minimize"}],active:0,"tab-id":"shell"},{title0:t(({value:l,isActive:e})=>[a("Maximize")]),title1:t(({value:l,isActive:e})=>[a("Minimize")]),tab0:t(({value:l,isActive:e})=>[g]),tab1:t(({value:l,isActive:e})=>[v]),_:1}),k,y,b,m(c,{id:"93",data:[{id:"≥"},{id:"="}],"tab-id":"shell @tab:active ≤"},{title0:t(({value:l,isActive:e})=>[a("≥")]),title1:t(({value:l,isActive:e})=>[a("=")]),tab0:t(({value:l,isActive:e})=>[x]),tab1:t(({value:l,isActive:e})=>[w]),_:1}),f,_,z,M,m(c,{id:"174",data:[{id:"Integer Variable"},{id:"0-1 Variable"}],"tab-id":"shell"},{title0:t(({value:l,isActive:e})=>[a("Integer Variable")]),title1:t(({value:l,isActive:e})=>[a("0-1 Variable")]),tab0:t(({value:l,isActive:e})=>[j]),tab1:t(({value:l,isActive:e})=>[q]),_:1}),A,s("p",L,[s("span",C,[s("span",S,[T,s("span",I,[H,s("span",V,[B,s("span",D,[s("span",O,[s("span",P,[s("span",E,[s("span",N,[s("span",F,[Y,s("span",R,[W,s("span",G,[(p(),i("svg",Z,K))])]),Q,s("span",U,[X,s("span",$,[(p(),i("svg",ss,ns))])]),ts]),ls]),es])])]),ps])])])])])]),is,s("div",ms,[cs,s("p",null,[a("Check this "),s("a",os,[a("example"),m(o)]),a(" in MicroCityWeb")])]),rs,us,hs,ds,gs,vs,ks,ys,bs,s("p",xs,[s("span",ws,[s("span",fs,[_s,s("span",zs,[Ms,s("span",js,[qs,s("span",As,[s("span",Ls,[s("span",Cs,[s("span",Ss,[s("span",Ts,[s("span",Is,[Hs,s("span",Vs,[Bs,s("span",Ds,[(p(),i("svg",Os,Es))])]),Ns,s("span",Fs,[Ys,s("span",Rs,[(p(),i("svg",Ws,Zs))])]),Js]),Ks]),Qs])])]),Us])])])])])]),Xs,s("div",$s,[sa,s("p",null,[a("Check this "),s("a",aa,[a("example"),m(o)]),a(" in MicroCityWeb")])]),na,ta,la,ea,pa,ia])}const ua=u(h,[["render",ma],["__file","mip.html.vue"]]);export{ua as default}; diff --git a/assets/mip.html-B6IhijhB.js b/assets/mip.html-B6IhijhB.js deleted file mode 100644 index c43a175f..00000000 --- a/assets/mip.html-B6IhijhB.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-dfdf5468","path":"/notes/mip.html","title":"混合整数规划","lang":"zh-CN","frontmatter":{"description":"本文档介绍MicroCity Web中混合整数规划的建模方法。 创建混合整数规划模型 创建整数规划模型对象 设置目标函数 MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。 允许选择目标函数求最大值或最小值。具体用法如下: tab:active 最大值@tab 最小值 参数说明及示例 参数 作用 -------...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/mip.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"混合整数规划"}],["meta",{"property":"og:description","content":"本文档介绍MicroCity Web中混合整数规划的建模方法。 创建混合整数规划模型 创建整数规划模型对象 设置目标函数 MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。 允许选择目标函数求最大值或最小值。具体用法如下: tab:active 最大值@tab 最小值 参数说明及示例 参数 作用 -------..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"混合整数规划\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"创建混合整数规划模型","slug":"创建混合整数规划模型","link":"#创建混合整数规划模型","children":[]},{"level":2,"title":"设置目标函数","slug":"设置目标函数","link":"#设置目标函数","children":[]},{"level":2,"title":"添加约束","slug":"添加约束","link":"#添加约束","children":[{"level":3,"title":"添加约束方程","slug":"添加约束方程","link":"#添加约束方程","children":[]},{"level":3,"title":"设置变量类型","slug":"设置变量类型","link":"#设置变量类型","children":[]}]},{"level":2,"title":"模型求解和输出","slug":"模型求解和输出","link":"#模型求解和输出","children":[{"level":3,"title":"模型求解","slug":"模型求解","link":"#模型求解","children":[]},{"level":3,"title":"输出","slug":"输出","link":"#输出","children":[]}]},{"level":2,"title":"建模的一些技巧","slug":"建模的一些技巧","link":"#建模的一些技巧","children":[{"level":3,"title":"线性化","slug":"线性化","link":"#线性化","children":[]},{"level":3,"title":"中间变量的处理","slug":"中间变量的处理","link":"#中间变量的处理","children":[]}]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/mip.md","autoDesc":true}');export{e as data}; diff --git a/assets/mip.html-EzteSB1w.js b/assets/mip.html-EzteSB1w.js new file mode 100644 index 00000000..c2477e60 --- /dev/null +++ b/assets/mip.html-EzteSB1w.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-304136e0","path":"/en/notes/mip.html","title":"Mixed integer programming","lang":"en-US","frontmatter":{"description":"Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This a...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/mip.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/mip.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Mixed integer programming"}],["meta",{"property":"og:description","content":"Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This a..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Mixed integer programming\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Creating a Mixed-Integer Programming Model","slug":"creating-a-mixed-integer-programming-model","link":"#creating-a-mixed-integer-programming-model","children":[]},{"level":2,"title":"Setting the Objective Function","slug":"setting-the-objective-function","link":"#setting-the-objective-function","children":[]},{"level":2,"title":"Adding Constraints","slug":"adding-constraints","link":"#adding-constraints","children":[{"level":3,"title":"Adding Constraint Equations","slug":"adding-constraint-equations","link":"#adding-constraint-equations","children":[]},{"level":3,"title":"Setting Variable Types","slug":"setting-variable-types","link":"#setting-variable-types","children":[]}]},{"level":2,"title":"Model Solution and Output","slug":"model-solution-and-output","link":"#model-solution-and-output","children":[{"level":3,"title":"Model Solution","slug":"model-solution","link":"#model-solution","children":[]},{"level":3,"title":"Output","slug":"output","link":"#output","children":[]}]},{"level":2,"title":"Some Modeling Techniques","slug":"some-modeling-techniques","link":"#some-modeling-techniques","children":[{"level":3,"title":"Linearization","slug":"linearization","link":"#linearization","children":[]},{"level":3,"title":"Handling Intermediate Variables","slug":"handling-intermediate-variables","link":"#handling-intermediate-variables","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/mip.md","autoDesc":true}');export{e as data}; diff --git a/assets/mip.html-Jt_OOSuJ.js b/assets/mip.html-KGIauE4D.js similarity index 99% rename from assets/mip.html-Jt_OOSuJ.js rename to assets/mip.html-KGIauE4D.js index 047fd674..900d6360 100644 --- a/assets/mip.html-Jt_OOSuJ.js +++ b/assets/mip.html-KGIauE4D.js @@ -1,4 +1,4 @@ -import{_ as u,r,o as p,c as i,d as m,w as t,b as a,a as s,e as n}from"./app-DaLjD81q.js";const h={},d=n(`

混合整数规划

本文档介绍MicroCity Web中混合整数规划的建模方法。

创建混合整数规划模型

创建整数规划模型对象

local mip = math.newmip() -- 将创建的模型对象赋值给 mip
+import{_ as u,r,o as p,c as i,d as m,w as t,b as a,a as s,e as n}from"./app-LOf__QKq.js";const h={},d=n(`

混合整数规划

本文档介绍MicroCity Web中混合整数规划的建模方法。

创建混合整数规划模型

创建整数规划模型对象

local mip = math.newmip() -- 将创建的模型对象赋值给 mip
 

设置目标函数

MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。

允许选择目标函数求最大值最小值。具体用法如下:

`,8),g=s("div",{class:"language-lua","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[a("mip"),s("span",{class:"token punctuation"},":"),s("span",{class:"token function"},"addrow"),s("span",{class:"token punctuation"},"("),a("coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},"'max'"),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"--求最大值"),a(` `)])])],-1),v=s("div",{class:"language-lua","data-ext":"lua"},[s("pre",{class:"language-lua"},[s("code",null,[a("mip"),s("span",{class:"token punctuation"},":"),s("span",{class:"token function"},"addrow"),s("span",{class:"token punctuation"},"("),a("coeff"),s("span",{class:"token punctuation"},","),a(),s("span",{class:"token string"},"'min'"),s("span",{class:"token punctuation"},")"),a(),s("span",{class:"token comment"},"--求最小值"),a(` `)])])],-1),k=n('

参数说明及示例

参数作用
mip数学模型对象。将数学模型输入函数中,为模型设置目标函数
coeff目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。
"min""max"确定目标函数求最大还是求最小。

coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数

',3),y=s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("msub",null,[s("mi",null,"x"),s("mn",null,"1")]),s("mo",null,"+"),s("mn",null,"12"),s("msub",null,[s("mi",null,"x"),s("mn",null,"2")]),s("mo",null,"+"),s("mn",null,"18"),s("msub",null,[s("mi",null,"x"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"}," 4x_1+12x_2+18x_3 ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"1")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"12"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"+"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7944em","vertical-align":"-0.15em"}}),s("span",{class:"mord"},"18"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal"},"x"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"0em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])])])])])])],-1),b=n(`

最小值,则添加目标函数的做法如下:

-- 假设你已经创建了模型对象,并存入变量mip中
diff --git a/assets/module_settings-yrsWXh8u.js b/assets/module_settings-yrsWXh8u.js
new file mode 100644
index 00000000..520ef8b3
--- /dev/null
+++ b/assets/module_settings-yrsWXh8u.js
@@ -0,0 +1 @@
+const A="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAP8AAAFjCAMAAADFBS10AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKyUExURf///6CgoOPj4wB416WlpYKHkGlpafDw8PLy8tzc3MzMzAAAAPHx8fz8/I6Ojqurq9TU1AAAhAAA/9fX1//bkAD///DOhzo6kNv//87w8Kvw8PLyrKzy8gCQ7PKsYQA2iDYAADp418/y8rb//4fO8JGRkWEAADYAYPDOhtvq7PLPiDY2h2Gs8gAAYfLyzzoAZvr7+zU1hog2AAAANmCr8DaIz/Dwq/CrYABhrIjP8vDwzpCQ15Db/21tbWEAYQAAYAA2h9vbkP+2ZgCo8mZ4186HNv39/axhAAB43s+INgA6kDoAAGa2/wBgqwCt/4c2Nv//tmAAAO3t7DYANjUAAAB45f7+/v//26tgAP/q7GbU/zqQ27ao1zaHzpDq/4c2AJA6ANu+3gAAOobO8AAAZoSEhPr6+rS0tNnZ2bZmAM6GNWAANv/U5Tq++P//+Etjp9uQOgBmtpDq+AA1hmYAALb/8joAOrq7vGAAYP//8jWGzs7OhqvOhmYAOvb29mYAZpubm8fHx/X19bb/+DUAYM7wq2EANtv/ttv/+LZmZpBmAAAANTYAYWA2NrbbkAA2YJCQOjZgYJCQkKysrIhhANXV1TUANTY2NjU1NZA6OqtgYKvwzs7Oh5DU/4iIYYeHztv/8oY1ANvq8tvU5Yg2NqtgNaxhYWbU8mAANTY2YM6HYIarhjpmZjY2AIeHNqvOh6tgNoerh4fOq2A2hwA2NqurYDVgq2A1hoY1YKuHNtvq+La+7JCQ29u+5bbq+M7wzmao8v/q8mA1ADVgYGCHhzZhYTU1YGaQkIis8odgAIZgADq+8quGNYhhiAA6Zjo6ZjWGhqzyrGY6Os/PiNuQZoY1NWGsz5C+3mCGzjp45azyz8/yrDo6Orb/25C2kGY6kLZmOpDbts6GYIbOq4Zghs+sYVBAmB8AAAwGSURBVHja7d2JQxTXHQfw0bUO5pljpyzCAguKHCUclfuyICqIgoGoiKLGVKti1aoxiSE2p7ZpYluTmMaYNG2TpleS3jl63/d933f7f/T3e+/Nziy7KuwuMrvzfS47b2ZnYD/v93tvrgWNBT4uixYtMhaYvi3wX9pftaLAN362Vn1gj9lyMpzlfiHcE9vP7oMXmmLMWRp/Kdd8J/9f2GNefGXSbJ00qzaL7nDVih93n1pR0PrInoNC3Hb3978tRJNJ1UcoRUaoTitRNWMbwOY7/oOTHf8981rBWFPLCEGHqjZzLtx9Olx1OmxePEU9o7Wbe0brUMdHmlS6ZG56iCjf8Ve9WvVqx+tPvx6WI8HpU/y8mcgtI92K2vKJPRR0ygVmc010h7PI33LylSbz3/95rcDlX/HTIX5lhHsC+V+kLKCckP5MHhoS5r/5wgXK8QuTps5/6S8Ym6z6o9nxuxdprlVG/uBt35D5Tytl1/hHMs74JtMe/6S/ZeSXNNpNcrpTto8J8Z0VBTzTJLtCQcby4/Z/ly/ZeyQEP47/jQWGX8tC7Z/vzzIv6vdn9sPv+N/guzLF77ex74p+Ok3wm1+IKJoqlv/8lmWpJhChkC/9BqOv7M9dkh9XS/hyBsZ/qj93wzF6nthbdmV/bn2ZXLQqAxrlsvFnftR/xy/KjOET0/dnQfxj/PXnBo3el4iWu0G8tYsTQoj1+WykL3ps3S0Xx8T/YV6Uu+ThvedoOBmXtfdF15zgRRnkp3f+z7/Xl23dTe2wPp8nCq4nE+O8OMa/YdA4Sk1EE5lAXVyLrkmP4a96Ov+Zbzj+vz31r3+sqi9j8fA7uxjp9r/73jJePLX/56oNqGx9qkutrNfUjZU5/rKjfx2nZ37fFHyeuP2rqDvoDuD2D9+r/Ef5RbWyXpN6gRjMKD9nMD3Xy/DZcDsNOKoJxn8d/969ZTHxV+Xo3KfA5fo/891+9az7P+c6d+47uoyJ9br/G+8pm+qfOCZ3A0ePyf6v2kyt+dsuo/eYp+Of2M8DP+8Fe4V4iWVC/MAe/8UxfahACU4D/Sq5h5D+4RPi57+2/WpN2j5mZ+rx+Pvt/Mc+CfLh+R/O/1VZmeBigFMPpFgyL/5CBIPCR/6VcfqgqwH8FX+tdzXAZXHFb1qa2f47y1W5U/NDweCUBshuf/mbVSnX/mBcA/jMH9cAgcDqQ4HAdv669TDN30roD961Zt0u40gnV3kSKM5Xc0vl13ZeS62QeX5XA8jdoAzyuuPPrVl3nDnFD3UW5+/gxgis3raUqzRZt0tOtJ9qW/6gV/C8/+Z3cLm5nPYC9E+OfiFb/zYVf4IXP394x5bb1wTUDDF5ZsuDnVosl0TnJFuv4H2/KuWGkwCyAViv/YHtOw7vWH2o+PlAgDrAEcXkM9ojbjHlgJ6jzDd26BU879c3h8uNmAYgfcgI6fwPrP7a8c4tt3+TEvquNa746/GP4/9hlQ00USPi4W1/UitknF82AMXe5rO/+Ms8qD3XGTh8SPZ/JlL3Dnx8TTTiqv8/1BnYvm3pTzp5yFQrZNj+XzeAIL5w9v/rdpGFYh/YUmZ86+vKz0l+KDriU7bTy9w9vkK9weAZtUJGHv9T/MXMjn+v8XCZ+fmvmPH53zU5ni1J+GOKL/0rZ9i9yH+5j55kcvypBH3nXxmj50OCzPXn3LOvbzSF+AeDlhXM4PgfmL9432gq8beC/KCa5Sx07gp73r///vkP9CUf/6DyE95y/MMnBu27QGnxV5eWLJst/337D+T0pTL+c/6T3wqFLLsJ9Ecfcpesqj8nxOCEl/2PPf7E4mtT6v+kJz/pQ1Y0/uPav2Hc6BWDXvZfd/0NM/avdP2TuwBldxqA+/+gfe93Sf40/BUk7Bc1Of21f24QorGdzG39tUWFFUI0s/9/PM3h2doifi2nroEqEToWrclRK11Ff3yx/c4Y0Ms3+qfv729sJ0ZzXUPJX0hDyOrSL5bW/orroobrvKxQzvJryl9dyq+qpTVz6o/Nf/lBj92DM/EPkHLTy22FFc26NapLKQkioo2C3cz1worG9oiQWdJs+yMy7HqluY2/Gv/s2I+rD/rMwE+ASMn5kt9saq+j/Bfsb+NW4dIm+z+1yQB7Bxw/R75kmV5pbuPPTWA4459QH/mavp8S/3xzpPHZ2qIBint/1N8cHf/6Of60rJ/7Q8mywgrq/zwAtA0k3fnT60/t+G+g8WVyPdmmYq79hfZYoPx2/7enERl4vdJc+1M8/q0urS2i1Jejecl57c+pLnX77fGfw/77BuWnV9RKGe6fq+Nf+OGHH3744Ycffvivuv+Nc1YQf/jhhx9++OGHf+79hW8p8qmfr222+dcf4TtYkWa/+gsranyd/xF9h5v99lX+ATlJ5e5uRvrlPdBIbVH1WU6Fwne159Q11PjIL6tE5ju+8laPmMUE8Ez/pzDH+D/azo3Q2B6ZtY9+eGv8H5DBbo7mf8my6h+qLKDc/1hR9u//I8Le/9vjX7+8q893N2t8c/yH43/44Ycffvjhhx9++OH3nf8Sl8HSfzLsFb/81Lej86GfznH72/ztj/jbX9egf8WnOeYyiL4AIj/mntX9n6+A6cu9rsvAdT9bxhN5Haw/q+PP3V9f7nVdBtb3AeRsduc/h1gLXZeB+Vebqs/6wZ8zwL/WIy/3ui4Ds3lA5X9dQ3b76xra9GjnGv94ZPjeWfm7jo3PZq0fx7/ww+9P/9wV+OG/On6vFvivht/D5Wr4Zck5sP++x67zXEnm798kVe6Zf//+x6/3XEnx7x9Nv+xbPP/AEzd4riTz96+SKn37HshZ7L2S6t8/m3YZHe3ru9Z7pa9vdBT//wP88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDDDz/88MMPP/zwww8//PDD7zm/70qsP71lXmaUWfLPW5gpZbb8SW+YwltJ5qd61C9cxZd+Z5jOXH8SMXT8oVBo40bLCF5tfzCN8RczDqLjT6IHpMEfNINU0pb/iRogr5RETfZcx03LL+FP0APySofoeaw7PHv+oGVNi593Y0FcLVH+J0BUhgmy88r++B6Qt+mTYbNlZDb9VpAfVLNc1gTNPh2/KUKh+AZgv9naHV5LrbOz4xZ67vkSV+P88T0gr/LTTWbro5VqW/rJPxKN1HxjeuvU/UHlJ7zl9ido9mn5ZQPEI+j7tLx9ufzGy+34UzXOH9cD8io/c2PBZz/H34A3yCttMtf2FLT2FLR8KF3jH+c/+a1QyIo2QbTZue9yg3MX7ilgOH3Rg6LojoM7/0N2icl/s+OWJpX8tl9PY/1Te0Be5dM3ff4Lz0g/bcBvgBqS/Gns/6QnP+lDlvOOdbPzu6afxhMF15Oxnbw4Ggcn/y0rvgGi8ackbtR+WZ1y/KP9lmVYjj+89smd/A3kBtrPfagpfft/GX2yOw0QbXb9A+UI5vKfORmOiYMr/6kBEuY/9X962PFX1djjX/ZvpGIFY/yc9pV6W/kGZDKslT86bcc/tt+a0uwspODzxO1/hvdojU4cXO+EGkCXKeM/9dwh2enHaBNdvZR/o+FuOvl25Ab8Bqj2qeVm61B6j/+m5r9udv75HH8Nt9OA46/KWp0CzjuJbwB7/98yIt7/3uU823NGVWP91APUhgn8als1DJmtQqihOX3xV+NfzIjFz7r/y85L4x9Hr0f3f/NiOBqHmHcys8M49/mfMPhohOIfusTh49Q9TzqP/0kf7+dgcVNTiz/KuSfEd+3xXww5cUjT+e8Vz4Fm1T/35/8zPgPw0vlfstejTNNI/mKW6R1/koU3XpjKxsn5U2j0tEVibor2m+m9qmhmmN/Hhf2L/F387v8/d7iN0ESosl4AAAAASUVORK5CYII=",f="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAP8AAAFjCAMAAADFBS10AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAL9UExURf///6CgoOPj48zMzKWlpYKHkGlpafDw8PLy8tzc3AB41wAAANfX1/Hx8Y6Ojvz8/NTU1KurqwAAhAAA///bkKOjo2NjY4aGhoWFhaGhodv//zo6kAD///DOh87w8Kzy8tvq7ACQ7Kvw8PLyz2Gs8og2ALb///LyrDp41wAAYfLPiGEAADYAAJDb/4fO8JGRkTYAYPDOhgAANgA2iDY2h4jP8s/y8joAZvr7+zU1hmCr8PKsYf+2ZvDwq/CrYPDwzv//26xhAAA6kJCQ121tbQAAYDYAYf//tjaIzwA2h2a2/zqQ7JA6ADoAALZmAM6HNjqQ2wAAZgBmttuQOs+INgBhrABgqwCt/wAAOoc2NmAAADYANu3t7KSkpLao1zUAAAB43qtgANvbkP/q7DaHzmYAZoc2AIbO8GYAOoSEhJA6OgCo8pDq+M6GNWAANjoAOktjp///+GZ41wB45QA1hrq7vKmpqWAAYJDq/zWGzpBmAM7OhqvOhtu+3tv/8v39/YiIiNv/+Nv/trZmZjUAYM7wq2bU/6xhYQAANWYAAGA2NrbbkAA2YP7+/jo6Zvr6+mRkZGVlZWEANtnZ2bS0tGdnZ2hoaJKSkpeXl7u7uzZgYJ2dndbW1uTk5Ojo6O7u7jUANTU1NQA2NqtgYKvwzs7Oh4iIYYeHzoY1ADp43rb/+DZhYatgNZCQOpCQ22aQkGAANTq++DY2YDo6Os6HYDpmtoarhv//8jqo8jpmZs+sYQA6ZmY6OoeHNtuQZqvOhzY2NofOq2A2h6tgNoerh6urYDVgq2A1hoY1YGa++KKiovb29vX19ZCQkKysrJubm8fHx9XV1UhLUHuAiICFjp+fn1dbYWxweIiIz2bU8quHNpDU/5C++GFhYYg2Yc7wzmA1ADVgYIg2NmGsrGCHh7a+7DU1YIdgAIZgAKzyrKuGNTqQtra2ZohhADWGhv/q8rbq+GGsz4Y1NWCGzrb/25C2kGY6kJDbtrZmOoZghs6GYIbOqzp45f/U5c+IYYQezC0AAAxXSURBVHja7d0HfNTWHQdwMYoOvyZtT27TkvM5nO0jGBsPYijnhSHGI2DAi8ZJDSYQWihNSwY4gZC0QJMmIW2TrnSkhKQz6UqzuldW9957773Xp///e08n3fDgONvS6fewTzpZsvV9//970tOLHWNugMv8+fONuWZgC/xj++tWRgPjZ2vdm3aazftiBe4Xwr2w/ezeczyRYi7Q+Eu55jv5f/dO88TDo2bLqFm3RbTH6lb+ov3AymjLdTv3CHHZVT/7gRAJk1avoxQZonXaiVZ9WwE23/HvGW3955FHoyOJ5iGCDtZt4Vy46nCs7nDMPHGAWkZLO7eMlsHWtyZUuvg3PUSS7/jrHql7pPWxOx+LyZ7g8AF+3ULk5qF2RW1+904KOuUCs3lNtMcKyN+87+GE+a9/Pxp1+Vf+apC/MsQtgfz3UxZQTki/n7uGrPlv3n2ccvz4qKnzX/qjI6N1fzZb/3Q/vWuRkd9z2fdl/tNOhdX/kYwzPmHa/Z/0Nw/9jnq7UU53yvYRIX64MspvErIpRH3Lz7j+jV8K904Iftz/G3ONoJZ52j87mGVW0h/M7Iff8T8hcCXNH7S+b0I/DROC5hciiaYVK3h+y7JUFYhIJJB+g9ET+4vPXJCxlvXLPox/ur94fS+99myKT+wvXhGXm7b5oFLGjT/zk/5LjsWNjusn7y+A+Kf4V9zTbTQ9RLTi9eJZ1ZwQQqxewEb6pI9V6+TmlPhfyZuKz7xy0z3UnWyUazck9+zhTT7y05n/468r4qvWUT2sXsALBdeLno28OcW/vtvooyqihUygal5L7kkfHe/0dP4z33D8f9n1979tWxFnccdzqhnp9r9oR5w3p7f/YnUAlVW7qtXOek9dWf7xx/vu3UivfN4UfF64/duoOegG4PZ37FD+Pv6i2lnvSa1AdPvKzxlMrytk+Gy4nQYc1Sz9v45/06Z4SvxV6Zv5FBiv/TPf7Vevuv1zrnPjvqTa6Fmt27/x4ni6v6dXXgb6emX7V3Wm9vxwtdHU6+n4Z/dzx89XwSYhHmKZEO+y+3/Rq28VKMGpo98mrxDS33G9+MAHbb/ak45PuZh6PP5BG//Yg6AAjv8w/lfl3CwPA4IcfyHCYRHY+LM+XHAVMNn4a/1kK8APQ79x/ZfXqHK55kfC4ZOpAN/7a56pSo32h0+uAgrPn6UC+Pa1hz839iWH93E1uC9WQ3/9rEDf96kRv/OcwF9+VwXoyyDfyu46xgMbZ3hvqME9r+qHBE3JhyRqxO88J/C0/8IXcLmwhq4C9E/2fhFb/1y1D4/o7uvr7pDjOT2869iRMjrUzwqSfsPewft+VWoMJwFkBbBe+42e7r7upt7i+9zDezW4d4kpB1zjnu5i5zmBp/16crjGSKkA0keMiH0b2PTrXdUdO36z0TW8V8lguJ4OOM+K5Ijf9ZzAV35ZARR7F98ovpc7tWPVruG9oQb3yYir9q8eEqgRv/OcwEfXf10BgviuMcCqdWSh2LuG94Ya3Ns9vn5WoB4SqBG/85zAd/f/FH8R0PtffRMc6PEfnn9keSTgLkW5F1/GPxw4/7kper4lCG78w2HLCk86/gvPOrvQ4m+F+YPWLMe/kG4BLjo7C9betPV5a7JVhv/iH1Z+wluO/9L4cFHRN/eOE3/pL4j4G5z/5LciEUtVASmv3quw5139HcMYPmq8cA3D6XPhWY/THge37qfXi86j9wvoa/SFb/PCp+2f9OQnfcRKxv+g9i84WLTbGC7azVblp/gvvHaNzv+37eevUS3IhY/i7/yTlwBl1xWg2/8w+5XaWZN+wms/b7307XZy+PT6z8X2W8n+fzfnfDb/ewzKde1/kIK+df+w//2p+S97OGa5/NQlSP+DD+x1xZ+2Fkb8Vf+n/bsPykae4r92TdFRviQ+/l/+UtHRYXf793/8uQoMp/8zVLfu+Dntf8rx/0/c+P0f1nAPofv/B/YWFYY/qOOfSY7/5ni5TIc/5N0yZxqef8AfGu/3b+CHf+b8b3jj61717AD757z+Na8Msv+K157+cs/4Fy1ZXJrtLCurUrePtV8O/ldfcc3LPOCvrBKivmEy/v76hnz6r/nUGU976oz7mU/+sc7S7W8be7dc/Gc84+ke8DeKgVDofzL+lVXL3k9V0ShEJ7kHQmUVvG1xaVmFrKE2qqgBGf9FS4SQC9qf9vW5X0ZV+e+gZLhDtge3n7nkTfrle8FL3jfX9uARPwdXlGs/f4py2lTu9tu536bbf6NYtpyyoXPRkvqGsopcG4VH/CGZ1+U6/5fL/G5L9csqcvn7Oef72c/14HN/Yzm3gc5Mv1pnf7+2O/Ef4ForLwy//HWDjPjbbVz6hbA7wLT2XwB+ef2z27/j53r5o9P/LfstMWnX9P7f//6Zu/+FH3744Ycffvjhh3+6/U+cuYL4ww8//PDDDz/88M/k/Ee+5jR96S8f/zwn3AH+AvD382P/AflkvzOkFpVrS0OVa39JqzwtkPtErw/aP89ndTYS8xUNXCGLlrBV+Uu5gvT2Qs5/nszVk2FcE6l+vb3w/RIeyvSr7YXsb+vs52ZOb15SyotF36i8oIG7BZn/anvBtv/6hrZly8sqBuRsaLmcFKX+sF+Id6zlxbLlejvu/+CHH3744Ycffvjhx/wn5j+R//DDDz/88MPva/9UTff4Zf4zeH75C1DlgfbLuY4g+9UkB09xlVX8eAk/69ezP7y1/s1TMP3jOb+e4+Rfegw1Li7Vfp75KasofP+PGvQcp3xPL9ovZ/4aC95PQo0MpL9R/marnOPkWUCe9tSznwHIf8H/gUcopOc+yyq+q+4H9OwnbS3o/m8ypTG4/rLv8SWwMxTY+HOr6AyFAp3/hXr/N4MFfvinxe/ZAv80+L1cpsEvS+iWWz//2dM9V740DX//TZZPz/7CrZ97iufK16bh7//JcvNps2/54pM9V74+DX//UZZDN38mdJr3ypen4e9/ynLTTYcOPcl75Su33/5V/P+f4Icffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH3744Ycffvjhhx9++OGHH34/+wNXUv35LbP8UabIP2ueX8pU+XM+8BROJZef6lG/cJVA+p1u2r/+HGLo+CORyObNlhGebn84j/EXJx1Ex59DC8iDP2yGqeQt/7NVQEkViRL2u9bzl47hz9ICSqoG6XWkPTZ1/rBlTYpfck40Yy1b/mdB1MYIsn1if2YLKLngvTGzeWgq/VaYP2jNclmzVPtk/KaIRDIrgP1mS3tsA9XO9taL6bXrW7ya4c9sASW1H0qYLbfVqmPpJ/9c1FP1jeijT90fVn7CW25/lmqflF9WQCaCvk/z85fKb7zUjj+tZvgzWkBJ7UfOiX7ik/wN+ICSqoS5oSva0hVtfku++j/Of/JbkYiVrIJktXPb5QrnJtwVZTh90gdF0R0Hd/5H7JKS/2brxQmV/LZfL1P96S2gpPbO8z/28buknw7gE6CKJH8e2z/pyU/6iOWcsa52Pmv6abxQcL0Y2c6bk3Fw8t+yMisgGX9K4nrtl6tp9z/ab1mG5fhjGz66nb+BPED7uQ0l8nf9l9Enu1MByWrXP1D2YC7/kX2xlDi48p8qIGv+U/unDzv+ajX1/pf9m6lY4RQ/p32tPlaegEyGDfJH5+3+x/ZbadXOQgo+L9z+u/iKVu/EwXUmVAG6pPX/1HIHZaMfoUP06lj+zYa76uTpyAP4BGjtfUvNlsH83v+l57+udv75HH8Nt9OA46/KBp0CzplkVoB9/W8eEje+dCm/7TqiVlP91ALUgVn86ljVDZktQqiuOX/xV/1fSo/Fr7r9y8ZL/R9Hr0u3f/NELBmHlDM5uds49/hPGHw3QvGPjHH7mH7lyef9P+kz/Rwsrmqq8ds494T4id3/i0EnDnka/044BppS/8yP/096BOCl8V+uz6NM08j9YZbpHX+OhQ+edyoH5+Y/hUrPWyRmpmi/md+niqbP/AEu7J8f7BJ0//8BBRwxo36FEUsAAAAASUVORK5CYII=",P="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAZElEQVR42s1TWw7AIAwq9z80e9mF6NTaJcv4qlgoNRGWA72AHgSYCa8SbsCRFreCpQ9oDY67k98plkY4ETHQgSmDSYJKbMsJPjAYrGCVWIb+yqD7Bq3Y1hJEDV4mCEE/CZ/IFDZVF3sClc46gQAAAABJRU5ErkJggg==",v="/MicroCityNotes/assets/module_libraries_settings-lee40Qvj.png",z="/MicroCityNotes/assets/module_settings-3JBvpV80.png";export{P as _,A as a,f as b,v as c,z as d};
diff --git a/assets/network.html-m23VzkXJ.js b/assets/network.html-IGA5rLvk.js
similarity index 83%
rename from assets/network.html-m23VzkXJ.js
rename to assets/network.html-IGA5rLvk.js
index d78c8179..14a9f251 100644
--- a/assets/network.html-m23VzkXJ.js
+++ b/assets/network.html-IGA5rLvk.js
@@ -1,4 +1,4 @@
-import{_ as o,r as c,o as i,c as u,a as s,b as n,d as e,w as p,e as a}from"./app-DaLjD81q.js";const l="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQwMCIgaGVpZ2h0PSIyOTMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjcxNCIgeT0iNjMyIiB3aWR0aD0iMjQwMCIgaGVpZ2h0PSIyOTMiLz48L2NsaXBQYXRoPjwvZGVmcz48ZyBjbGlwLXBhdGg9InVybCgjY2xpcDApIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzE0IC02MzIpIj48cGF0aCBkPSJNMTU3Ni41IDY5Ny41QzE1NzYuNSA2NjguNzgxIDE1OTkuNzggNjQ1LjUgMTYyOC41IDY0NS41IDE2NTcuMjIgNjQ1LjUgMTY4MC41IDY2OC43ODEgMTY4MC41IDY5Ny41IDE2ODAuNSA3MjYuMjE5IDE2NTcuMjIgNzQ5LjUgMTYyOC41IDc0OS41IDE1OTkuNzggNzQ5LjUgMTU3Ni41IDcyNi4yMTkgMTU3Ni41IDY5Ny41WiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjQuNTgzMzMiIHN0cm9rZS1taXRlcmxpbWl0PSI4IiBmaWxsPSIjRkZGRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48dGV4dCBmb250LWZhbWlseT0iQ29uc29sYXMsQ29uc29sYXNfTVNGb250U2VydmljZSxzYW5zLXNlcmlmIiBmb250LXdlaWdodD0iNDAwIiBmb250LXNpemU9IjY0IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIDE2MTAuNTIgNzIwKSI+MjwvdGV4dD48cGF0aCBkPSJNODIzIDY5NyAxNTc2LjYzIDY5NyIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHBhdGggZD0iTTg0OC43OCA2OTEuODQ0IDE1NTAuODUgNjkxLjg0NCAxNTUwLjg1IDcwMi4xNTcgODQ4Ljc4IDcwMi4xNTZaTTg1My45MzcgNzEyLjQ2OSA4MjMgNjk3IDg1My45MzcgNjgxLjUzMVpNMTU0NS42OSA2ODEuNTMyIDE1NzYuNjMgNjk3IDE1NDUuNjkgNzEyLjQ2OVoiIGZpbGw9IiNBNUE1QTUiLz48cGF0aCBkPSJNNzE5LjUgNjk3LjVDNzE5LjUgNjY4Ljc4MSA3NDIuNzgxIDY0NS41IDc3MS41IDY0NS41IDgwMC4yMTkgNjQ1LjUgODIzLjUgNjY4Ljc4MSA4MjMuNSA2OTcuNSA4MjMuNSA3MjYuMjE5IDgwMC4yMTkgNzQ5LjUgNzcxLjUgNzQ5LjUgNzQyLjc4MSA3NDkuNSA3MTkuNSA3MjYuMjE5IDcxOS41IDY5Ny41WiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjQuNTgzMzMiIHN0cm9rZS1taXRlcmxpbWl0PSI4IiBmaWxsPSIjRkZGRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48dGV4dCBmb250LWZhbWlseT0iQ29uc29sYXMsQ29uc29sYXNfTVNGb250U2VydmljZSxzYW5zLXNlcmlmIiBmb250LXdlaWdodD0iNDAwIiBmb250LXNpemU9IjY0IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIDc1Mi45NDcgNzIwKSI+MTwvdGV4dD48dGV4dCBmb250LWZhbWlseT0iU2ltSGVpLFNpbUhlaV9NU0ZvbnRTZXJ2aWNlLHNhbnMtc2VyaWYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZvbnQtc2l6ZT0iNjQiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIDEgMTA3MS4xNiA4NzUpIj7mraPluLjnkIbop6M8L3RleHQ+PHBhdGggZD0iTTMwMDYuNSA2OTcuNUMzMDA2LjUgNjY4Ljc4MSAzMDI5Ljc4IDY0NS41IDMwNTguNSA2NDUuNSAzMDg3LjIyIDY0NS41IDMxMTAuNSA2NjguNzgxIDMxMTAuNSA2OTcuNSAzMTEwLjUgNzI2LjIxOSAzMDg3LjIyIDc0OS41IDMwNTguNSA3NDkuNSAzMDI5Ljc4IDc0OS41IDMwMDYuNSA3MjYuMjE5IDMwMDYuNSA2OTcuNVoiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0LjU4MzMzIiBzdHJva2UtbWl0ZXJsaW1pdD0iOCIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHRleHQgZm9udC1mYW1pbHk9IkNvbnNvbGFzLENvbnNvbGFzX01TRm9udFNlcnZpY2Usc2Fucy1zZXJpZiIgZm9udC13ZWlnaHQ9IjQwMCIgZm9udC1zaXplPSI2NCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgMSAzMDM5LjgxIDcyMCkiPjI8L3RleHQ+PHBhdGggZD0iTTIxNDguNSA2OTcuNUMyMTQ4LjUgNjY4Ljc4MSAyMTcxLjc4IDY0NS41IDIyMDAuNSA2NDUuNSAyMjI5LjIyIDY0NS41IDIyNTIuNSA2NjguNzgxIDIyNTIuNSA2OTcuNSAyMjUyLjUgNzI2LjIxOSAyMjI5LjIyIDc0OS41IDIyMDAuNSA3NDkuNSAyMTcxLjc4IDc0OS41IDIxNDguNSA3MjYuMjE5IDIxNDguNSA2OTcuNVoiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0LjU4MzMzIiBzdHJva2UtbWl0ZXJsaW1pdD0iOCIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHRleHQgZm9udC1mYW1pbHk9IkNvbnNvbGFzLENvbnNvbGFzX01TRm9udFNlcnZpY2Usc2Fucy1zZXJpZiIgZm9udC13ZWlnaHQ9IjQwMCIgZm9udC1zaXplPSI2NCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgMSAyMTgyLjI0IDcyMCkiPjE8L3RleHQ+PHBhdGggZD0iTTIyMzcuNSA2NTcuMDYyIDI5OTguNjYgNjU3LjA2MyAyOTk4LjY2IDY2My45MzggMjIzNy41IDY2My45MzdaTTI5OTQuMDcgNjQ2Ljc1IDMwMjEuNTcgNjYwLjUgMjk5NC4wNyA2NzQuMjVaIiBmaWxsPSIjQTVBNUE1Ii8+PHBhdGggZD0iTTEuNTgyMjFlLTA2LTMuNDM3NSA3NjEuMTU2LTMuNDM3MTUgNzYxLjE1NiAzLjQzNzg1LTEuNTgyMjFlLTA2IDMuNDM3NVpNNzU2LjU3My0xMy43NDk3IDc4NC4wNzMgMC4wMDAzNjA4OTIgNzU2LjU3MyAxMy43NTAzWiIgZmlsbD0iI0E1QTVBNSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMzAyMS41NyA3MzQuNSkiLz48dGV4dCBmb250LWZhbWlseT0iU2ltSGVpLFNpbUhlaV9NU0ZvbnRTZXJ2aWNlLHNhbnMtc2VyaWYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZvbnQtc2l6ZT0iNjQiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIDEgMjQwNC4yIDg3NSkiPue9kee7nOWbvuS4reeahOihqOi+vjwvdGV4dD48L2c+PC9zdmc+",d={},k=a('

操作网络

网络拓补化

网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题:

  1. 这条路是单向通行的还是双向通行?
  2. 这条路的起点是哪?终点是哪?

一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的符号为O,目的点的符号为D,这样,使用O和D就能清晰地描述每条路的方向。

对于上图的示例,上方的道路O=1,D=2,所以方向描述为从1到2;下方的道路O=2,D=1,方向描述为从2到1。

使用函数对网络进行拓补

',7),r=a(`

此处简单列举几种创建MicroCity中网络对象的方法:

local network = CreateNetwork() 
+import{_ as o}from"./two_way-xpspXH9g.js";import{_ as c,r as i,o as u,c as l,a as s,b as n,d as e,w as p,e as a}from"./app-LOf__QKq.js";const d={},k=a('

操作网络

网络拓补化

网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题:

  1. 这条路是单向通行的还是双向通行?
  2. 这条路的起点是哪?终点是哪?

一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的符号为O,目的点的符号为D,这样,使用O和D就能清晰地描述每条路的方向。

对于上图的示例,上方的道路O=1,D=2,所以方向描述为从1到2;下方的道路O=2,D=1,方向描述为从2到1。

使用函数对网络进行拓补

',7),r=a(`

此处简单列举几种创建MicroCity中网络对象的方法:

local network = CreateNetwork() 
 

创建一个空网络对象并返回此对象。network就是返回得到的空网络对象。

创建对象后,可以使用AddLinkDelLink等函数在网络对象中创建连接。具体用法见参考文档。

local network, nodes, links = CreateNetwork(Lines)
 

此处的Lines为一个矢量图形对象,类型为Line。MicroCity中的CreateNetwork()函数在这种用法中可以直接帮你在道路连线上添加起点和终点,并自动在返回的links对象中标上O点和D点的编号。

也就是说,你只需要提供网络连线即可,剩下的拓补化工作可以由函数自动完成。我认为这可能是最常用的创建网络图并进行拓补化的方法。

网络拓补的简单示例

-- 打开连线图层
 Shapes = Open("Shapes.shp")
@@ -43,13 +43,13 @@ Links = CreateS
 AddField(Links, "CAPACITY", "double") --容量
 

如果只是一次性地进行网络拓补,不会再用拓补化过的网络重新创建网络对象,也需要先创建以上属性。拓补化后数据并不会根据属性名称填入,而是根据位置填入。

如果只创建了OD两个属性,则O的属性中会被填入ID数据,而D的属性中会被填入O的数据。而如果只根据上面的顺序创建了IDOD三个属性,由于数据顺序根据位置填入,则最终的填入的数据是正确的。

CopyShapeTo函数

拓补的操作中使用了CopyShapeTo()函数,其作用是将一个Shape对象复制到Shapes图层中的对应位置,并根据输入的dxdyShapes图层中进行位置变换。其中,dxdy分别为在xy方向上的位移量(理解为deltax和deltay)。

CopyShapeTo(TargetShapes, dx, dy, Shape1 [, Shape2, ...])
 

根据函数的用法可以看到,还支持复制到多个图层上的对应位置后再进行变换。 如果只想将图形复制到对应图层的对应位置,而不进行变换,可以将dxdy设为0,像这样:

CopyShapeTo(TargetShapes, 0, 0, Shape1 [, Shape2, ...])
-
`,21),m=s("code",null,"CopyShapeTo()",-1),g=a(`

网络拓补化后算法的使用

对网络进行拓补化后,可以使用自带的函数求解很多问题,如:最短路径生成树、最短路径、最短距离等。本文以计算最短路径和最短路长为例介绍一下计算最短路径的流程及踩过的坑

计算最短路径和最短路长

要计算最短路径,首先必须要清楚计算网络中哪两个点之间的最短路径。这里以startIDendID分别表示起点和终点。本文假设你已经创建了网络对象,并存入名为Network的变量中。如果你不知道该如何创建一个网络图,可以参考上方介绍的 网络拓补化 流程。

创建最小生成树

第一步,先要以startID为开始点创建最短路径生成树。理论上以始点创建最短路径生成树后,就可以获取始点到网络上任意一点的最短距离。创建最短路径生成树可以调用GenSTPTree()函数实现。

GenSTPTree(Network, startID [, endID])
+
`,21),v=s("code",null,"CopyShapeTo()",-1),m=a(`

网络拓补化后算法的使用

对网络进行拓补化后,可以使用自带的函数求解很多问题,如:最短路径生成树、最短路径、最短距离等。本文以计算最短路径和最短路长为例介绍一下计算最短路径的流程及踩过的坑

计算最短路径和最短路长

要计算最短路径,首先必须要清楚计算网络中哪两个点之间的最短路径。这里以startIDendID分别表示起点和终点。本文假设你已经创建了网络对象,并存入名为Network的变量中。如果你不知道该如何创建一个网络图,可以参考上方介绍的 网络拓补化 流程。

创建最小生成树

第一步,先要以startID为开始点创建最短路径生成树。理论上以始点创建最短路径生成树后,就可以获取始点到网络上任意一点的最短距离。创建最短路径生成树可以调用GenSTPTree()函数实现。

GenSTPTree(Network, startID [, endID])
 

此处的endID不是必须的,如果有可以提供给函数。也就是说,您共有两种做法实现这一步:

GenSTPTree(Network, startID) --方法1
 GenSTPTree(Network, startID , endID) --方法2(建议)
 

一般认为提供的信息越完备,执行的效果越好。由于在计算最短路径之前就知道endID,因此建议将其提供给函数。

此处已经对函数的这种中括号写法进行了解释,后文中将会直接使用这种写法。

第二步,获取最短路径对应的信息。前面提到,确定起点和终点后才能确定两点之间的最短线路。由于前面使用始点startID创建了最小生成树,因此现在只需要提供终点endID就能获取到最短路径和最短路长。下面介绍了使用网络对象Network获取最短路长和最短路径的方法。

获取最短路长

MicroCity的文档中提供了3种获取最短路径的方式。

第一种,由于前面计算了最短路径生成树,已经输入了起始点的信息。因此现在只需要提供终点信息即可。(即使刚刚可能已经提供了终点信息)函数需要网络对象Network和终点endID用法如下。

local len = GetSTPLen(Network, endID)
 

第二种,通过提供始点startID和终点endID计算两个点在网络上的最短路长。这种用法不要求在计算最短路径前先生成最短路径生成树,可以直接使用。Network为网络对象,用法如下:

local len = GetSTPLen(Network, startID, endID)
 

第三种,通过提供始点和终点的xy坐标计算两个点在网络上的最短路长。这种用法也不需要在计算最短路径前先生成最短路径生成树,可以直接使用。起点的坐标设为x1y1;终点的坐标设为x2y2Network为网络对象,用法如下:

local len = GetSTPLen(Network, x1, y1, x2, y2)
-

获取最短路径

MicroCity的文档中提供了3种信息可供获取,分别为:

  1. 点或线的ID序列
  2. 点或线的索引(index)序列
  3. 点或线的形状(Shape)序列。
`,23),v=a(`

返回点的序列:

GetSTPPath (Network, endID, "iNodeShp")
+

获取最短路径

MicroCity的文档中提供了3种信息可供获取,分别为:

  1. 点或线的ID序列
  2. 点或线的索引(index)序列
  3. 点或线的形状(Shape)序列。
`,23),h=a(`

返回点的序列:

GetSTPPath (Network, endID, "iNodeShp")
 

返回线的序列:

GetSTPPath (Network, endID, "iLinkShp")
 

这样就能返回所有点或线的索引序列了。


踩坑经验:序列

Lua语言快速上手中介绍过Lua中的集合,它提供了丰富的特性帮助编写代码。但是没有听说过序列。序列是下面这个东西:

local x, y = GetCenterXY(Shapes) --借用一下这个函数
 

里面的x,y就是一个序列。还有这种情况:

GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) --再次借用一个函数
@@ -67,4 +67,4 @@ d1 = GetDistanc
 -- 这里获取到的indexList只是第一个Link的index,是一个数值。
 

既然等号左边没有办法改变,就从等号右边做出改变。还记得怎么定义一个最简单的table吗?

local list = {1, 2, 3, 4, 5}
 

右边的1, 2, 3, 4, 5其实可以看做一个序列。所以,只要给函数的返回值加上括号就能把他们全部捞起来 ( •̀ ω •́ )✧

local indexList = { GetSTPPath(Network, endID, "iLinkShp") }
-

上面的这种做法得到的indexList就是一个table类型的变量了。然后就可以开始执行集合的各种操作了捏😋

`,20);function N(I,b){const t=c("RouterLink");return i(),u("div",null,[k,s("p",null,[n("MicroCity可以处理网络,所有函数的具体用法见参考文档:"),e(t,{to:"/docs/4.6_networks.html"},{default:p(()=>[n("4.6 网络")]),_:1})]),r,s("p",null,[m,n("函数的具体用法见 "),e(t,{to:"/docs/4.3_shapes_and_tables.html"},{default:p(()=>[n("4.3 矢量图形和表格")]),_:1})]),g,s("p",null,[n("函数的详细用法请参阅 "),e(t,{to:"/docs/4.6_networks.html#algorithms"},{default:p(()=>[n("4.6 网络 - 算法")]),_:1}),n(",此处仅以第2种:点或线的索引序列作为示例。")]),v])}const h=o(d,[["render",N],["__file","network.html.vue"]]);export{h as default}; +

上面的这种做法得到的indexList就是一个table类型的变量了。然后就可以开始执行集合的各种操作了捏😋

`,20);function b(g,f){const t=i("RouterLink");return u(),l("div",null,[k,s("p",null,[n("MicroCity可以处理网络,所有函数的具体用法见参考文档:"),e(t,{to:"/docs/4.6_networks.html"},{default:p(()=>[n("4.6 网络")]),_:1})]),r,s("p",null,[v,n("函数的具体用法见 "),e(t,{to:"/docs/4.3_shapes_and_tables.html"},{default:p(()=>[n("4.3 矢量图形和表格")]),_:1})]),m,s("p",null,[n("函数的详细用法请参阅 "),e(t,{to:"/docs/4.6_networks.html#algorithms"},{default:p(()=>[n("4.6 网络 - 算法")]),_:1}),n(",此处仅以第2种:点或线的索引序列作为示例。")]),h])}const y=c(d,[["render",b],["__file","network.html.vue"]]);export{y as default}; diff --git a/assets/network.html-l_dMxKkp.js b/assets/network.html-l_dMxKkp.js new file mode 100644 index 00000000..77b8c60b --- /dev/null +++ b/assets/network.html-l_dMxKkp.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-608c75c6","path":"/en/notes/network.html","title":"Operating Networks","lang":"en-US","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,网络,拓补,network"}],["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/network.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/network.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Operating Networks"}],["meta",{"property":"og:description","content":"Network Topology Network topology, in simple terms, refers to a network with nodes and connections between them. If we think of connections as roads, then you need to solve the ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Operating Networks\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]],"description":"Network Topology Network topology, in simple terms, refers to a network with nodes and connections between them. If we think of connections as roads, then you need to solve the ..."},"headers":[{"level":2,"title":"Network Topology","slug":"network-topology","link":"#network-topology","children":[]},{"level":2,"title":"Building Network Topology using Functions","slug":"building-network-topology-using-functions","link":"#building-network-topology-using-functions","children":[]},{"level":2,"title":"Simple Example of Network Topology","slug":"simple-example-of-network-topology","link":"#simple-example-of-network-topology","children":[{"level":3,"title":"Pitfall: Creating Network Objects","slug":"pitfall-creating-network-objects","link":"#pitfall-creating-network-objects","children":[]},{"level":3,"title":"CopyShapeTo Function","slug":"copyshapeto-function","link":"#copyshapeto-function","children":[]}]},{"level":2,"title":"Using the Network Topology Algorithm","slug":"using-the-network-topology-algorithm","link":"#using-the-network-topology-algorithm","children":[{"level":3,"title":"Calculating the Shortest Path and Its Length","slug":"calculating-the-shortest-path-and-its-length","link":"#calculating-the-shortest-path-and-its-length","children":[]},{"level":3,"title":"Pitfall: Sequences","slug":"pitfall-sequences","link":"#pitfall-sequences","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/network.md","autoDesc":true}');export{t as data}; diff --git a/assets/network.html-qaPJNigq.js b/assets/network.html-qaPJNigq.js new file mode 100644 index 00000000..1801791c --- /dev/null +++ b/assets/network.html-qaPJNigq.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-16cb829c","path":"/notes/network.html","title":"操作网络","lang":"zh-CN","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,网络,拓补,network"}],["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/network.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/network.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"操作网络"}],["meta",{"property":"og:description","content":"网络拓补化 网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题: 1. 这条路是单向通行的还是双向通行? 2. 这条路的起点是哪?终点是哪? 一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"操作网络\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]],"description":"网络拓补化 网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题: 1. 这条路是单向通行的还是双向通行? 2. 这条路的起点是哪?终点是哪? 一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的..."},"headers":[{"level":2,"title":"网络拓补化","slug":"网络拓补化","link":"#网络拓补化","children":[]},{"level":2,"title":"使用函数对网络进行拓补","slug":"使用函数对网络进行拓补","link":"#使用函数对网络进行拓补","children":[]},{"level":2,"title":"网络拓补的简单示例","slug":"网络拓补的简单示例","link":"#网络拓补的简单示例","children":[{"level":3,"title":"踩坑经验:创建网络对象","slug":"踩坑经验-创建网络对象","link":"#踩坑经验-创建网络对象","children":[]},{"level":3,"title":"CopyShapeTo函数","slug":"copyshapeto函数","link":"#copyshapeto函数","children":[]}]},{"level":2,"title":"网络拓补化后算法的使用","slug":"网络拓补化后算法的使用","link":"#网络拓补化后算法的使用","children":[{"level":3,"title":"计算最短路径和最短路长","slug":"计算最短路径和最短路长","link":"#计算最短路径和最短路长","children":[]},{"level":3,"title":"踩坑经验:序列","slug":"踩坑经验-序列","link":"#踩坑经验-序列","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":8}]},"filePathRelative":"notes/network.md","autoDesc":true}');export{e as data}; diff --git a/assets/network.html-rimWgBRX.js b/assets/network.html-rimWgBRX.js new file mode 100644 index 00000000..35db0f73 --- /dev/null +++ b/assets/network.html-rimWgBRX.js @@ -0,0 +1,70 @@ +import{_ as c}from"./two_way-xpspXH9g.js";import{_ as l,r as i,o as u,c as r,a,b as n,d as s,w as o,e}from"./app-LOf__QKq.js";const d={},h=e('

Operating Networks

Network Topology

Network topology, in simple terms, refers to a network with nodes and connections between them. If we think of connections as roads, then you need to solve the following problems:

  1. Is this road one-way or two-way?
  2. Where does the road start? Where does it end?

In general, each road in a network diagram is considered to be one-way. If a two-way road is needed, you simply need to add a road in the opposite direction. Like this: Two-way road This way, each road has a direction. It is common to use the symbol O for the starting point and the symbol D for the destination point. Using O and D, the direction of each road can be clearly described.

For the example in the above diagram, the road at the top has O=1, D=2, so the direction is described as from 1 to 2; the road at the bottom has O=2, D=1, so the direction is described as from 2 to 1.

Building Network Topology using Functions

',7),k=e(`

Here are some simple methods for creating network objects in MicroCity:

local network = CreateNetwork() 
+

Create an empty network object and return it. network is the returned empty network object.

After creating the object, you can use functions like AddLink and DelLink to create connections in the network object. See the reference document for specific usage.

local network, nodes, links = CreateNetwork(Lines)
+

Here, Lines is a vector graphic object of type Line. In this usage, the CreateNetwork() function in MicroCity can directly add starting points and endpoints to the road connections and automatically label the O and D points in the returned links object.

In other words, you only need to provide the network connections, and the remaining work of topology can be automatically completed by the function. I believe this may be the most commonly used method for creating network diagrams and conducting topology.

Simple Example of Network Topology

-- Open the connection layer
+Shapes = Open("Shapes.shp")
+
+-- Create network topology
+network, network_nodes, network_links = CreateNetwork(Shapes)
+
+-- Create a layer to store the topologized network nodes
+Nodes = CreateShapes("Nodes", "point")
+-- Copy the network nodes obtained from topoization to the layer
+AddField(Nodes, "ID", "int")
+for i = 1, GetRecCount(network_nodes) do
+	CopyShapeTo(Nodes, 0, 0, GetShape(network_nodes, i))
+end
+
+-- Create a layer to store the topologized network connections
+Links = CreateShapes("Links", "line")
+-- Copy the original attribute fields from the network connections to the layer
+for i = 1, GetFieldCount(Shapes) do
+	AddField(Links, GetField(Shapes, i))
+end
+-- Add attribute fields for the connections, and corresponding data will be added later using functions
+AddField(Links, "ID", "int")
+AddField(Links, "O", "int")
+AddField(Links, "D", "int")
+AddField(Links, "IMPEDANCE", "double")
+AddField(Links, "DIRECTION", "int")
+AddField(Links, "CAPACITY", "double")
+-- Copy the network lines obtained from topoization to the layer (including corresponding data)
+for i = 1, GetRecCount(network_links) do
+	CopyShapeTo(Links, 0, 0, GetShape(network_links, i))
+end
+
+-- Update the layers
+Update(Nodes)
+Update(Links)
+

The example is modified from the built-in editor of MicroCity.

Although the network connection was established at the beginning, it is possible that during the topology process, the nodes on the connection may overlap, causing the continuous connection to be divided into multiple segments. Therefore, the resulting Links layer may be different from the input layer. The topology nodes Nodes obtained from the topology process correspond to the resulting links Links, so it is recommended to use the topological processing result of the Links layer as the connection between network nodes.

Pitfall: Creating Network Objects

If you need to create a network again using the CreateNetwork(Nodes, Links) function, you need to retain the attributes added during the topological process, otherwise there will be errors in network initialization:

AddField(Links, "ID", "int")
+AddField(Links, "O", "int")
+AddField(Links, "D", "int")
+AddField(Links, "IMPEDANCE", "double") -- impedance
+AddField(Links, "DIRECTION", "int") -- direction
+AddField(Links, "CAPACITY", "double") -- capacity
+

If you are only doing a one-time topology of the network and will not use the topologically processed network to create a network object again, you still need to create the above attributes first. The topologically processed data is not filled in according to the attribute names, but according to their positions.

If only O and D attributes are created, the ID data will be filled in the O attribute, and the O data will be filled in the D attribute. If only the ID, O, and D attributes are created in the order mentioned above, the data will be filled correctly due to the data order being filled based on their positions.

CopyShapeTo Function

The CopyShapeTo() function is used in the topological process to copy a Shape object to the corresponding position in the Shapes layer and perform position transformation in the Shapes layer based on the input dx and dy. Here, dx and dy represent the displacements in the x and y directions (referred to as deltax and deltay).

CopyShapeTo(TargetShapes, dx, dy, Shape1 [, Shape2, ...])
+

Based on the usage of the function, it also supports copying to multiple layers and then performing the transformation. If you only want to copy the shape to the corresponding position of the corresponding layer without transformation, you can set dx and dy to 0, like this:

CopyShapeTo(TargetShapes, 0, 0, Shape1 [, Shape2, ...])
+
`,21),m=a("code",null,"CopyShapeTo()",-1),g=e(`

Using the Network Topology Algorithm

After performing the network topology, you can use the built-in functions to solve many problems, such as generating a minimum spanning tree, finding the shortest path, or calculating the shortest distance. This article will take the calculation of the shortest path and its length as an example to explain the process and pitfalls of calculating the shortest path.

Calculating the Shortest Path and Its Length

To calculate the shortest path, it is necessary to determine which two points in the network the shortest path is between. Here, startID and endID represent the starting point and the endpoint, respectively. Let's assume that you have already created a network object and stored it in a variable named Network. If you don't know how to create a network graph, you can refer to the Network Topology process described above.

Creating a Minimum Spanning Tree

Step 1: First, create a minimum spanning tree with startID as the starting point. Theoretically, after creating a minimum spanning tree with the starting point, you can obtain the shortest distance from the starting point to any point on the network. You can use the GenSTPTree() function to create a minimum spanning tree.

GenSTPTree(Network, startID [, endID])
+

The endID here is not necessary, but if it is available, you can provide it to the function. In other words, you have two ways to accomplish this:

GenSTPTree(Network, startID) -- Method 1
+GenSTPTree(Network, startID, endID) -- Method 2 (recommended)
+

It is generally believed that the more complete the information provided, the better the execution effect. Since you already know endID before calculating the shortest path, it is recommended to provide it to the function.

The usage of this function with brackets has been explained here, and this notation will be used directly in the following text.

Step 2, obtain the information corresponding to the shortest path. As mentioned earlier, the shortest route between two points can only be determined after the starting point and the destination point are determined. Since the minimum spanning tree was created using the starting point startID earlier, now we only need to provide the destination point endID in order to obtain the shortest path and its length. The following explains the methods to obtain the shortest path length and the shortest path using the Network object.

Obtaining the Shortest Path Length

MicroCity's documentation provides three ways to obtain the shortest path.

The first method is used when the shortest path spanning tree has already been calculated and the information for the starting point has been inputted. Therefore, now only the information for the destination point needs to be provided (even if it has been provided already). The function requires a network object Network and the endpoint endID is used as follows:

local len = GetSTPLen(Network, endID)
+

The second method calculates the shortest path length between two points on the network by providing the starting point startID and the destination point endID. This usage does not require generating the shortest path spanning tree before calculating the shortest path and can be used directly. The Network parameter represents the network object and is used as follows:

local len = GetSTPLen(Network, startID, endID)
+

The third method calculates the shortest path length between two points on the network by providing the xy coordinates of the starting and destination points. This usage also does not require generating the shortest path spanning tree before calculating the shortest path and can be used directly. The coordinates of the starting point are set as x1 and y1, the coordinates of the destination point are set as x2 and y2, and the Network parameter represents the network object and is used as follows:

local len = GetSTPLen(Network, x1, y1, x2, y2)
+

Obtaining the Shortest Path

MicroCity's documentation provides three pieces of information that can be obtained, namely:

  1. The sequence of point or line IDs
  2. The sequence of point or line indices
  3. The sequence of point or line shapes.
`,23),b=e(`

To return the sequence of points:

GetSTPPath (Network, endID, "iNodeShp")
+

To return the sequence of lines:

GetSTPPath (Network, endID, "iLinkShp")
+

This way, the sequence of point or line indices can be obtained.


Pitfall: Sequences

In Getting Started with Lua, we introduced sets in Lua, which provide rich features to assist in code writing. However, we have not heard of sequences. A sequence is something like this:

local x, y = GetCenterXY(Shapes) -- using this function temporarily
+

Here, x and y form a sequence. Here's another scenario:

GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) -- using another function here temporarily
+

In this case, the more points that are inputted, the more return values there will be. If four points are inputted, it can be handled like this:

-- Normal case
+d1, d2, d3, d4 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4)
+
+-- Only the first two return values can be kept
+d1, d2 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4)
+
+-- Of course, only one return value can be kept as well
+d1 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4)
+

The number of input parameters and output parameters in the above function are related. If n points are inputted as parameters, n distances will be returned. However, for the network topology, when returning the shortest path, the returned values are always parameter sequences, and I don't know how many parameters the function will give me; and when there are too many output parameters, it is also not feasible to manually create many variables to store these parameters.

-- Wrong approach:
+local indexList = GetSTPPath(Network, endID, "iLinkShp")
+-- The GetSTPPath() function does not return a table
+-- The indexList obtained here is only the index of the first Link, which is a numerical value.
+

Since the left side of the equal sign cannot be changed, let's make changes on the right side. Do you remember how to define a simplest table?

local list = {1, 2, 3, 4, 5}
+

The [to_be_replace[x]] on the right side can actually be seen as a sequence. So, as long as you add parentheses to the return value of a function, you can pick them all up ( •̀ ω •́ )✧

local indexList = { GetSTPPath(Network, endID, "iLinkShp") }
+

The indexList obtained using the above method is a variable of table type. Then, you can start performing various operations on the collection 😋

`,20),v={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},f=a("strong",null,"feedback",-1);function y(w,q){const t=i("RouterLink"),p=i("ExternalLinkIcon");return u(),r("div",null,[h,a("p",null,[n("MicroCity can handle networks, and the specific usage of all functions can be found in the reference document: "),s(t,{to:"/en/docs/4.6_networks.html"},{default:o(()=>[n("4.6 Networks")]),_:1})]),k,a("p",null,[n("For the specific usage of the "),m,n(" function, please refer to "),s(t,{to:"/en/docs/4.3_shapes_and_tables.html"},{default:o(()=>[n("4.3 Vector Graphics and Tables")]),_:1})]),g,a("p",null,[n("For detailed usage of the functions, please refer to "),s(t,{to:"/en/docs/4.6_networks.html#algorithms"},{default:o(()=>[n("4.6 Networks - Algorithms")]),_:1}),n(". Here, only the second method, which returns the sequence of point or line indices, will be used as an example.")]),b,a("blockquote",null,[a("p",null,[n("This post is translated using ChatGPT, please "),a("a",v,[f,s(p)]),n(" if any omissions.")])])])}const I=l(d,[["render",y],["__file","network.html.vue"]]);export{I as default}; diff --git a/assets/network.html-td-Kb3D8.js b/assets/network.html-td-Kb3D8.js deleted file mode 100644 index 35385c22..00000000 --- a/assets/network.html-td-Kb3D8.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-16cb829c","path":"/notes/network.html","title":"操作网络","lang":"zh-CN","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,网络,拓补,network"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/network.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"操作网络"}],["meta",{"property":"og:description","content":"网络拓补化 网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题: 1. 这条路是单向通行的还是双向通行? 2. 这条路的起点是哪?终点是哪? 一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-20T02:50:58.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"操作网络"}],["meta",{"property":"article:modified_time","content":"2022-12-20T02:50:58.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"操作网络\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-20T02:50:58.000Z\\",\\"author\\":[]}"]],"description":"网络拓补化 网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题: 1. 这条路是单向通行的还是双向通行? 2. 这条路的起点是哪?终点是哪? 一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的..."},"headers":[{"level":2,"title":"网络拓补化","slug":"网络拓补化","link":"#网络拓补化","children":[]},{"level":2,"title":"使用函数对网络进行拓补","slug":"使用函数对网络进行拓补","link":"#使用函数对网络进行拓补","children":[]},{"level":2,"title":"网络拓补的简单示例","slug":"网络拓补的简单示例","link":"#网络拓补的简单示例","children":[{"level":3,"title":"踩坑经验:创建网络对象","slug":"踩坑经验-创建网络对象","link":"#踩坑经验-创建网络对象","children":[]},{"level":3,"title":"CopyShapeTo函数","slug":"copyshapeto函数","link":"#copyshapeto函数","children":[]}]},{"level":2,"title":"网络拓补化后算法的使用","slug":"网络拓补化后算法的使用","link":"#网络拓补化后算法的使用","children":[{"level":3,"title":"计算最短路径和最短路长","slug":"计算最短路径和最短路长","link":"#计算最短路径和最短路长","children":[]},{"level":3,"title":"踩坑经验:序列","slug":"踩坑经验-序列","link":"#踩坑经验-序列","children":[]}]}],"git":{"updatedTime":1671504658000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":7}]},"filePathRelative":"notes/network.md","autoDesc":true}');export{t as data}; diff --git a/assets/oop.html-GH4Nnww4.js b/assets/oop.html-GH4Nnww4.js new file mode 100644 index 00000000..ca405bb1 --- /dev/null +++ b/assets/oop.html-GH4Nnww4.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c58fd9e0","path":"/notes/oop.html","title":"面向对象编程","lang":"zh-CN","frontmatter":{"description":"面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。 堆场对象 网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/oop.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/oop.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"面向对象编程"}],["meta",{"property":"og:description","content":"面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。 堆场对象 网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T16:30:53.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T16:30:53.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"面向对象编程\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T16:30:53.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"面向对象编程的基本概念","slug":"面向对象编程的基本概念","link":"#面向对象编程的基本概念","children":[{"level":3,"title":"类和对象","slug":"类和对象","link":"#类和对象","children":[]},{"level":3,"title":"类的属性和方法","slug":"类的属性和方法","link":"#类的属性和方法","children":[]}]},{"level":2,"title":"仿真中使用面向对象的优点和缺点","slug":"仿真中使用面向对象的优点和缺点","link":"#仿真中使用面向对象的优点和缺点","children":[{"level":3,"title":"优点","slug":"优点","link":"#优点","children":[]},{"level":3,"title":"缺点","slug":"缺点","link":"#缺点","children":[]}]},{"level":2,"title":"面向对象在Lua中的实现","slug":"面向对象在lua中的实现","link":"#面向对象在lua中的实现","children":[{"level":3,"title":"示例","slug":"示例","link":"#示例","children":[]}]},{"level":2,"title":"类的类型","slug":"类的类型","link":"#类的类型","children":[]}],"git":{"updatedTime":1701016253000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"notes/oop.md","autoDesc":true}');export{e as data}; diff --git a/assets/oop.html-QdhyUyOK.js b/assets/oop.html-QdhyUyOK.js new file mode 100644 index 00000000..04e1cd98 --- /dev/null +++ b/assets/oop.html-QdhyUyOK.js @@ -0,0 +1,68 @@ +import{_ as e}from"./RMGObjects-PwARz0cG.js";import{_ as t,r as o,o as i,c,a as n,b as s,d as p,e as l}from"./app-LOf__QKq.js";const r={},u=l('

Object-Oriented Programming

Object-Oriented Programming (OOP) is a programming paradigm that abstracts real-world entities into objects in the program world. Objects communicate with each other through message passing, forming the functionality of a program.

Yard Objects

According to online sources, OOP has three main characteristics: encapsulation, inheritance, and polymorphism. However, in this simulation, encapsulation is the most frequently used, while the opportunities for inheritance and polymorphism are rare. Additionally, I haven't implemented object message passing in MicroCity yet. If I do, I will update this article accordingly. Therefore, the following mainly introduces how to use encapsulation in Lua code for MicroCity.

Tips

The code examples in this article are applicable to MicroCityWeb and may not necessarily work for the desktop version of MicroCity. Furthermore, this article is based on personal insights and does not guarantee absolute correctness in terms of concepts.

Basic Concepts of Object-Oriented Programming

Classes and Objects

In simple terms, a class is a template for objects, and an object is an instance of a class.

A class is a fundamental concept in object-oriented programming that represents a category of things. The concept of a class can be understood as a category of objects—such as AGVs, shelves, and gantry cranes. You can think of a class as a template for a category of things, and objects are specific instances created based on this template.

A good example is the mentioned shelf. A shelf is a class, and a specific shelf is an object. The shelf class contains various attributes, such as the shelf's location and the items it holds. Different shelf objects created from the shelf class belong to the shelf class, such as Shelf 1, Shelf 2, etc. Although their attributes may differ, they are all objects of the shelf class.

Class Attributes and Methods

In MicroCity simulation, based on my personal experience, classes usually have attributes but not necessarily methods. Continuing with the example of a shelf mentioned earlier, attributes are the characteristics of a class, such as the location of the shelf and the items on the shelf. Methods represent the behaviors of a class and are usually implemented with functions, such as an AGV lifting or placing a shelf, an AGV moving, or driving a shelf.

Advantages and Disadvantages of Using Object-Oriented Programming in Simulation

Advantages

In MicroCity, when dealing with scenarios involving the movement of multiple objects of the same type and playing animations of object movements (such as AGVs, shelves, and gantry cranes), a considerable amount of coordinate calculations and position settings are required. If each object needs to be implemented individually, the code for modifying the coordinate of each object will become very long, making it difficult to maintain. By using the object-oriented programming paradigm, data processing code can be encapsulated into individual objects, making the code more readable and maintainable.

Furthermore, if multiple objects of the same type need to be created in a scene, each object may have different parameters. By encapsulating using object-oriented methods, each object's parameters can be encapsulated within the objects themselves. When the simulation process or scale becomes more complex, the reusability of the code can be increased.

For simulations, the most important aspect is understanding the business process and business logic. Using object-oriented programming can make the simulation's business process and logic more clear, improve code readability, and increase maintainability. Furthermore, when it is necessary to modify the business logic of a class of objects, you only need to enter the class and make the modification. For example, modifying the scheduling algorithm for all gantry cranes in a port only needs to be done once because all gantry cranes share the same scheduling algorithm.

Based on personal experience, when using object-oriented methods to encapsulate objects, it is mostly intended to create a generic object and then create multiple objects of the same type in subsequent simulations automatically or manually, with different parameters for each object. This increases code reusability and improves code readability, providing convenience for future maintenance and modifications, and lays a foundation for large-scale simulations.

Disadvantages

If the simulation is small in scale and involves simple operations with a small codebase, it is not recommended to use object-oriented methods for code encapsulation. Using object-oriented methods will increase the number of lines of code, and may make the code appear more complex than the original problem. (Of course, there will be no consequences if you still choose to use it, except that it may look strange.) Specifically, you can refer to the provided code examples in the following sections and notice that most of the code is dedicated to describing classes and their business logic, while the code for the business process is simple and occupies a small proportion.

Implementation of Object-Oriented Programming in Lua

In Lua, the concept of object-oriented programming is typically implemented using tables. A table is a data structure in Lua that can represent arrays, dictionaries, objects, etc. In object-oriented programming, tables can be used to represent objects.

Example

Since the objects created in MicroCity are tables, we can encapsulate the object's attributes directly in a table and return that table when creating an object.

Here's an example:

-- The function will return an AGV object
+function AGV()
+    -- Create a 3D object of an AGV in MicroCity
+    local agv = scene.addobj('/res/agv.glb')
+
+    -- Set the properties of the object
+    agv.position = {0, 0, 0} -- Set the position of the object
+    agv.speed = 1 -- Set the speed of the object
+
+    function agv:move(dx, dy, dz)
+        agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- Modify the object's coordinates
+
+        agv:setpos(agv.position[1], agv.position[2], agv.position[3]) -- Set the object's position
+        scene.render() -- Render the scene (Not recommended to call here, just for demonstration purposes)
+    end
+
+    return agv -- Return the object
+end
+
+-- Object usage
+local obj = AGV() -- Create an object
+obj:move(1, 0, 0) -- Move the object 1 unit in the x direction
+

Or you can choose to encapsulate the object within a table and return that table after creating the object.

-- The function will return an AGV object
+function AGV()
+    -- Set the object's properties directly in the table to be returned
+    local agv = {
+        object = scene.addobj('/res/agv.glb'),
+        position = {0, 0, 0},
+        speed = 1
+    }
+
+    function agv:move(dx, dy, dz)
+        agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- Modify the object's coordinates
+
+        agv.object:setpos(agv.position[1], agv.position[2], agv.position[3]) -- Set the object's position
+        scene.render() -- Render the scene (Not recommended to call here, just for demonstration purposes)
+    end
+
+    return agv -- Return the object
+end
+
+-- Object usage
+local agv = AGV() -- Create an object
+agv:move(1, 0, 0) -- Move the object 1 unit in the x direction
+

There is also another method to create objects using setmetatable, this belongs to advanced usage, but I feel like it is not used very often. However, it seems like this method can be used to achieve class inheritance, if you are interested, you can search for it yourself. Here is the code implementation of the shelf class that I wrote for an earlier assignment as a reference. (Now I feel like this class is not written very well 😂, for example, x and y can be replaced with pos = {x, y}, and x_origin and y_origin can be replaced with origin = {x, y}).

-- Shelf
+Shelf = {
+    x = 1,
+    y = 1,
+    cargo = {"box"}, -- Items on the shelf
+    x_origin = 1, -- Shelf's original x coordinate
+    y_origin = 1 -- Shelf's original y coordinate
+}
+
+function Shelf:New(x, y)
+    local self = {}
+    setmetatable(self, {
+        __index = Shelf
+    })
+    self.__index = self
+
+    self.x = x
+    self.y = y
+    -- Set the original coordinates
+    self.x_origin = x
+    self.y_origin = y
+    return self
+end
+

Types of Classes

Here, I would like to summarize the main types of classes that I have created.

  1. 3D entity classes: These classes mainly control the movement of 3D entities, such as AGVs and cranes. Most of them have physical entities that need to be moved. Some even include sub-objects, such as crane objects that have hoists, ropes, and cranes as sub-objects.
  2. Data model classes: These classes represent various entities in a system, such as yards, shelves, and goods. For example, a yard class contains data about the yard's dimensions, the goods in the yard, and the containers in the yard.

It should be noted that I do not strictly categorize these types, as certain classes may possess the characteristics of multiple types. For instance, an AGV class also includes data about the AGV's position and speed, while a shelf class merely stores the shelf model. The movement of the shelf model is controlled by the AGV, and the more important function of the shelf class is to record the information of the goods on the shelf. Therefore, I consider these types as rough distinctions, and the specific implementation should be based on the actual business processes and requirements.

`,34),d={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},m=n("strong",null,"feedback",-1);function h(k,b){const a=o("ExternalLinkIcon");return i(),c("div",null,[u,n("blockquote",null,[n("p",null,[s("This post is translated using ChatGPT, please "),n("a",d,[m,p(a)]),s(" if any omissions.")])])])}const f=t(r,[["render",h],["__file","oop.html.vue"]]);export{f as default}; diff --git a/assets/oop.html-3LUP3-Yz.js b/assets/oop.html-VmjZry6A.js similarity index 71% rename from assets/oop.html-3LUP3-Yz.js rename to assets/oop.html-VmjZry6A.js index e6093f27..b840fa80 100644 --- a/assets/oop.html-3LUP3-Yz.js +++ b/assets/oop.html-VmjZry6A.js @@ -1,4 +1,4 @@ -import{_ as n,o as s,c as a,e as p}from"./app-DaLjD81q.js";const t="/MicroCityNotes/assets/RMGObjects-yrTAIJHV.png",e={},o=p('

面向对象编程

面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。

堆场对象

网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实现过对象的消息传递,如果实现了会继续更新本文。因此下面主要介绍一下如何在适用于MicroCity的lua代码中使用封装。

提示

本文中的代码示例适用于MicroCityWeb,对于桌面版的MicroCity不一定适用。此外,本文均为个人感悟,不保证概念绝对的正确性。

面向对象编程的基本概念

类和对象

通俗来说,类是对象的模板,对象是类的实例(实体)。

类是面向对象编程的基本概念,它是对一类事物的抽象。类的概念可以理解为一类对象,比如AGV、货架、场桥等。你可以把类理解为一类事物的模板,而对象则是根据这个模板创建出来的具体的事物。

一个比较好的例子是上面提到的货架。货架是一个类,那么具体的货架就是一个对象。货架类中包含了货架的各种属性,比如货架的位置,装载的货物等。通过货架类创建出来的不同的货架对象都属于货架类,比如货架1、货架2等,尽管它们的属性可能不同,但是它们都是货架类的对象。

类的属性和方法

在MicroCity的仿真中,就我个人遇到的情况而言,类一般会有属性,但是不一定会有方法。延续上面举的货架的例子来说,属性是类的特征,比如货架的位置、货架上的货物等。方法是类的行为,通常使用函数体现,比如AGV将货架抬起、放下、AGV移动或者带动货架移动。

仿真中使用面向对象的优点和缺点

优点

在MicroCity中,就涉及到多个同类物体移动、播放物体移动动画等场景而言(如AGV、货架、场桥移动等),需要进行比较大量的坐标计算和位置设置。如果对每个对象都实现一次,那么修改各个对象坐标的代码将会非常冗长,而且不易于维护。如果使用面向对象的编程思想,可以将数据处理的代码封装成一个个的对象,也能使代码更加更具有可读性和可维护性。

此外,如果在场景中创建多个同类对象,各个对象的参数也可能各不相同。如果使用面向对象的方法封装,可以将各个对象的参数封装在各个对象自身中。当仿真流程或者规模变得复杂时,能够增加代码的复用性。

对于仿真来说,最重要的是搞清楚仿真的业务流程和业务逻辑。使用面向对象编程可以使仿真的业务流程和业务逻辑体现得更清晰,使代码的可读性提高,更具有可维护性。 此外,当需要修改一类对象的业务逻辑时,只需要进入类中修改即可。比如修改一个港口中所有场桥的调度算法,由于所有场桥共用一套调度算法,因此只需要修改一次即可。

就我个人的情况而言,采用面向对象的方法封装对象时大多是希望创建一个通用的对象,然后在后续的仿真中通过自动或手动的方式创建多个同类对象,而各个对象的参数各不相同。这么做会使得代码通用性增加,而且也能够使得代码更加易懂,为后续的维护和修改提供便利,为大规模的仿真打下基础。

缺点

如果仿真规模很小,代码量不大的简单的操作,不建议使用面向对象的方法封装代码。 使用面向对象的方法会增加代码行数,甚至会使代码看起来显得比原问题更加复杂。(当然你要用也不会有什么后果,只是看起来会比较奇怪而已)具体可以参考下文提供的代码示例,不难发现,代码主要篇幅用在描述类及其业务逻辑上,而业务流程的代码很简单,且占比很小。

面向对象在Lua中的实现

在Lua中,面向对象的概念通常使用table实现。table是Lua中的一种数据结构,它可以用来表示数组、字典、对象等。在面向对象的编程中,table也可以用来表示对象。

示例

由于MicroCity中创建的对象都是table,因此我们可以在创建对象时,将对象的属性直接封装在table中,然后返回这个table。

下面是一个例子:

-- 函数将返回一个AGV对象
+import{_ as n}from"./RMGObjects-PwARz0cG.js";import{_ as s,o as a,c as p,e as t}from"./app-LOf__QKq.js";const e={},o=t('

面向对象编程

面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。

堆场对象

网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实现过对象的消息传递,如果实现了会继续更新本文。因此下面主要介绍一下如何在适用于MicroCity的lua代码中使用封装。

提示

本文中的代码示例适用于MicroCityWeb,对于桌面版的MicroCity不一定适用。此外,本文均为个人感悟,不保证概念绝对的正确性。

面向对象编程的基本概念

类和对象

通俗来说,类是对象的模板,对象是类的实例(实体)。

类是面向对象编程的基本概念,它是对一类事物的抽象。类的概念可以理解为一类对象,比如AGV、货架、场桥等。你可以把类理解为一类事物的模板,而对象则是根据这个模板创建出来的具体的事物。

一个比较好的例子是上面提到的货架。货架是一个类,那么具体的货架就是一个对象。货架类中包含了货架的各种属性,比如货架的位置,装载的货物等。通过货架类创建出来的不同的货架对象都属于货架类,比如货架1、货架2等,尽管它们的属性可能不同,但是它们都是货架类的对象。

类的属性和方法

在MicroCity的仿真中,就我个人遇到的情况而言,类一般会有属性,但是不一定会有方法。延续上面举的货架的例子来说,属性是类的特征,比如货架的位置、货架上的货物等。方法是类的行为,通常使用函数体现,比如AGV将货架抬起、放下、AGV移动或者带动货架移动。

仿真中使用面向对象的优点和缺点

优点

在MicroCity中,就涉及到多个同类物体移动、播放物体移动动画等场景而言(如AGV、货架、场桥移动等),需要进行比较大量的坐标计算和位置设置。如果对每个对象都实现一次,那么修改各个对象坐标的代码将会非常冗长,而且不易于维护。如果使用面向对象的编程思想,可以将数据处理的代码封装成一个个的对象,也能使代码更加更具有可读性和可维护性。

此外,如果在场景中创建多个同类对象,各个对象的参数也可能各不相同。如果使用面向对象的方法封装,可以将各个对象的参数封装在各个对象自身中。当仿真流程或者规模变得复杂时,能够增加代码的复用性。

对于仿真来说,最重要的是搞清楚仿真的业务流程和业务逻辑。使用面向对象编程可以使仿真的业务流程和业务逻辑体现得更清晰,使代码的可读性提高,更具有可维护性。 此外,当需要修改一类对象的业务逻辑时,只需要进入类中修改即可。比如修改一个港口中所有场桥的调度算法,由于所有场桥共用一套调度算法,因此只需要修改一次即可。

就我个人的情况而言,采用面向对象的方法封装对象时大多是希望创建一个通用的对象,然后在后续的仿真中通过自动或手动的方式创建多个同类对象,而各个对象的参数各不相同。这么做会使得代码通用性增加,而且也能够使得代码更加易懂,为后续的维护和修改提供便利,为大规模的仿真打下基础。

缺点

如果仿真规模很小,代码量不大的简单的操作,不建议使用面向对象的方法封装代码。 使用面向对象的方法会增加代码行数,甚至会使代码看起来显得比原问题更加复杂。(当然你要用也不会有什么后果,只是看起来会比较奇怪而已)具体可以参考下文提供的代码示例,不难发现,代码主要篇幅用在描述类及其业务逻辑上,而业务流程的代码很简单,且占比很小。

面向对象在Lua中的实现

在Lua中,面向对象的概念通常使用table实现。table是Lua中的一种数据结构,它可以用来表示数组、字典、对象等。在面向对象的编程中,table也可以用来表示对象。

示例

由于MicroCity中创建的对象都是table,因此我们可以在创建对象时,将对象的属性直接封装在table中,然后返回这个table。

下面是一个例子:

-- 函数将返回一个AGV对象
 function AGV()
     -- 在MicroCity中创建一个AGV的3d对象
     local agv = scene.addobj('/res/agv.glb')
@@ -65,4 +65,4 @@ Shelf = {.y_origin = y
     return self
 end
-

类的类型

我在这里还想总结一下我创建过的类主要有什么类型。

  1. 3D实体类。 主要控制3D实体的运动,如AGV、场桥等,它们大多具有实体且需要移动。有的甚至还包含子对象,比如场桥对象具有吊具、绳索、吊车等子对象。
  2. 数据模型。 比如堆场,货架、货物。具体来说比如堆场类中包含堆场的长宽、堆场中的货物、堆场中的集装箱等数据。

需要注意的是,我认为这些类型也不是严格区分的,某些类甚至共同具有这些类的特性,严格区分这个类属于哪种类型也没有太大意义。比如AGV类中也包含了AGV的位置、速度等数据,而货架类只是存储了货架模型,货架模型的移动还是交由AGV控制,而其更重要的功能是记录货架上货物的信息。因此,我认为这些类型只是一种大致的划分,具体的实现还是要根据实际业务流程和需求情况来。

`,34),c=[o];function i(l,u){return s(),a("div",null,c)}const d=n(e,[["render",i],["__file","oop.html.vue"]]);export{d as default}; +

类的类型

我在这里还想总结一下我创建过的类主要有什么类型。

  1. 3D实体类。 主要控制3D实体的运动,如AGV、场桥等,它们大多具有实体且需要移动。有的甚至还包含子对象,比如场桥对象具有吊具、绳索、吊车等子对象。
  2. 数据模型。 比如堆场,货架、货物。具体来说比如堆场类中包含堆场的长宽、堆场中的货物、堆场中的集装箱等数据。

需要注意的是,我认为这些类型也不是严格区分的,某些类甚至共同具有这些类的特性,严格区分这个类属于哪种类型也没有太大意义。比如AGV类中也包含了AGV的位置、速度等数据,而货架类只是存储了货架模型,货架模型的移动还是交由AGV控制,而其更重要的功能是记录货架上货物的信息。因此,我认为这些类型只是一种大致的划分,具体的实现还是要根据实际业务流程和需求情况来。

`,34),c=[o];function i(l,u){return a(),p("div",null,c)}const k=s(e,[["render",i],["__file","oop.html.vue"]]);export{k as default}; diff --git a/assets/oop.html-azlXcYwP.js b/assets/oop.html-azlXcYwP.js deleted file mode 100644 index 86c9ce1b..00000000 --- a/assets/oop.html-azlXcYwP.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-c58fd9e0","path":"/notes/oop.html","title":"面向对象编程","lang":"zh-CN","frontmatter":{"description":"面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。 堆场对象 网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/oop.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"面向对象编程"}],["meta",{"property":"og:description","content":"面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。 堆场对象 网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-05-21T08:26:32.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"面向对象编程"}],["meta",{"property":"article:modified_time","content":"2023-05-21T08:26:32.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"面向对象编程\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-05-21T08:26:32.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"面向对象编程的基本概念","slug":"面向对象编程的基本概念","link":"#面向对象编程的基本概念","children":[{"level":3,"title":"类和对象","slug":"类和对象","link":"#类和对象","children":[]},{"level":3,"title":"类的属性和方法","slug":"类的属性和方法","link":"#类的属性和方法","children":[]}]},{"level":2,"title":"仿真中使用面向对象的优点和缺点","slug":"仿真中使用面向对象的优点和缺点","link":"#仿真中使用面向对象的优点和缺点","children":[{"level":3,"title":"优点","slug":"优点","link":"#优点","children":[]},{"level":3,"title":"缺点","slug":"缺点","link":"#缺点","children":[]}]},{"level":2,"title":"面向对象在Lua中的实现","slug":"面向对象在lua中的实现","link":"#面向对象在lua中的实现","children":[{"level":3,"title":"示例","slug":"示例","link":"#示例","children":[]}]},{"level":2,"title":"类的类型","slug":"类的类型","link":"#类的类型","children":[]}],"git":{"updatedTime":1684657592000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"notes/oop.md","autoDesc":true}');export{t as data}; diff --git a/assets/oop.html-lICjQDMc.js b/assets/oop.html-lICjQDMc.js new file mode 100644 index 00000000..ded8d7de --- /dev/null +++ b/assets/oop.html-lICjQDMc.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3d68f424","path":"/en/notes/oop.html","title":"Object-Oriented Programming","lang":"en-US","frontmatter":{"description":"Object-Oriented Programming (OOP) is a programming paradigm that abstracts real-world entities into objects in the program world. Objects communicate with each other through mes...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/oop.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/oop.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Object-Oriented Programming"}],["meta",{"property":"og:description","content":"Object-Oriented Programming (OOP) is a programming paradigm that abstracts real-world entities into objects in the program world. Objects communicate with each other through mes..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Object-Oriented Programming\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Basic Concepts of Object-Oriented Programming","slug":"basic-concepts-of-object-oriented-programming","link":"#basic-concepts-of-object-oriented-programming","children":[{"level":3,"title":"Classes and Objects","slug":"classes-and-objects","link":"#classes-and-objects","children":[]},{"level":3,"title":"Class Attributes and Methods","slug":"class-attributes-and-methods","link":"#class-attributes-and-methods","children":[]}]},{"level":2,"title":"Advantages and Disadvantages of Using Object-Oriented Programming in Simulation","slug":"advantages-and-disadvantages-of-using-object-oriented-programming-in-simulation","link":"#advantages-and-disadvantages-of-using-object-oriented-programming-in-simulation","children":[{"level":3,"title":"Advantages","slug":"advantages","link":"#advantages","children":[]},{"level":3,"title":"Disadvantages","slug":"disadvantages","link":"#disadvantages","children":[]}]},{"level":2,"title":"Implementation of Object-Oriented Programming in Lua","slug":"implementation-of-object-oriented-programming-in-lua","link":"#implementation-of-object-oriented-programming-in-lua","children":[{"level":3,"title":"Example","slug":"example","link":"#example","children":[]}]},{"level":2,"title":"Types of Classes","slug":"types-of-classes","link":"#types-of-classes","children":[]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/oop.md","autoDesc":true}');export{e as data}; diff --git a/assets/play-RaBYbg3m.js b/assets/play-RaBYbg3m.js new file mode 100644 index 00000000..1a5a1e06 --- /dev/null +++ b/assets/play-RaBYbg3m.js @@ -0,0 +1 @@ +const e="data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='utf-8'?%3e%3c!--%20Generator:%20Adobe%20Illustrator%2016.0.0,%20SVG%20Export%20Plug-In%20.%20SVG%20Version:%206.00%20Build%200)%20--%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20version='1.1'%20id='图层_1'%20xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'%20xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'%20xmlns:svg='http://www.w3.org/2000/svg'%20inkscape:version='1.2.2%20(732a01da63,%202022-12-09)'%20sodipodi:docname='play.svg'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20x='0px'%20y='0px'%20width='24px'%20height='24px'%20viewBox='0%200%2024%2024'%20enable-background='new%200%200%2024%2024'%20xml:space='preserve'%3e%3csodipodi:namedview%20inkscape:cy='12.014337'%20inkscape:cx='8.0860215'%20inkscape:zoom='34.875'%20showgrid='false'%20borderopacity='0.25'%20bordercolor='%23000000'%20pagecolor='%23ffffff'%20id='namedview255'%20inkscape:current-layer='图层_1'%20inkscape:window-width='1920'%20inkscape:window-y='-8'%20inkscape:deskcolor='%23d1d1d1'%20inkscape:pagecheckerboard='0'%20inkscape:window-maximized='1'%20inkscape:pageopacity='0.0'%20inkscape:showpageshadow='2'%20inkscape:window-x='-8'%20inkscape:window-height='1017'%3e%3c/sodipodi:namedview%3e%3ctitle%20id='title249'%3eic_fluent_play_24_regular%3c/title%3e%3cdesc%20id='desc251'%3eCreated%20with%20Sketch.%3c/desc%3e%3cpath%20id='_xD83C__xDFA8_-Color'%20inkscape:highlight-color='%23000000'%20d='M6.34,2.275C5.253,1.673,3.884,2.066,3.282,3.153%20C3.097,3.487,3,3.862,3,4.243V19.76c0,1.242,1.007,2.25,2.25,2.25c0.381,0,0.756-0.098,1.09-0.281l14.008-7.76%20c1.088-0.603,1.479-1.972,0.879-3.059c-0.205-0.37-0.51-0.674-0.879-0.878L6.34,2.275z%20M19.914,11.637%20c0.201,0.362,0.07,0.819-0.293,1.02L5.613,20.415C5.502,20.477,5.377,20.51,5.25,20.51c-0.414,0-0.75-0.336-0.75-0.75V4.243%20c0-0.127,0.032-0.252,0.094-0.363c0.201-0.362,0.657-0.493,1.02-0.292l14.008,7.757C19.744,11.412,19.846,11.514,19.914,11.637z'/%3e%3c/svg%3e";export{e as _}; diff --git a/assets/plots.html-6AeiZZxH.js b/assets/plots.html-6AeiZZxH.js new file mode 100644 index 00000000..c3ffad9b --- /dev/null +++ b/assets/plots.html-6AeiZZxH.js @@ -0,0 +1,258 @@ +import{_ as o,a as e}from"./Subplot_Vertical-oXTmfxKU.js";import{_ as c,r as l,o as u,c as i,a as n,b as s,d as t,e as p}from"./app-LOf__QKq.js";const r={},k=p('

Generic Drawing Code

This section provides some pre-written drawing objects, which are convenient for direct use when visualizing data.

Info

All open source code on this page is licensed under the MIT license and can be used freely. However, please retain the copyright information when publicly distributing.

Histogram

A histogram is generally used to display the frequency or frequency distribution of various data values in a data set. It divides the data into several intervals (or "bins") according to a certain interval and then plots the frequency (or frequency) of each interval as a bar chart on the y-axis to reflect the distribution of the data.

Here is an example of a histogram drawn using the histogram object I wrapped.

Histogram Example

Importing the Histogram

First, import the histogram code. There are currently two options:

  1. Download the code file and import it (recommended): [Download the histogram code file](#Code file download) Histogram.lua and import it into MicroCityWeb. Then, reference the file to use it. The code reference is as follows:
require("Histogram") --Reference the histogram
+
  1. Copy the code: Copy the code from the Histogram.lua file directly into your code. The code is shown [below](#Histogram Code).

Creating a Histogram Object

Create a histogram object.

local plot = Histogram(list) -- list is the data set
+

You can also set the properties of the graph when creating the object.

local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end})
+

Setting the properties is not necessary and can be done as needed. In this case, only the range, scale, and fdisp properties are set.

Setting Histogram Properties

The above example provides a simple demonstration of setting histogram properties. According to the code, more properties can be set. See the table below for details:

PropertyFunctionExample
originSet the origin of the graph (bottom-left point)origin = {-50, -50}, set the origin of the graph at position (-50,-50)
sizeSet the length of the x and y axes of the graphsize = {100, 100}, set the length of the x and y axes of the graph to 100 each
scaleSet the graduations of the x and y axesscale = {3, 2}, set the graduations of the x and y axes of the graph to 3 and 2 respectively
axislabelSet the titles of the x and y axesaxislabel = {"x", "y"}, set the titles of the x and y axes of the graph to "x" and "y" respectively
rangeSet the display range of the x and y axesrange = {0, 10, 0, 20}, set the x-axis range of the graph to [0,10] and the y-axis range to [0,20]
filledSet whether to fill the bar chartfilled = false, set the bar chart to unfilled. The default style is filled
fdispThe display function for data labels, which defaults to the quantity. When setting the display function for data labels, it will also affect the display of y-axis tick marks.fdisp = function(v) return (v/n*100).."%" end, change the data labels to display in proportion (assuming n is the sample size)

Advanced Usage of Histograms

Dynamically refresh the data plot.

  1. Modify the data in the graph. Here, we use adding data to the graph as an example. Let's assume rnd is the data to be added. You can also directly modify the value of plot.data.
table.insert(plot.data, rnd)
+
  1. Refresh the graph.
plot:refresh()
+

Example

Basic Usage Example: Drawing a Poisson Distribution

require("Histogram") --Reference the histogram
+
+local seed = math.randomseed(1, {
+    distribution = "poisson",
+    mu = "3"
+})
+local list = {seed:random()}
+
+
+--Static drawing
+for i = #list, 400 do
+    table.insert(list, seed:random())
+end
+
+local histplot = Histogram(list, {
+    range = {0, 10, 0, 50},
+    scale = {1, 5}
+})
+scene.render()
+

Advanced Usage Example: Dynamically Refreshing Plot of the Poisson Distribution

This is an example of plotting the Poisson distribution and dynamically refreshing the data plot. It is assumed that the Histogram object has been imported and the scene is set for 2D display.

require("Histogram") -- Import the histogram
+
+local seed = math.randomseed(1, {
+    distribution = "poisson",
+    mu = "3"
+})
+local list = {seed:random()}
+
+local histplot = Histogram(list, {
+    range = {0, 10, 0, 50},
+    scale = {1, 8}
+})
+scene.render()
+
+-- Dynamic drawing
+local count = 1
+while count < 1000 do
+    local rnd = seed:random()
+    table.insert(histplot.data, rnd)
+
+    histplot:refresh()
+    count = count + 1
+    scene.render()
+end
+

Subplots

Subplots are a way to position and size multiple plots within a single interface. The name is borrowed from MATLAB.

Subplots

Importing Subplots

First, import the code for subplots. Like histograms, there are two options for importing:

  1. Download the code file and import (recommended): Download the subplot code file, import the Subplot.lua file in MicroCityWeb, and then use the code. Use the following code to import:
    require("Subplot") -- Import the subplot code
    +
  2. Copy the code: Copy the code from the Subplot.lua file directly into your code. In this case, there is no need to import the code. See the code below.

Creating Subplot Objects

When creating a subplot, you must specify the number of rows and columns. The number of rows and columns determines the number of subplots.

local subplot = Subplot(rows, cols)
+

You can also set additional properties to define the position and size of the subplots. Here is an example of setting the position and size of the subplots when creating them:

local subplot = Subplot(rows, cols, {span=10, diag={-80, -70, 80, 70}})
+

Setting Subplot Properties

Here, we will provide a detailed description of the properties of subplots. Setting these properties is optional and can be done as needed.

PropertyDescriptionExample
spanSets the spacing between subplotsspan=10, sets the spacing between subplots to 10 in all directions
diagSets the position and size of a subplot by specifying the coordinates of the two diagonal pointsdiag = {-80, -70, 80, 70}, sets the diagonal range of the subplot from coordinates (-80,-70) to (80,70)

Reading Subplot Values

After creating a subplot with properties, or modifying the properties and refreshing, you can read the values of the subplots, including the origin position and size of each subplot, using the following attributes.

Note

Here, it is assumed that the subplot object is stored in the subplot variable after creation.

AttributeMeaningExample
originptThe origin position of each subplot in the Subplot objectThe origin position of the subplot in the i-th row and j-th column can be obtained by subplot.originpt[i][j][1] and subplot.originpt[i][j][2]
psizeThe size of each subplot in the Subplot objectThe width and height of the subplot in the subplot can be obtained by subplot.psize[1] and subplot.psize[2].(assuming all subplots have the same size)

Example

This is an example of drawing the range of subplots. Assume that the Subplot object has been imported and the scene has been set to 2D display.

Here, the display range of each subplot in a 2x3 subplot is drawn as a rectangle. The range of each subplot is represented by four gray points, and the position of each subplot is represented by a blue rectangle.

require("Subplot") -- import the Subplot library
+
+local subplot = Subplot(2, 3, {span = 10})
+
+-- Draw the boundary points of the Subplot object
+local lb = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[2],0}})
+local lt = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[4],0}})
+local rb = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[4],0}})
+local rt = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[2],0}})
+
+-- Draw the range of each subplot
+for i = 1, subplot.row do
+    for j = 1, subplot.col do
+        scene.addobj("polyline", {size = 8, color = "blue",
+            vertices={
+                subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0,
+                subplot.originpt[i][j][1], subplot.originpt[i][j][2], 0,
+                subplot.originpt[i][j][1], subplot.originpt[i][j][2]+subplot.psize[2], 0,
+                subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2]+subplot.psize[2], 0,
+                subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0,
+            }
+        })
+    end
+end
+scene.render()
+

Code

You can remove the scene.setenv code at the beginning depending on the combination of your code. The scene.render() in the code is used to refresh the image during dynamic drawing.

Code File Download

`,58),d={href:"https://github.com/huuhghhgyg/ModelResource/tree/main/libs",target:"_blank",rel:"noopener noreferrer"},b=n("thead",null,[n("tr",null,[n("th",null,"Name"),n("th",null,"Link")])],-1),m=n("td",null,"Histogram",-1),v={href:"https://github.com/huuhghhgyg/ModelResource/blob/main/libs/Histogram.lua",target:"_blank",rel:"noopener noreferrer"},h=n("td",null,"Subplot",-1),g={href:"https://github.com/huuhghhgyg/ModelResource/blob/main/libs/Subplot.lua",target:"_blank",rel:"noopener noreferrer"},f=p(`

Histogram Code

Histogram

-- Initial scene settings
+local s = scene.setenv({camtype = "ortho"})
+
+-- Returns a histogram object
+function Histogram(data, ...)
+    local plot = {
+        -- Default value settings
+        origin = {-50, -50}, -- Coordinate origin coordinates
+        size = {100, 100}, -- Coordinate axis length
+        scale = {3, 2}, -- Coordinate axis scale values
+        range = {0, 10, 0, 20}, -- xy-axis range
+        axislabel = {"x", "y"},
+        filled = true, -- Whether to fill
+        fdisp = function(v) -- Data label display
+            return v
+        end,
+    }
+    -- Import parameters and fallback
+    if ... ~= nil then
+        for k, v in pairs(...) do
+            plot[k] = v
+        end
+    end
+    
+    local barShape = "polygon"
+    if plot.filled == false then barShape = "polyline" end
+
+    -- Initialization
+    plot.axes = {} -- Coordinate axes
+    plot.originlabel = {} -- The zero point may have dual coordinates
+    plot.bars = {} -- Data bars
+    plot.xvalue = {} -- x-axis tick values (excluding the minimum value)
+    plot.data = data
+
+    function plot:deldata() -- Delete data (private)
+        if #plot.bars == 0 then
+            return
+        end
+
+        for i = #plot.bars, 1, -1 do
+            -- print("plot.bar:",i)
+            plot.bars[i][2]:delete()
+            plot.bars[i][1]:delete()
+        end
+
+        plot.zero:delete()
+        for i = #plot.originlabel, 1, -1 do
+            plot.originlabel[i]:delete()
+        end
+
+        for i = #plot.axes, 1, -1 do
+            for j = #plot.axes[i], 1, -1 do
+                plot.axes[i][j][2]:delete()
+                plot.axes[i][j][1]:delete()
+            end
+        end
+    end
+
+    function plot:refresh() -- Called when drawing repeatedly (public)
+        plot:deldata()
+

-- Calculate coordinate scale parameters local xmax = math.max(math.max(table.unpack(plot.data)), plot.range[2]) local xmin = math.min(math.min(table.unpack(plot.data)), plot.range[1]) local valueRange = xmax - xmin plot.range[1], plot.range[2] = xmin, xmax

-- Statistical drawing values local barData = {} for i = 1, #data do -- Deep copy table.insert(barData, data[i]) end plot.barValue = {}

-- Draw zero point plot.zero = scene.addobj("points", { vertices = {plot.origin[1], plot.origin[2], 0}, size = 10 }) if plot.range[1] == plot.range[3] then -- Both are 0 plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1] - 4, plot.origin[2] - 4, 0) else plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1], plot.origin[2] - 4, 0) plot.originlabel[2] = scene.addobj("label", { text = plot.range[3], size = 4 }) plot.originlabel[2]:setpos(plot.origin[1] - 4, plot.origin[2], 0) end

-- X-axis Scale local xaxis = {} -- x-axis object, with elements as {point, label} for j = 1, (plot.range[2] - plot.range[1]) / plot.scale[1] do -- index of the scale local xpt = plot.origin[1] + j * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] -- X-axis scale position local pt = scene.addobj("points", { vertices = {xpt, plot.origin[2], 0}, size = 5 }) -- scale point local label = scene.addobj("label", { text = string.format("%.1f", plot.range[1] + j * plot.scale[1]), size = 4 }) -- scale label table.insert(plot.xvalue, plot.range[1] + j * plot.scale[1]) -- current x-axis value label:setpos(xpt, plot.origin[2] - 4, 0) xaxis[j] = {pt, label} -- add object to x-axis collection end plot.axes[1] = xaxis

    for i = 1, #plot.axes[1] do -- based on x-axis score
+        local ub = plot.xvalue[i] -- current loop maximum value
+        -- print("Loop", i, "ub=", ub) -- for debugging
+
+        local value = 0
+        for j = #barData, 1, -1 do
+            if barData[j] <= ub then
+                value = value + 1
+                table.remove(barData, j)
+            end
+        end
+        plot.barValue[i] = value -- record value
+    end
+    local ymax = math.max(table.unpack(plot.barValue))
+    plot.range[4] = math.max(ymax, plot.range[4])
+
-- Y-axis scale
+local yaxis = {} -- y-axis objects, each element is {point, label}
+for i = 1, (plot.range[4] - plot.range[3]) / plot.scale[2] do -- index of each scale
+    local ypt = plot.origin[2] + i * plot.size[2] / (plot.range[4] - plot.range[3]) * plot.scale[2] -- Y-scale position
+    local pt = scene.addobj("points", {
+        vertices = {plot.origin[1], ypt, 0},
+        size = 5
+    }) -- scale point
+    local label = scene.addobj("label", {
+        text = plot.fdisp(plot.range[3] + i * plot.scale[2]),
+        size = 4
+    }) -- scale label
+    label:setpos(plot.origin[1] - 4, ypt, 0)
+    yaxis[i] = {pt, label}
+end
+plot.axes[2] = yaxis
+
+-- Draw data
+local xunit = plot.size[1] / (plot.range[2] - plot.range[1]) * #plot.axes[1] -- x-axis division value
+local yunit = plot.size[2] / (plot.range[4] - plot.range[3]) -- y-axis division value
+
+-- Draw histogram based on the values
+for i = 1, #plot.axes[1] do
+    -- Drawing
+    local xl = plot.origin[1] + (i - 1) * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1]
+    local xr = plot.origin[1] + i * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1]
+    local yb, yt = plot.origin[2], plot.origin[2] + plot.barValue[i] * yunit
+    local bar = scene.addobj(barShape, {
+        vertices = {xl, yb, 0, xr, yb, 0, xr, yt, 0, xl, yt, 0, xl, yb, 0}
+    })
+    local label = scene.addobj("label", {
+        text = plot.fdisp(plot.barValue[i]),
+        size = 4
+    })
+    label:setpos((xl + xr) / 2, yt + 2, 0)
+    plot.bars[i] = {bar, label}
+end
+
function plot:draw() -- Draw initialization
+    -- Coordinate axis object
+    plot.coord = scene.addobj("polyline", {
+        vertices = {plot.origin[1] + plot.size[1], plot.origin[2], 0, plot.origin[1], plot.origin[2], 0,
+                    plot.origin[1], plot.origin[2] + plot.size[2], 0}
+    })
+    -- Coordinate axis title
+    if plot.axislabel~=nil then
+        plot.axislabel[1] = scene.addobj("label", {
+            text = plot.axislabel[1],
+            size = 4
+        })
+        plot.axislabel[1]:setpos(plot.origin[1] + plot.size[1], plot.origin[2] - 8, 0)
+        plot.axislabel[2] = scene.addobj("label", {
+            text = plot.axislabel[2],
+            size = 4,
+        })
+        plot.axislabel[2]:setpos(plot.origin[1]-4, plot.origin[2] + plot.size[2]+6, 0)
+        plot.axislabel[2]:setrot(0,0,1)
+    end
+end
+
+plot:draw()
+plot:refresh()
+scene.render()
+return plot
+end
+

Subplot code

Subplot

-- Attribute parameters
+-- local diag = {-80, -70, 80, 70} -- lbx,lby,rtx,rty
+-- local span = 10
+-- local row, col = 2, 2
+function Subplot(row, col, ...)
+    local subplot = {
+        span = 10,
+        diag = {-80, -70, 80, 70},
+        originpt = {}, -- Store coordinates of each row and column
+        psize = {} -- Subplot size
+    }
+    subplot.row, subplot.col = row, col
+
+\`\`\`lua
+-- Import parameters and fallback
+if ... ~= nil then
+    for k, v in pairs(...) do
+        subplot[k] = v
+    end
+end
+
+function subplot:refresh()
+    -- Calculate parameters
+    subplot.psize = {
+        (subplot.diag[3]-subplot.diag[1] - (subplot.col-1)*subplot.span)/subplot.col,
+        (subplot.diag[4]-subplot.diag[2] - (subplot.row-1)*subplot.span)/subplot.row
+    }
+    local gwidth, gheight = subplot.psize[1]+subplot.span, subplot.psize[2]+subplot.span
+
+    -- Recalculate originpt
+    subplot.originpt = {}
+    for i = 1, subplot.row do
+        subplot.originpt[i]={}
+        for j = 1, subplot.col do
+            subplot.originpt[i][j] = {subplot.diag[1]+(j-1)*gwidth, subplot.diag[2]+(i-1)*gheight}
+        end
+    end
+end
+
+subplot:refresh()
+return subplot
+end
+
`,13),y={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},w=n("strong",null,"feedback",-1);function x(q,j){const a=l("ExternalLinkIcon");return u(),i("div",null,[k,n("p",null,[s("A list of code files can be found in "),n("a",d,[s("ModelResource/libs"),t(a)])]),n("table",null,[b,n("tbody",null,[n("tr",null,[m,n("td",null,[n("a",v,[s("ModelResource/libs/Histogram.lua"),t(a)])])]),n("tr",null,[h,n("td",null,[n("a",g,[s("ModelResource/libs/Subplot.lua"),t(a)])])])])]),f,n("blockquote",null,[n("p",null,[s("This post is translated using ChatGPT, please "),n("a",y,[w,t(a)]),s(" if any omissions.")])])])}const _=c(r,[["render",x],["__file","plots.html.vue"]]);export{_ as default}; diff --git a/assets/plots.html-FPAlzRUf.js b/assets/plots.html-FPAlzRUf.js new file mode 100644 index 00000000..100d25cb --- /dev/null +++ b/assets/plots.html-FPAlzRUf.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-471724fc","path":"/en/notes/plots.html","title":"Generic Drawing Code","lang":"en-US","frontmatter":{"description":"This section provides some pre-written drawing objects, which are convenient for direct use when visualizing data. All open source code on this page is licensed under the MIT li...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/plots.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/plots.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Generic Drawing Code"}],["meta",{"property":"og:description","content":"This section provides some pre-written drawing objects, which are convenient for direct use when visualizing data. All open source code on this page is licensed under the MIT li..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Generic Drawing Code\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Histogram","slug":"histogram","link":"#histogram","children":[{"level":3,"title":"Importing the Histogram","slug":"importing-the-histogram","link":"#importing-the-histogram","children":[]},{"level":3,"title":"Creating a Histogram Object","slug":"creating-a-histogram-object","link":"#creating-a-histogram-object","children":[]},{"level":3,"title":"Setting Histogram Properties","slug":"setting-histogram-properties","link":"#setting-histogram-properties","children":[]},{"level":3,"title":"Advanced Usage of Histograms","slug":"advanced-usage-of-histograms","link":"#advanced-usage-of-histograms","children":[]},{"level":3,"title":"Example","slug":"example","link":"#example","children":[]}]},{"level":2,"title":"Subplots","slug":"subplots","link":"#subplots","children":[{"level":3,"title":"Importing Subplots","slug":"importing-subplots","link":"#importing-subplots","children":[]},{"level":3,"title":"Creating Subplot Objects","slug":"creating-subplot-objects","link":"#creating-subplot-objects","children":[]},{"level":3,"title":"Setting Subplot Properties","slug":"setting-subplot-properties","link":"#setting-subplot-properties","children":[]},{"level":3,"title":"Reading Subplot Values","slug":"reading-subplot-values","link":"#reading-subplot-values","children":[]},{"level":3,"title":"Example","slug":"example-1","link":"#example-1","children":[]}]},{"level":2,"title":"Code","slug":"code","link":"#code","children":[{"level":3,"title":"Code File Download","slug":"code-file-download","link":"#code-file-download","children":[]},{"level":3,"title":"Histogram Code","slug":"histogram-code","link":"#histogram-code","children":[]},{"level":3,"title":"Subplot code","slug":"subplot-code","link":"#subplot-code","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/plots.md","autoDesc":true}');export{e as data}; diff --git a/assets/plots.html-JiB_VWcB.js b/assets/plots.html-JiB_VWcB.js deleted file mode 100644 index 6afd02a3..00000000 --- a/assets/plots.html-JiB_VWcB.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-f610fd24","path":"/notes/plots.html","title":"通用绘图代码","lang":"zh-CN","frontmatter":{"description":"本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。 本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。 直方图 直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/plots.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"通用绘图代码"}],["meta",{"property":"og:description","content":"本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。 本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。 直方图 直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-05-21T06:17:26.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"通用绘图代码"}],["meta",{"property":"article:modified_time","content":"2023-05-21T06:17:26.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"通用绘图代码\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-05-21T06:17:26.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"直方图","slug":"直方图","link":"#直方图","children":[{"level":3,"title":"导入直方图","slug":"导入直方图","link":"#导入直方图","children":[]},{"level":3,"title":"创建直方图对象","slug":"创建直方图对象","link":"#创建直方图对象","children":[]},{"level":3,"title":"直方图属性设置","slug":"直方图属性设置","link":"#直方图属性设置","children":[]},{"level":3,"title":"直方图高级用法","slug":"直方图高级用法","link":"#直方图高级用法","children":[]},{"level":3,"title":"示例","slug":"示例","link":"#示例","children":[]}]},{"level":2,"title":"子图","slug":"子图","link":"#子图","children":[{"level":3,"title":"导入子图","slug":"导入子图","link":"#导入子图","children":[]},{"level":3,"title":"创建子图对象","slug":"创建子图对象","link":"#创建子图对象","children":[]},{"level":3,"title":"子图属性设置","slug":"子图属性设置","link":"#子图属性设置","children":[]},{"level":3,"title":"子图值读取","slug":"子图值读取","link":"#子图值读取","children":[]},{"level":3,"title":"示例","slug":"示例-1","link":"#示例-1","children":[]}]},{"level":2,"title":"代码","slug":"代码","link":"#代码","children":[{"level":3,"title":"代码文件下载","slug":"代码文件下载","link":"#代码文件下载","children":[]},{"level":3,"title":"直方图代码","slug":"直方图代码","link":"#直方图代码","children":[]},{"level":3,"title":"子图代码","slug":"子图代码","link":"#子图代码","children":[]}]}],"git":{"updatedTime":1684649846000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"notes/plots.md","autoDesc":true}');export{e as data}; diff --git a/assets/plots.html-ODP8nuzQ.js b/assets/plots.html-KiXIG1Oc.js similarity index 97% rename from assets/plots.html-ODP8nuzQ.js rename to assets/plots.html-KiXIG1Oc.js index ce76eaff..9c02f770 100644 --- a/assets/plots.html-ODP8nuzQ.js +++ b/assets/plots.html-KiXIG1Oc.js @@ -1,4 +1,4 @@ -import{_ as o,r as e,o as c,c as l,a as n,b as s,d as p,e as t}from"./app-DaLjD81q.js";const u="/MicroCityNotes/assets/Histogram-hCqM-8K4.png",i="/MicroCityNotes/assets/Subplot_Vertical-X1t_RUlM.png",k={},r=t('

通用绘图代码

本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。

相关信息

本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。

直方图

直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的分布情况。

以下是用我包装的直方图对象绘制的直方图的示例

直方图示例

导入直方图

首先导入直方图的代码。目前有两种选择:

  1. 下载代码文件并导入(推荐)下载直方图代码文件 Histogram.lua,在MicroCityWeb中导入该文件,再引用该文件后即可使用。引用的代码如下:
require("Histogram") --引用直方图
+import{_ as o,a as e}from"./Subplot_Vertical-oXTmfxKU.js";import{_ as c,r as l,o as u,c as i,a as n,b as s,d as p,e as t}from"./app-LOf__QKq.js";const k={},r=t('

通用绘图代码

本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。

相关信息

本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。

直方图

直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的分布情况。

以下是用我包装的直方图对象绘制的直方图的示例

直方图示例

导入直方图

首先导入直方图的代码。目前有两种选择:

  1. 下载代码文件并导入(推荐)下载直方图代码文件 Histogram.lua,在MicroCityWeb中导入该文件,再引用该文件后即可使用。引用的代码如下:
require("Histogram") --引用直方图
 
  1. 复制代码:直接将Histogram.lua文件中的代码复制到你的代码中,代码见下方

创建直方图对象

创建一个直方图对象

local plot = Histogram(list) -- list为数据集
 

还可以在创建对象时对图的属性进行设置。

local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end})
 

属性的设置不是必须的,可以仅根据需要设置。此处就只设置了rangescalefdisp属性。

直方图属性设置

上面提供了直方图属性设置的简单例子。根据代码,还可以设置更多的属性。具体见下表:

属性值作用示例
origin设置图原点(左下角点)origin = {-50, -50},将图的原点设置在(-50,-50)的位置
size设置图横纵轴长度,可以理解为图的大小size = {100, 100},将图的x轴和y轴长度分别设置为100、100
scale设置横纵坐标轴的分度值scale = {3, 2},将图的x轴和y轴分度值分别设置为3和2
axislabel设置横纵轴标题axislabel = {"x", "y"},将图的x轴和y轴标题分别设置为"x"和"y"
range设置横纵坐标轴的显示范围range = {0, 10, 0, 20},将图的x轴范围设置为[0,10],y轴范围设置为[0,20]
filled设置是否填充柱状图filled = false,将柱状图设置为空心。默认样式为填充
fdisp数据标签的显示函数,默认返回数量。设置数据标签显示函数时也会影响y轴刻度的显示。fdisp = function(v) return (v/n*100).."%" end,将数据标签改为按照比例显示(假设n为样本数)

直方图高级用法

动态刷新数据图

  1. 修改图中的数据。此处以向图中添加数据为例。其中假设rnd为添加的数据。也可以直接修改plot.data的值。
table.insert(plot.data, rnd)
@@ -45,7 +45,7 @@ scene.render
     count = count + 1
     scene.render()
 end
-

子图

子图(Subplot)是为了解决同时在界面中放置多个图的图定位和尺寸问题。名称借鉴自MATLAB。

子图

导入子图

首先导入直方图的代码。与直方图一样,导入有两种选择:

  1. 下载代码文件并导入(推荐)下载子图代码文件,在MicroCityWeb中导入Subplot.lua文件,再引用该文件后即可使用。引用的代码如下:
require("Subplot") --引入子图代码
+

子图

子图(Subplot)是为了解决同时在界面中放置多个图的图定位和尺寸问题。名称借鉴自MATLAB。

子图

导入子图

首先导入直方图的代码。与直方图一样,导入有两种选择:

  1. 下载代码文件并导入(推荐)下载子图代码文件,在MicroCityWeb中导入Subplot.lua文件,再引用该文件后即可使用。引用的代码如下:
require("Subplot") --引入子图代码
 
  1. 复制代码:直接将Subplot.lua文件中的代码复制到你的代码中。这样就不需要导入了。代码见下方

创建子图对象

创建子图时必须输入子图的行数和列数。子图的行数和列数决定了子图的数量。

local subplot = Subplot(rows, cols)
 

还可以设置附加属性,对子图的位置和尺寸进行设置。这是一个在创建时设置子图位置和尺寸的例子。

local subplot = Subplot(rows, cols, {span=10, diag={-80, -70, 80, 70}})
 

子图属性设置

此处将对子图的属性进行详细说明。属性的设置不是必须的,可以仅根据需要设置。

`,48),d=n("table",null,[n("thead",null,[n("tr",null,[n("th",{style:{"text-align":"center"}},"属性"),n("th",null,"作用"),n("th",null,"示例")])]),n("tbody",null,[n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"span")]),n("td",null,"设置子图之间的间隔"),n("td",null,[n("code",null,"span=10"),s(",设置子图上下左右之间的间隔为10")])]),n("tr",null,[n("td",{style:{"text-align":"center"}},[n("code",null,"diag")]),n("td",null,"通过输入对角线两个点的坐标设置子图位置和大小"),n("td",null,[n("code",null,"diag = {-80, -70, 80, 70}"),s(",设置子图的对角线范围从坐标 "),n("span",{class:"katex"},[n("span",{class:"katex-mathml"},[n("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[n("semantics",null,[n("mrow",null,[n("mo",{stretchy:"false"},"("),n("mo",null,"−"),n("mn",null,"80"),n("mo",{separator:"true"},","),n("mo",null,"−"),n("mn",null,"70"),n("mo",{stretchy:"false"},")")]),n("annotation",{encoding:"application/x-tex"},"(-80,-70)")])])]),n("span",{class:"katex-html","aria-hidden":"true"},[n("span",{class:"base"},[n("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),n("span",{class:"mopen"},"("),n("span",{class:"mord"},"−"),n("span",{class:"mord"},"80"),n("span",{class:"mpunct"},","),n("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),n("span",{class:"mord"},"−"),n("span",{class:"mord"},"70"),n("span",{class:"mclose"},")")])])]),s(" 到坐标 "),n("span",{class:"katex"},[n("span",{class:"katex-mathml"},[n("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[n("semantics",null,[n("mrow",null,[n("mo",{stretchy:"false"},"("),n("mn",null,"80"),n("mo",{separator:"true"},","),n("mn",null,"70"),n("mo",{stretchy:"false"},")")]),n("annotation",{encoding:"application/x-tex"},"(80,70)")])])]),n("span",{class:"katex-html","aria-hidden":"true"},[n("span",{class:"base"},[n("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),n("span",{class:"mopen"},"("),n("span",{class:"mord"},"80"),n("span",{class:"mpunct"},","),n("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),n("span",{class:"mord"},"70"),n("span",{class:"mclose"},")")])])])])])])],-1),m=t(`

子图值读取

通过属性创建子图后,或者修改子图属性并刷新后,可以对子图的计算值进行读取,获取Subplot中各个子图的原点位置和尺寸。主要通过以下几个属性值进行读取。

此处假设子图对象创建后存放于 subplot 变量中。

计算属性含义示例
originptSubplot对象中各个子图的原点位置通过subplot.originpt[i][j][1]subplot.originpt[i][j][2]能够获取到第ij列的子图对应的原点位置
psizeSubplot对象中各个子图的尺寸通过subplot.psize[1]subplot.psize[2]能够获取到subplot中子图对应的宽度和高度。(假设子图中所有图所需尺寸相同)

示例

这是一个绘制子图范围的示例。假设已经导入了Subplot对象,并将场景设为二维显示。

此处将一个2行3列子图中各个子图的显示范围绘制为一个矩形。其中子图范围用四个灰色点表示,子图位置用蓝色矩形表示。

require("Subplot") --引入子图代码
@@ -312,4 +312,4 @@ scene.render
     subplot:refresh()
     return subplot
 end
-
`,6);function x(q,j){const a=e("ExternalLinkIcon");return c(),l("div",null,[r,d,m,n("p",null,[s("代码文件列表见 "),n("a",b,[s("ModelResource/libs"),p(a)])]),n("table",null,[v,n("tbody",null,[n("tr",null,[g,n("td",null,[n("a",h,[s("ModelResource/libs/Histogram.lua"),p(a)])])]),n("tr",null,[y,n("td",null,[n("a",f,[s("ModelResource/libs/Subplot.lua"),p(a)])])])])]),w])}const _=o(k,[["render",x],["__file","plots.html.vue"]]);export{_ as default}; +
`,6);function x(q,j){const a=l("ExternalLinkIcon");return u(),i("div",null,[r,d,m,n("p",null,[s("代码文件列表见 "),n("a",b,[s("ModelResource/libs"),p(a)])]),n("table",null,[v,n("tbody",null,[n("tr",null,[g,n("td",null,[n("a",h,[s("ModelResource/libs/Histogram.lua"),p(a)])])]),n("tr",null,[y,n("td",null,[n("a",f,[s("ModelResource/libs/Subplot.lua"),p(a)])])])])]),w])}const B=c(k,[["render",x],["__file","plots.html.vue"]]);export{B as default}; diff --git a/assets/plots.html-wJZ2mJax.js b/assets/plots.html-wJZ2mJax.js new file mode 100644 index 00000000..e44d1f75 --- /dev/null +++ b/assets/plots.html-wJZ2mJax.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-f610fd24","path":"/notes/plots.html","title":"通用绘图代码","lang":"zh-CN","frontmatter":{"description":"本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。 本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。 直方图 直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/plots.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/plots.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"通用绘图代码"}],["meta",{"property":"og:description","content":"本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。 本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。 直方图 直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"通用绘图代码\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"直方图","slug":"直方图","link":"#直方图","children":[{"level":3,"title":"导入直方图","slug":"导入直方图","link":"#导入直方图","children":[]},{"level":3,"title":"创建直方图对象","slug":"创建直方图对象","link":"#创建直方图对象","children":[]},{"level":3,"title":"直方图属性设置","slug":"直方图属性设置","link":"#直方图属性设置","children":[]},{"level":3,"title":"直方图高级用法","slug":"直方图高级用法","link":"#直方图高级用法","children":[]},{"level":3,"title":"示例","slug":"示例","link":"#示例","children":[]}]},{"level":2,"title":"子图","slug":"子图","link":"#子图","children":[{"level":3,"title":"导入子图","slug":"导入子图","link":"#导入子图","children":[]},{"level":3,"title":"创建子图对象","slug":"创建子图对象","link":"#创建子图对象","children":[]},{"level":3,"title":"子图属性设置","slug":"子图属性设置","link":"#子图属性设置","children":[]},{"level":3,"title":"子图值读取","slug":"子图值读取","link":"#子图值读取","children":[]},{"level":3,"title":"示例","slug":"示例-1","link":"#示例-1","children":[]}]},{"level":2,"title":"代码","slug":"代码","link":"#代码","children":[{"level":3,"title":"代码文件下载","slug":"代码文件下载","link":"#代码文件下载","children":[]},{"level":3,"title":"直方图代码","slug":"直方图代码","link":"#直方图代码","children":[]},{"level":3,"title":"子图代码","slug":"子图代码","link":"#子图代码","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"notes/plots.md","autoDesc":true}');export{e as data}; diff --git a/assets/query_results-qHjDevxa.js b/assets/query_results-qHjDevxa.js new file mode 100644 index 00000000..ff8e713a --- /dev/null +++ b/assets/query_results-qHjDevxa.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/gis_data_structure-OyzSP1K_.png",t="/MicroCityNotes/assets/query_results-8DtTlPIZ.png";export{s as _,t as a}; diff --git a/assets/scene_coordinate-_YCPy6or.js b/assets/scene_coordinate-_YCPy6or.js new file mode 100644 index 00000000..b2b675fd --- /dev/null +++ b/assets/scene_coordinate-_YCPy6or.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/new_scene-8_vgmKnR.png",t="/MicroCityNotes/assets/scene_menu-RSZKJk7N.png",o="/MicroCityNotes/assets/object_menu-rLYhy67y.png",e="/MicroCityNotes/assets/scene_coordinate-muj-oFBk.png";export{s as _,t as a,o as b,e as c}; diff --git a/assets/script_editor-a48-sxc_.js b/assets/script_editor-a48-sxc_.js new file mode 100644 index 00000000..0bffb050 --- /dev/null +++ b/assets/script_editor-a48-sxc_.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/script_editor-51w4xjN9.png";export{s as _}; diff --git a/assets/shot_parameter_id-roH75mzn.js b/assets/shot_parameter_id-roH75mzn.js new file mode 100644 index 00000000..18c5b736 --- /dev/null +++ b/assets/shot_parameter_id-roH75mzn.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/shot_parameter_id-ljNzzofT.png";export{s as _}; diff --git a/assets/shot_script_editor-VtQOeIXC.js b/assets/shot_script_editor-VtQOeIXC.js new file mode 100644 index 00000000..72ef95b1 --- /dev/null +++ b/assets/shot_script_editor-VtQOeIXC.js @@ -0,0 +1 @@ +const s="/MicroCityNotes/assets/city_logistics-8RxmuTB1.png",t="/MicroCityNotes/assets/shipping_planning-_Mkxb6xn.png",i="/MicroCityNotes/assets/warehouse_simulation-CPwzj5dU.gif",o="/MicroCityNotes/assets/terminal_simulation-rx4w_Kp0.gif",_="/MicroCityNotes/assets/modules-cY5Kwc-8.png",e="/MicroCityNotes/assets/shot_script_editor-_OW8Kkrd.png";export{s as _,t as a,i as b,o as c,_ as d,e}; diff --git a/assets/timelapse.html-mpQRHhbv.js b/assets/timelapse.html-VDhH9cuD.js similarity index 74% rename from assets/timelapse.html-mpQRHhbv.js rename to assets/timelapse.html-VDhH9cuD.js index d4d53a0e..282c8328 100644 --- a/assets/timelapse.html-mpQRHhbv.js +++ b/assets/timelapse.html-VDhH9cuD.js @@ -1,4 +1,4 @@ -import{_ as l,r as o,o as i,c as r,d as s,a as p,b as n,w as e,e as t}from"./app-DaLjD81q.js";const d="/MicroCityNotes/assets/fixed_increment_advance-ufFIwQjw.png",u={},k=t('

时间推进法

仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。

时间推进法的分类

常见的仿真时间推进方法有三大类:

  • 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。
  • 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。
  • 主导时钟推进法:主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。

实例

事件调度法

事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。在仿真过程中,仿真系统会根据当前仿真时间和各个事件发生的时间来确定下一个要发生的事件,并将仿真时间推进到该事件发生的时间。

事件调度法主要分为以下3个主要步骤,这3个步骤也是控制事件调度法的主控程序的主要步骤:

  • 时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻
  • 事件辨识:正确地辨识当前要发生的事件
  • 事件执行:正确地执行当前发生的事件

事件调度法基本原理流程图如下:

',11),m=t('

固定增量推进法

固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。在每个步长内,若无事件发生,则仿真钟再推进一个单位时间T;若在该步内有若干个事件发生,则认为这些事件均发生在该步的结束时刻。

固定增量推进法

例题

代码流程示例

while scene.render() do
+import{_ as l}from"./fixed_increment_advance-iwDvqivb.js";import{_ as i,r as o,o as r,c as d,d as s,a as p,b as n,w as e,e as t}from"./app-LOf__QKq.js";const u={},k=t('

时间推进法

仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。

时间推进法的分类

常见的仿真时间推进方法有三大类:

  • 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。
  • 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。
  • 主导时钟推进法:主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。

实例

事件调度法

事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。在仿真过程中,仿真系统会根据当前仿真时间和各个事件发生的时间来确定下一个要发生的事件,并将仿真时间推进到该事件发生的时间。

事件调度法主要分为以下3个主要步骤,这3个步骤也是控制事件调度法的主控程序的主要步骤:

  • 时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻
  • 事件辨识:正确地辨识当前要发生的事件
  • 事件执行:正确地执行当前发生的事件

事件调度法基本原理流程图如下:

',11),m=t('

固定增量推进法

固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。在每个步长内,若无事件发生,则仿真钟再推进一个单位时间T;若在该步内有若干个事件发生,则认为这些事件均发生在该步的结束时刻。

固定增量推进法

例题

代码流程示例

while scene.render() do
     t = t + dt
     if t % cycle ~= work_time then
         d = d + v * dt
@@ -34,4 +34,4 @@ import{_ as l,r as o,o as i,c as r,d as s,a as p,b as n,w as e,e as t}from"./app
 	
     t0 = os.clock() -- 记录仿真时间
 end
-

相关说明

  • 当仿真速度 simspeed 为1时,表示仿真时钟与真实世界时钟的速度相同。simspeed 可以视作加速倍率。
  • dt 表示两次记录时间之间的时间差,仿真中的时间步进根据 dt*simspeed 计算得到。

    相关信息

    需要注意的是,时间增量 dt 的数值在每个循环周期一般都不相同,dt 的具体大小一般取决于电脑的运算能力

    提示

    有时两次记录时间之间没有太多耗时的操作,计算得到的 dt 可能为0。一般两次时间记录之间存在一个 scene.render(),这样一般能够保证两次采样的时间之间能够计算得到一个不为0的时间差值。

`,10);function h(b,y){const c=o("FlowChart"),a=o("RouterLink");return i(),r("div",null,[k,s(c,{id:"flowchart-61",code:"eJzLzMsssbUrLkksKrFSeNox9+ny7qc907iKkxPzbO3yC1KLEksy8/OsFJ7s6n6ye9uzztXP+vu5UitSk7HKLn+xsIcrszjV1i45Py8lEyL5tGPJs2lrn81Y/3TCsue7Jz+bO58LqCA1LwWob/f+53PmQwW5QG7RtQNZrWsHskLXDmgUyDiNvHxNiASYV5laDOSmcgEApctWxQ==",preset:"vue"}),p("p",null,[n("事件调度法在MicroCityWeb中的具体实现参见 "),s(a,{to:"/notes/event-scheduling.html"},{default:e(()=>[n("离散事件模拟和程序控制 - 协程")]),_:1})]),m,p("p",null,[s(a,{to:"/notes/warehouse-simulation.html"},{default:e(()=>[n("自动化仓库仿真思路")]),_:1}),n("的最后一部分提到了"),s(a,{to:"/notes/warehouse-simulation.html#%E6%94%B9%E8%BF%9B%E7%A9%BA%E9%97%B4"},{default:e(()=>[n("改进空间")]),_:1}),n(",最终实现了同步主导时钟的主导时钟推进法。")]),v])}const w=l(u,[["render",h],["__file","timelapse.html.vue"]]);export{w as default}; +

相关说明

  • 当仿真速度 simspeed 为1时,表示仿真时钟与真实世界时钟的速度相同。simspeed 可以视作加速倍率。
  • dt 表示两次记录时间之间的时间差,仿真中的时间步进根据 dt*simspeed 计算得到。

    相关信息

    需要注意的是,时间增量 dt 的数值在每个循环周期一般都不相同,dt 的具体大小一般取决于电脑的运算能力

    提示

    有时两次记录时间之间没有太多耗时的操作,计算得到的 dt 可能为0。一般两次时间记录之间存在一个 scene.render(),这样一般能够保证两次采样的时间之间能够计算得到一个不为0的时间差值。

`,10);function h(b,y){const c=o("FlowChart"),a=o("RouterLink");return r(),d("div",null,[k,s(c,{id:"flowchart-61",code:"eJzLzMsssbUrLkksKrFSeNox9+ny7qc907iKkxPzbO3yC1KLEksy8/OsFJ7s6n6ye9uzztXP+vu5UitSk7HKLn+xsIcrszjV1i45Py8lEyL5tGPJs2lrn81Y/3TCsue7Jz+bO58LqCA1LwWob/f+53PmQwW5QG7RtQNZrWsHskLXDmgUyDiNvHxNiASYV5laDOSmcgEApctWxQ==",preset:"vue"}),p("p",null,[n("事件调度法在MicroCityWeb中的具体实现参见 "),s(a,{to:"/notes/event-scheduling.html"},{default:e(()=>[n("离散事件模拟和程序控制 - 协程")]),_:1})]),m,p("p",null,[s(a,{to:"/notes/warehouse-simulation.html"},{default:e(()=>[n("自动化仓库仿真思路")]),_:1}),n("的最后一部分提到了"),s(a,{to:"/notes/warehouse-simulation.html#%E6%94%B9%E8%BF%9B%E7%A9%BA%E9%97%B4"},{default:e(()=>[n("改进空间")]),_:1}),n(",最终实现了同步主导时钟的主导时钟推进法。")]),v])}const x=i(u,[["render",h],["__file","timelapse.html.vue"]]);export{x as default}; diff --git a/assets/timelapse.html-ghI-6cF8.js b/assets/timelapse.html-ghI-6cF8.js new file mode 100644 index 00000000..6ea2f403 --- /dev/null +++ b/assets/timelapse.html-ghI-6cF8.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-51a5edf4","path":"/en/notes/timelapse.html","title":"Time Advancement Methods","lang":"en-US","frontmatter":{"description":"The time advancement method in simulation refers to how the simulation time is progressed during the simulation process. Classification of Time Advancement Methods There are thr...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/timelapse.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/timelapse.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Time Advancement Methods"}],["meta",{"property":"og:description","content":"The time advancement method in simulation refers to how the simulation time is progressed during the simulation process. Classification of Time Advancement Methods There are thr..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Time Advancement Methods\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Classification of Time Advancement Methods","slug":"classification-of-time-advancement-methods","link":"#classification-of-time-advancement-methods","children":[]},{"level":2,"title":"Example","slug":"example","link":"#example","children":[{"level":3,"title":"Event Scheduling Method","slug":"event-scheduling-method","link":"#event-scheduling-method","children":[]},{"level":3,"title":"Fixed Increment Advancement Method","slug":"fixed-increment-advancement-method","link":"#fixed-increment-advancement-method","children":[]},{"level":3,"title":"Master Clock Advancement Method","slug":"master-clock-advancement-method","link":"#master-clock-advancement-method","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/timelapse.md","autoDesc":true}');export{e as data}; diff --git a/assets/timelapse.html-hdyuE7Lk.js b/assets/timelapse.html-hdyuE7Lk.js deleted file mode 100644 index eda90ff5..00000000 --- a/assets/timelapse.html-hdyuE7Lk.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-19652be0","path":"/notes/timelapse.html","title":"时间推进法","lang":"zh-CN","frontmatter":{"description":"仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。 时间推进法的分类 常见的仿真时间推进方法有三大类: 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。; 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/timelapse.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"时间推进法"}],["meta",{"property":"og:description","content":"仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。 时间推进法的分类 常见的仿真时间推进方法有三大类: 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。; 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-06-01T08:12:10.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"时间推进法"}],["meta",{"property":"article:modified_time","content":"2023-06-01T08:12:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"时间推进法\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-06-01T08:12:10.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"时间推进法的分类","slug":"时间推进法的分类","link":"#时间推进法的分类","children":[]},{"level":2,"title":"实例","slug":"实例","link":"#实例","children":[{"level":3,"title":"事件调度法","slug":"事件调度法","link":"#事件调度法","children":[]},{"level":3,"title":"固定增量推进法","slug":"固定增量推进法","link":"#固定增量推进法","children":[]},{"level":3,"title":"主导时钟推进法","slug":"主导时钟推进法","link":"#主导时钟推进法","children":[]}]}],"git":{"updatedTime":1685607130000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":6}]},"filePathRelative":"notes/timelapse.md","autoDesc":true}');export{t as data}; diff --git a/assets/timelapse.html-rfk9Tyut.js b/assets/timelapse.html-rfk9Tyut.js new file mode 100644 index 00000000..d9c69772 --- /dev/null +++ b/assets/timelapse.html-rfk9Tyut.js @@ -0,0 +1,37 @@ +import{_ as r}from"./fixed_increment_advance-iwDvqivb.js";import{_ as p,r as a,o as d,c as m,d as s,a as n,b as e,w as o,e as i}from"./app-LOf__QKq.js";const u={},h=i('

Time Advancement Methods

The time advancement method in simulation refers to how the simulation time is progressed during the simulation process.

Classification of Time Advancement Methods

There are three major categories of common simulation time advancement methods:

  • Event scheduling method: Event scheduling method is an event-based simulation method that sorts events in the simulation system and simulates them based on the order of their occurrence.
  • Fixed increment advancement method: The fixed increment advancement method refers to fixing a time increment during the simulation process. After setting the starting time, the simulation time is advanced based on the time increment.
  • Master clock advancement method: The master clock advancement method refers to controlling the entire simulation system during the simulation process using a master clock. It controls the simulation process by controlling the clock.

Example

Event Scheduling Method

The event scheduling method is an event-based simulation method that sorts events in the simulation system and simulates them based on the order of their occurrence. During the simulation process, the simulation system determines the next event to occur based on the current simulation time and the time of each event, and advances the simulation time to the time when the event occurs.

The event scheduling method consists of the following three main steps, which are also the main steps of the control program for the event scheduling method:

  • Time scanning: Determine the time when the next event will occur and advance the simulation clock to that moment.
  • Event identification: Correctly identify the event that is about to occur.
  • Event execution: Correctly execute the event that has occurred.

The basic principle flowchart of the event scheduling method is as follows:

',11),k=i('

Fixed Increment Advancement Method

The fixed increment advancement method refers to fixing a time increment during the simulation process and advancing the time simulation based on the increment from the starting time. Within each time step, if no event occurs, the simulation clock is advanced by one unit of time T; if there are multiple events within the step, these events are considered to occur at the end of the step.

Fixed Increment Advancement Method

Example

Code Flow Example

while scene.render() do
+    t = t + dt
+    if t % cycle ~= work_time then
+        d = d + v * dt
+        print("Time after departure:", t, "hours")
+    else
+        print("Time after departure:", t, "hours, resting")
+    end
+
+    car:setpos(CastToLine(d)) -- Linear trajectory
+
+    os.sleep(200)
+end
+

This is the main flow of the code and cannot be used directly.

Master Clock Advancement Method

The master clock advancement method refers to controlling the entire simulation system during the simulation process using a master clock. It controls the simulation process by controlling the clock. The master clock advancement method can be divided into two types: synchronous master clock and asynchronous master clock. Synchronous master clock means that all modules use the same master clock for advancement, while asynchronous master clock means that different modules use different master clocks for advancement.

`,8),v=i(`

The implementation is done but the code is not included.

Changes from the Automated Warehouse Simulation to the Master Clock Advancement Method

Specifically, the following changes were made based on the original approach:

  • Most of the os.sleep() related to the event scheduling method were deleted. Due to the simplicity of the simulation process, the event scheduling method related to loading and unloading operations is retained to optimize resource utilization.
  • Set a global simulation clock and change the idea of the Agv:Move() function from "executing tasks and refreshing the scene at a fixed step size" to "monitoring changes in the simulation clock duration, executing tasks based on the duration changes, and refreshing the scene".
  • Added simulation speed adjustment.

From the above changes, it can be seen that the core of the simulation has shifted from event tasks to the simulation clock. In this, the part of scene refreshing is implemented using os.clock().

Example of Master Clock Advancement Method

Below is a simple example of the dominant clock driving method and the os.clock() function, modified from the built-in block rotation example in MicroCityWeb.

local obj = scene.addobj('box')
+
+-- Initial position
+local x = 1
+local y = 1
+local z = 0
+
+local rx, ry = 0.1, 0.1 -- Rotation speed in the x and y directions
+local simspeed = 10 -- Simulation speed
+
+local t = 0 -- Global simulation clock
+local t0 = os.clock() -- Record the start time of the simulation
+while scene.render() do
+    local dt = os.clock() - t0 -- Calculate the time difference since the last recorded time
+    t = t + dt -- Move the simulation clock forward by the corresponding time difference
+    
+    -- Set the current rotation position of the block
+	x = x + rx * dt * simspeed 
+	y = y + ry * dt * simspeed 
+	obj:setrot(x, y, z)
+	
+    t0 = os.clock() -- Record the simulation time
+end
+

Explanation:

  • When the simulation speed simspeed is 1, it means that the simulation clock is moving at the same speed as the real-world clock. simspeed can be considered as an acceleration factor.
  • dt represents the time difference between two recorded times, and the time step in the simulation is calculated as dt * simspeed.

    Info

    It should be noted that the value of the time increment dt is generally not the same in each loop cycle, and the specific value of dt generally depends on the computational power of the computer.

    Tips

    Sometimes there is not much time-consuming operation between two recorded times, and the calculated dt may be 0. Generally, there is a scene.render() between two time recordings, which usually ensures a non-zero time difference between the two samples.

`,10),f={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},b=n("strong",null,"feedback",-1);function g(w,y){const c=a("FlowChart"),t=a("RouterLink"),l=a("ExternalLinkIcon");return d(),m("div",null,[h,s(c,{id:"flowchart-61",code:"eJxVjjEOwjAMRfecwiMMvUCkeEEZmMsFotRQi9ZBjYuA0+OEicn6/9vPn4U1YNW0qYezCU4Lf5JyEVdzkoDlQVvXHi68EozmCsvN0YvyXxyfJArR7L3fc6WAuchk1JafZsp34CuwAlfQmYBkcrZkw8PI6750FESzXas2YCsxYPs1oAEb9CDl+Au6elM1Se4LQWVHAA==",preset:"vue"}),n("p",null,[e("For the specific implementation of the event scheduling method in MicroCityWeb, please refer to "),s(t,{to:"/en/notes/event-scheduling.html"},{default:o(()=>[e("Discrete Event Simulation and Program Control - Coroutine")]),_:1}),e(".")]),k,n("p",null,[e("The last part of the "),s(t,{to:"/en/notes/warehouse-simulation.html"},{default:o(()=>[e("Automated Warehouse Simulation Approach")]),_:1}),e(" mentions the "),s(t,{to:"/en/notes/warehouse-simulation.html#improvement-space"},{default:o(()=>[e("improvement space")]),_:1}),e(" and ultimately implements the master clock advancement method with synchronous master clock.")]),v,n("blockquote",null,[n("p",null,[e("This post is translated using ChatGPT, please "),n("a",f,[b,s(l)]),e(" if any omissions.")])])])}const C=p(u,[["render",g],["__file","timelapse.html.vue"]]);export{C as default}; diff --git a/assets/timelapse.html-xp-pHQoZ.js b/assets/timelapse.html-xp-pHQoZ.js new file mode 100644 index 00000000..34933506 --- /dev/null +++ b/assets/timelapse.html-xp-pHQoZ.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-19652be0","path":"/notes/timelapse.html","title":"时间推进法","lang":"zh-CN","frontmatter":{"description":"仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。 时间推进法的分类 常见的仿真时间推进方法有三大类: 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。; 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/timelapse.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/timelapse.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"时间推进法"}],["meta",{"property":"og:description","content":"仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。 时间推进法的分类 常见的仿真时间推进方法有三大类: 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。; 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"时间推进法\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"时间推进法的分类","slug":"时间推进法的分类","link":"#时间推进法的分类","children":[]},{"level":2,"title":"实例","slug":"实例","link":"#实例","children":[{"level":3,"title":"事件调度法","slug":"事件调度法","link":"#事件调度法","children":[]},{"level":3,"title":"固定增量推进法","slug":"固定增量推进法","link":"#固定增量推进法","children":[]},{"level":3,"title":"主导时钟推进法","slug":"主导时钟推进法","link":"#主导时钟推进法","children":[]}]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":7}]},"filePathRelative":"notes/timelapse.md","autoDesc":true}');export{e as data}; diff --git a/assets/tools.html-kWg64VtA.js b/assets/tools.html-LamHaYH8.js similarity index 93% rename from assets/tools.html-kWg64VtA.js rename to assets/tools.html-LamHaYH8.js index d2c5103f..1b32b12f 100644 --- a/assets/tools.html-kWg64VtA.js +++ b/assets/tools.html-LamHaYH8.js @@ -1 +1 @@ -import{_ as r,r as s,o as a,c as l,a as e,b as o,d as n}from"./app-DaLjD81q.js";const c={},_=e("h1",{id:"有关工具",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#有关工具","aria-hidden":"true"},"#"),o(" 有关工具")],-1),h=e("p",null,"可能能够用到的工具",-1),d={href:"https://mapshaper.org/",target:"_blank",rel:"noopener noreferrer"},i=e("code",null,".geojson",-1),p=e("code",null,".shp",-1),u={href:"https://threejs.org/editor/",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"🔨 持续更新...",-1);function m(x,k){const t=s("ExternalLinkIcon");return a(),l("div",null,[_,h,e("ul",null,[e("li",null,[e("a",d,[o("MapShaper"),n(t)]),o(" 地图编辑器。可以编辑"),i,o("文件并导出为"),p,o("文件")]),e("li",null,[e("a",u,[o("Three.js Editor"),n(t)]),o(" Three.js的在线3D对象编辑器。")])]),f])}const b=r(c,[["render",m],["__file","tools.html.vue"]]);export{b as default}; +import{_ as r,r as s,o as a,c as l,a as e,b as o,d as n}from"./app-LOf__QKq.js";const c={},_=e("h1",{id:"有关工具",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#有关工具","aria-hidden":"true"},"#"),o(" 有关工具")],-1),h=e("p",null,"可能能够用到的工具",-1),d={href:"https://mapshaper.org/",target:"_blank",rel:"noopener noreferrer"},i=e("code",null,".geojson",-1),p=e("code",null,".shp",-1),u={href:"https://threejs.org/editor/",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"🔨 持续更新...",-1);function m(x,k){const t=s("ExternalLinkIcon");return a(),l("div",null,[_,h,e("ul",null,[e("li",null,[e("a",d,[o("MapShaper"),n(t)]),o(" 地图编辑器。可以编辑"),i,o("文件并导出为"),p,o("文件")]),e("li",null,[e("a",u,[o("Three.js Editor"),n(t)]),o(" Three.js的在线3D对象编辑器。")])]),f])}const b=r(c,[["render",m],["__file","tools.html.vue"]]);export{b as default}; diff --git a/assets/tools.html-PgdIJCR5.js b/assets/tools.html-PgdIJCR5.js new file mode 100644 index 00000000..f4a4cc2d --- /dev/null +++ b/assets/tools.html-PgdIJCR5.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-7994b60e","path":"/en/notes/tools.html","title":"Tools","lang":"en-US","frontmatter":{"description":"Possible tools that may come in handy: MapShaper (https://mapshaper.org/) - a map editor tool. It allows you to edit .geojson files and export them as .shp files.; Three.js Edit...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/tools.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/tools.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Tools"}],["meta",{"property":"og:description","content":"Possible tools that may come in handy: MapShaper (https://mapshaper.org/) - a map editor tool. It allows you to edit .geojson files and export them as .shp files.; Three.js Edit..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Tools\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/tools.md","autoDesc":true}');export{t as data}; diff --git a/assets/tools.html-Tsv49Nwb.js b/assets/tools.html-Tsv49Nwb.js new file mode 100644 index 00000000..651a3f34 --- /dev/null +++ b/assets/tools.html-Tsv49Nwb.js @@ -0,0 +1 @@ +import{_ as n,r,o as l,c as a,a as e,b as o,d as s}from"./app-LOf__QKq.js";const i={},c=e("h1",{id:"tools",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#tools","aria-hidden":"true"},"#"),o(" Tools")],-1),h=e("p",null,"Possible tools that may come in handy:",-1),_={href:"https://mapshaper.org/",target:"_blank",rel:"noopener noreferrer"},d=e("code",null,".geojson",-1),p=e("code",null,".shp",-1),u={href:"https://threejs.org/editor/",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"🔨 Work In Progress...",-1),m={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},g=e("strong",null,"feedback",-1);function b(k,x){const t=r("ExternalLinkIcon");return l(),a("div",null,[c,h,e("ul",null,[e("li",null,[e("a",_,[o("MapShaper"),s(t)]),o(" - a map editor tool. It allows you to edit "),d,o(" files and export them as "),p,o(" files.")]),e("li",null,[e("a",u,[o("Three.js Editor"),s(t)]),o(" - an online 3D object editor for Three.js.")])]),f,e("blockquote",null,[e("p",null,[o("This post is translated using ChatGPT, please "),e("a",m,[g,s(t)]),o(" if any omissions.")])])])}const T=n(i,[["render",b],["__file","tools.html.vue"]]);export{T as default}; diff --git a/assets/tools.html-hzuhyAmn.js b/assets/tools.html-hzuhyAmn.js new file mode 100644 index 00000000..d6f4dff2 --- /dev/null +++ b/assets/tools.html-hzuhyAmn.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-6bb8b8e5","path":"/notes/tools.html","title":"有关工具","lang":"zh-CN","frontmatter":{"description":"可能能够用到的工具 MapShaper (https://mapshaper.org/) 地图编辑器。可以编辑.geojson文件并导出为.shp文件; Three.js Editor (https://threejs.org/editor/) Three.js的在线3D对象编辑器。; 🔨 持续更新...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/tools.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/tools.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"有关工具"}],["meta",{"property":"og:description","content":"可能能够用到的工具 MapShaper (https://mapshaper.org/) 地图编辑器。可以编辑.geojson文件并导出为.shp文件; Three.js Editor (https://threejs.org/editor/) Three.js的在线3D对象编辑器。; 🔨 持续更新..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-20T14:40:11.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T14:40:11.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"有关工具\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T14:40:11.000Z\\",\\"author\\":[]}"]]},"headers":[],"git":{"updatedTime":1700491211000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/tools.md","autoDesc":true}');export{t as data}; diff --git a/assets/tools.html-zf97O5Kc.js b/assets/tools.html-zf97O5Kc.js deleted file mode 100644 index 42c5d585..00000000 --- a/assets/tools.html-zf97O5Kc.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-6bb8b8e5","path":"/notes/tools.html","title":"有关工具","lang":"zh-CN","frontmatter":{"description":"可能能够用到的工具 MapShaper (https://mapshaper.org/) 地图编辑器。可以编辑.geojson文件并导出为.shp文件; Three.js Editor (https://threejs.org/editor/) Three.js的在线3D对象编辑器。; 🔨 持续更新...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/tools.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"有关工具"}],["meta",{"property":"og:description","content":"可能能够用到的工具 MapShaper (https://mapshaper.org/) 地图编辑器。可以编辑.geojson文件并导出为.shp文件; Three.js Editor (https://threejs.org/editor/) Three.js的在线3D对象编辑器。; 🔨 持续更新..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-20T14:40:11.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T14:40:11.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"有关工具\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T14:40:11.000Z\\",\\"author\\":[]}"]]},"headers":[],"git":{"updatedTime":1700491211000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/tools.md","autoDesc":true}');export{t as data}; diff --git a/assets/two_way-xpspXH9g.js b/assets/two_way-xpspXH9g.js new file mode 100644 index 00000000..3fb7d88f --- /dev/null +++ b/assets/two_way-xpspXH9g.js @@ -0,0 +1 @@ +const N="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQwMCIgaGVpZ2h0PSIyOTMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjcxNCIgeT0iNjMyIiB3aWR0aD0iMjQwMCIgaGVpZ2h0PSIyOTMiLz48L2NsaXBQYXRoPjwvZGVmcz48ZyBjbGlwLXBhdGg9InVybCgjY2xpcDApIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzE0IC02MzIpIj48cGF0aCBkPSJNMTU3Ni41IDY5Ny41QzE1NzYuNSA2NjguNzgxIDE1OTkuNzggNjQ1LjUgMTYyOC41IDY0NS41IDE2NTcuMjIgNjQ1LjUgMTY4MC41IDY2OC43ODEgMTY4MC41IDY5Ny41IDE2ODAuNSA3MjYuMjE5IDE2NTcuMjIgNzQ5LjUgMTYyOC41IDc0OS41IDE1OTkuNzggNzQ5LjUgMTU3Ni41IDcyNi4yMTkgMTU3Ni41IDY5Ny41WiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjQuNTgzMzMiIHN0cm9rZS1taXRlcmxpbWl0PSI4IiBmaWxsPSIjRkZGRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48dGV4dCBmb250LWZhbWlseT0iQ29uc29sYXMsQ29uc29sYXNfTVNGb250U2VydmljZSxzYW5zLXNlcmlmIiBmb250LXdlaWdodD0iNDAwIiBmb250LXNpemU9IjY0IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIDE2MTAuNTIgNzIwKSI+MjwvdGV4dD48cGF0aCBkPSJNODIzIDY5NyAxNTc2LjYzIDY5NyIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHBhdGggZD0iTTg0OC43OCA2OTEuODQ0IDE1NTAuODUgNjkxLjg0NCAxNTUwLjg1IDcwMi4xNTcgODQ4Ljc4IDcwMi4xNTZaTTg1My45MzcgNzEyLjQ2OSA4MjMgNjk3IDg1My45MzcgNjgxLjUzMVpNMTU0NS42OSA2ODEuNTMyIDE1NzYuNjMgNjk3IDE1NDUuNjkgNzEyLjQ2OVoiIGZpbGw9IiNBNUE1QTUiLz48cGF0aCBkPSJNNzE5LjUgNjk3LjVDNzE5LjUgNjY4Ljc4MSA3NDIuNzgxIDY0NS41IDc3MS41IDY0NS41IDgwMC4yMTkgNjQ1LjUgODIzLjUgNjY4Ljc4MSA4MjMuNSA2OTcuNSA4MjMuNSA3MjYuMjE5IDgwMC4yMTkgNzQ5LjUgNzcxLjUgNzQ5LjUgNzQyLjc4MSA3NDkuNSA3MTkuNSA3MjYuMjE5IDcxOS41IDY5Ny41WiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjQuNTgzMzMiIHN0cm9rZS1taXRlcmxpbWl0PSI4IiBmaWxsPSIjRkZGRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48dGV4dCBmb250LWZhbWlseT0iQ29uc29sYXMsQ29uc29sYXNfTVNGb250U2VydmljZSxzYW5zLXNlcmlmIiBmb250LXdlaWdodD0iNDAwIiBmb250LXNpemU9IjY0IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIDc1Mi45NDcgNzIwKSI+MTwvdGV4dD48dGV4dCBmb250LWZhbWlseT0iU2ltSGVpLFNpbUhlaV9NU0ZvbnRTZXJ2aWNlLHNhbnMtc2VyaWYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZvbnQtc2l6ZT0iNjQiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIDEgMTA3MS4xNiA4NzUpIj7mraPluLjnkIbop6M8L3RleHQ+PHBhdGggZD0iTTMwMDYuNSA2OTcuNUMzMDA2LjUgNjY4Ljc4MSAzMDI5Ljc4IDY0NS41IDMwNTguNSA2NDUuNSAzMDg3LjIyIDY0NS41IDMxMTAuNSA2NjguNzgxIDMxMTAuNSA2OTcuNSAzMTEwLjUgNzI2LjIxOSAzMDg3LjIyIDc0OS41IDMwNTguNSA3NDkuNSAzMDI5Ljc4IDc0OS41IDMwMDYuNSA3MjYuMjE5IDMwMDYuNSA2OTcuNVoiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0LjU4MzMzIiBzdHJva2UtbWl0ZXJsaW1pdD0iOCIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHRleHQgZm9udC1mYW1pbHk9IkNvbnNvbGFzLENvbnNvbGFzX01TRm9udFNlcnZpY2Usc2Fucy1zZXJpZiIgZm9udC13ZWlnaHQ9IjQwMCIgZm9udC1zaXplPSI2NCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgMSAzMDM5LjgxIDcyMCkiPjI8L3RleHQ+PHBhdGggZD0iTTIxNDguNSA2OTcuNUMyMTQ4LjUgNjY4Ljc4MSAyMTcxLjc4IDY0NS41IDIyMDAuNSA2NDUuNSAyMjI5LjIyIDY0NS41IDIyNTIuNSA2NjguNzgxIDIyNTIuNSA2OTcuNSAyMjUyLjUgNzI2LjIxOSAyMjI5LjIyIDc0OS41IDIyMDAuNSA3NDkuNSAyMTcxLjc4IDc0OS41IDIxNDguNSA3MjYuMjE5IDIxNDguNSA2OTcuNVoiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0LjU4MzMzIiBzdHJva2UtbWl0ZXJsaW1pdD0iOCIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHRleHQgZm9udC1mYW1pbHk9IkNvbnNvbGFzLENvbnNvbGFzX01TRm9udFNlcnZpY2Usc2Fucy1zZXJpZiIgZm9udC13ZWlnaHQ9IjQwMCIgZm9udC1zaXplPSI2NCIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgMSAyMTgyLjI0IDcyMCkiPjE8L3RleHQ+PHBhdGggZD0iTTIyMzcuNSA2NTcuMDYyIDI5OTguNjYgNjU3LjA2MyAyOTk4LjY2IDY2My45MzggMjIzNy41IDY2My45MzdaTTI5OTQuMDcgNjQ2Ljc1IDMwMjEuNTcgNjYwLjUgMjk5NC4wNyA2NzQuMjVaIiBmaWxsPSIjQTVBNUE1Ii8+PHBhdGggZD0iTTEuNTgyMjFlLTA2LTMuNDM3NSA3NjEuMTU2LTMuNDM3MTUgNzYxLjE1NiAzLjQzNzg1LTEuNTgyMjFlLTA2IDMuNDM3NVpNNzU2LjU3My0xMy43NDk3IDc4NC4wNzMgMC4wMDAzNjA4OTIgNzU2LjU3MyAxMy43NTAzWiIgZmlsbD0iI0E1QTVBNSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMzAyMS41NyA3MzQuNSkiLz48dGV4dCBmb250LWZhbWlseT0iU2ltSGVpLFNpbUhlaV9NU0ZvbnRTZXJ2aWNlLHNhbnMtc2VyaWYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZvbnQtc2l6ZT0iNjQiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIDEgMjQwNC4yIDg3NSkiPue9kee7nOWbvuS4reeahOihqOi+vjwvdGV4dD48L2c+PC9zdmc+";export{N as _}; diff --git a/assets/versions.html-1Kk-C1xB.js b/assets/versions.html-1Kk-C1xB.js new file mode 100644 index 00000000..6c96bb38 --- /dev/null +++ b/assets/versions.html-1Kk-C1xB.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-ebb0d7ba","path":"/en/notes/versions.html","title":"Versions of MicroCity","lang":"en-US","frontmatter":{"description":"MicroCity GitHub release (latest by date) When MicroCity software was initially launched, there was only a desktop version available, which could only run on Windows operating s...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/versions.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/versions.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Versions of MicroCity"}],["meta",{"property":"og:description","content":"MicroCity GitHub release (latest by date) When MicroCity software was initially launched, there was only a desktop version available, which could only run on Windows operating s..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Versions of MicroCity\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCity","slug":"microcity","link":"#microcity","children":[]},{"level":2,"title":"MicroCityWeb","slug":"microcityweb","link":"#microcityweb","children":[]},{"level":2,"title":"Compatibility","slug":"compatibility","link":"#compatibility","children":[]},{"level":2,"title":"Summary","slug":"summary","link":"#summary","children":[]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/versions.md","autoDesc":true}');export{t as data}; diff --git a/assets/versions.html-8A5Y-n6r.js b/assets/versions.html-8A5Y-n6r.js new file mode 100644 index 00000000..1832f83c --- /dev/null +++ b/assets/versions.html-8A5Y-n6r.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-77d2e8b7","path":"/notes/versions.html","title":"MicroCity的版本","lang":"zh-CN","frontmatter":{"description":"MicroCity GitHub release (latest by date) MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwind (https://github.com/sunzhuo))意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/versions.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/versions.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"MicroCity的版本"}],["meta",{"property":"og:description","content":"MicroCity GitHub release (latest by date) MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwind (https://github.com/sunzhuo))意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-20T15:40:00.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T15:40:00.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"MicroCity的版本\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T15:40:00.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCity","slug":"microcity","link":"#microcity","children":[]},{"level":2,"title":"MicroCityWeb","slug":"microcityweb","link":"#microcityweb","children":[]},{"level":2,"title":"兼容性","slug":"兼容性","link":"#兼容性","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"updatedTime":1700494800000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":9}]},"filePathRelative":"notes/versions.md","autoDesc":true}');export{t as data}; diff --git a/assets/versions.html-HjNHjtrH.js b/assets/versions.html-HjNHjtrH.js deleted file mode 100644 index 2b014ded..00000000 --- a/assets/versions.html-HjNHjtrH.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-77d2e8b7","path":"/notes/versions.html","title":"MicroCity的版本","lang":"zh-CN","frontmatter":{"description":"MicroCity GitHub release (latest by date) MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwind (https://github.com/sunzhuo))意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/versions.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"MicroCity的版本"}],["meta",{"property":"og:description","content":"MicroCity GitHub release (latest by date) MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwind (https://github.com/sunzhuo))意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-20T15:40:00.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-20T15:40:00.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"MicroCity的版本\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-20T15:40:00.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"MicroCity","slug":"microcity","link":"#microcity","children":[]},{"level":2,"title":"MicroCityWeb","slug":"microcityweb","link":"#microcityweb","children":[]},{"level":2,"title":"兼容性","slug":"兼容性","link":"#兼容性","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"updatedTime":1700494800000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":9}]},"filePathRelative":"notes/versions.md","autoDesc":true}');export{t as data}; diff --git a/assets/versions.html-9uZsLBnu.js b/assets/versions.html-aHfbE8Cr.js similarity index 98% rename from assets/versions.html-9uZsLBnu.js rename to assets/versions.html-aHfbE8Cr.js index d45b98cc..7d7427c8 100644 --- a/assets/versions.html-9uZsLBnu.js +++ b/assets/versions.html-aHfbE8Cr.js @@ -1 +1 @@ -import{_ as r,r as c,o as s,c as n,a as e,b as i,d as o,e as l}from"./app-DaLjD81q.js";const a={},h=e("h1",{id:"microcity的版本",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity的版本","aria-hidden":"true"},"#"),i(" MicroCity的版本")],-1),d=e("h2",{id:"microcity",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity","aria-hidden":"true"},"#"),i(" MicroCity")],-1),p=e("img",{src:"https://img.shields.io/github/v/release/microcity/Desktop",alt:"GitHub release (latest by date)"},null,-1),u={href:"https://github.com/microcity/Desktop/releases/latest",target:"_blank",rel:"noopener noreferrer"},_=e("img",{src:"https://img.shields.io/github/downloads/microcity/Desktop/latest/total",alt:"GitHub release (by tag)"},null,-1),b={href:"https://github.com/sunzhuo",target:"_blank",rel:"noopener noreferrer"},m=e("h2",{id:"microcityweb",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcityweb","aria-hidden":"true"},"#"),i(" MicroCityWeb")],-1),y=e("p",null,[e("img",{src:"https://img.shields.io/github/last-commit/microcity/microcity.github.io/master",alt:"GitHub last commit (branch)"})],-1),g={href:"https://microcityweb.gitee.io",target:"_blank",rel:"noopener noreferrer"},C={href:"https://gitee.com/microcityweb/microcityweb/releases/latest",target:"_blank",rel:"noopener noreferrer"},M=l('

为了解决这个问题,开发者决定开发 MicroCity Web,这是一个可以直接在浏览器中运行的版本。 MicroCity Web 不需要任何安装,只需要使用现代浏览器(如Google Chrome、Microsoft Edge)访问它的网站即可。虽然相比于桌面版,运行在浏览器上可能会造成一定的性能损失,但是这使得用户可以在几乎任何操作系统上使用该软件,比如电脑系统Windows、MacOS、Linux和手机/平板系统Android等。

尽管MicroCity的开发者推出了 MicroCity Web,您仍然可以继续使用以前开发的桌面版MicroCity。然而,桌面版本将不再更新新功能,所有新的功能和改进都将集中在 MicroCity Web 版中。这个决定的目的是确保 MicroCity 能够专注于一种版本,并在这个版本中提供最好的体验。这也使得 MicroCity 更容易管理和维护,避免了版本控制问题。

值得一提的是,尽管桌面版本不再更新新功能,它仍然可以继续使用。如果用户已经习惯使用桌面版本,他们可以继续使用它。然而,如果用户希望体验最新的功能和改进,则需要改用 MicroCity Web 版。

MicroCity Web 版也提供使用浏览器打包导出的离线版本(见上方 🔗链接)。

注意

但是由于 Chromium 浏览器内核的更新,某些老旧的系统版本可能不受支持(如 Windows 8.1 及以下的 Windows 版本、32 位的 Windows 操作系统等)

兼容性

MicroCity Web 版使用 Lua 5.4 作为脚本语言编写脚本。您可以在 MicroCity Web 运行环境或编辑器中输入 print(_VERSION) 指令查看使用的 Lua 版本。

由于使用了实验性的 JavaScript函数,MicroCity Web 可能在以下浏览器内核中运行存在兼容性问题:

  • iOS和iPad OS上的大多数浏览器(由于Apple强制使用Safari的浏览器内核)
  • FireFox浏览器

2023/9/29测试遇到的兼容性问题及部分技术细节

  • iOS 和 iPad OS:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)
  • FireFox:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)
',11),f=e("code",null,"showOpenFilePicker()",-1),W={href:"https://developer.mozilla.org/zh-CN/docs/Web/API/window/showOpenFilePicker#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7",target:"_blank",rel:"noopener noreferrer"},w=e("h2",{id:"总结",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#总结","aria-hidden":"true"},"#"),i(" 总结")],-1),k=e("p",null,"MicroCity Web 版的推出使得软件更加易用和普及,让更多的用户可以从中受益。同时,MicroCity 桌面版本仍然可用,使得那些已经习惯于使用该版本的用户可以继续使用,并让他们更容易地过渡到 MicroCity Web 版。",-1),x=e("p",null,"本文作者在写这篇笔记的时候 MicroCity Web 正在被第一次用于教学环境中,已经基本能够正常运行并实现一定的仿真功能。本文作者的学习经历如下:",-1),E=e("ul",null,[e("li",null,"MicroCity(桌面版):物流信息管理"),e("li",null,"MicroCity Web :物流系统仿真")],-1),O={href:"https://github.com/huuhghhgyg/MicroCityNotes/pulls",target:"_blank",rel:"noopener noreferrer"};function v(F,S){const t=c("ExternalLinkIcon");return s(),n("div",null,[h,d,e("p",null,[p,i(),e("a",u,[_,o(t)])]),e("p",null,[i("MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者("),e("a",b,[i("@mixwind"),o(t)]),i(")意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他操作系统,比如MacOS、Linux等。")]),m,y,e("p",null,[i("🎯"),e("a",g,[i("访问MicroCity Web"),o(t)]),i(" 📍"),e("a",C,[i("(离线版)下载"),o(t)])]),M,e("blockquote",null,[e("p",null,[i("关于 "),f,i(" 方法的影响参见 "),e("a",W,[i("MDN Web Docs | showOpenFilePicker()"),o(t)])])]),w,k,x,E,e("p",null,[i("本站笔记内容仅供参考。如果本文内容由于时间的因素出现偏差,也欢迎各位在 Github 上通过 "),e("a",O,[i("Pull Request"),o(t)]),i(" 的方式对本站内容进行修正🥳")])])}const N=r(a,[["render",v],["__file","versions.html.vue"]]);export{N as default}; +import{_ as r,r as c,o as s,c as n,a as e,b as i,d as o,e as l}from"./app-LOf__QKq.js";const a={},h=e("h1",{id:"microcity的版本",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity的版本","aria-hidden":"true"},"#"),i(" MicroCity的版本")],-1),d=e("h2",{id:"microcity",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity","aria-hidden":"true"},"#"),i(" MicroCity")],-1),p=e("img",{src:"https://img.shields.io/github/v/release/microcity/Desktop",alt:"GitHub release (latest by date)"},null,-1),u={href:"https://github.com/microcity/Desktop/releases/latest",target:"_blank",rel:"noopener noreferrer"},_=e("img",{src:"https://img.shields.io/github/downloads/microcity/Desktop/latest/total",alt:"GitHub release (by tag)"},null,-1),b={href:"https://github.com/sunzhuo",target:"_blank",rel:"noopener noreferrer"},m=e("h2",{id:"microcityweb",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcityweb","aria-hidden":"true"},"#"),i(" MicroCityWeb")],-1),y=e("p",null,[e("img",{src:"https://img.shields.io/github/last-commit/microcity/microcity.github.io/master",alt:"GitHub last commit (branch)"})],-1),g={href:"https://microcityweb.gitee.io",target:"_blank",rel:"noopener noreferrer"},C={href:"https://gitee.com/microcityweb/microcityweb/releases/latest",target:"_blank",rel:"noopener noreferrer"},M=l('

为了解决这个问题,开发者决定开发 MicroCity Web,这是一个可以直接在浏览器中运行的版本。 MicroCity Web 不需要任何安装,只需要使用现代浏览器(如Google Chrome、Microsoft Edge)访问它的网站即可。虽然相比于桌面版,运行在浏览器上可能会造成一定的性能损失,但是这使得用户可以在几乎任何操作系统上使用该软件,比如电脑系统Windows、MacOS、Linux和手机/平板系统Android等。

尽管MicroCity的开发者推出了 MicroCity Web,您仍然可以继续使用以前开发的桌面版MicroCity。然而,桌面版本将不再更新新功能,所有新的功能和改进都将集中在 MicroCity Web 版中。这个决定的目的是确保 MicroCity 能够专注于一种版本,并在这个版本中提供最好的体验。这也使得 MicroCity 更容易管理和维护,避免了版本控制问题。

值得一提的是,尽管桌面版本不再更新新功能,它仍然可以继续使用。如果用户已经习惯使用桌面版本,他们可以继续使用它。然而,如果用户希望体验最新的功能和改进,则需要改用 MicroCity Web 版。

MicroCity Web 版也提供使用浏览器打包导出的离线版本(见上方 🔗链接)。

注意

但是由于 Chromium 浏览器内核的更新,某些老旧的系统版本可能不受支持(如 Windows 8.1 及以下的 Windows 版本、32 位的 Windows 操作系统等)

兼容性

MicroCity Web 版使用 Lua 5.4 作为脚本语言编写脚本。您可以在 MicroCity Web 运行环境或编辑器中输入 print(_VERSION) 指令查看使用的 Lua 版本。

由于使用了实验性的 JavaScript函数,MicroCity Web 可能在以下浏览器内核中运行存在兼容性问题:

  • iOS和iPad OS上的大多数浏览器(由于Apple强制使用Safari的浏览器内核)
  • FireFox浏览器

2023/9/29测试遇到的兼容性问题及部分技术细节

  • iOS 和 iPad OS:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)
  • FireFox:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)
',11),f=e("code",null,"showOpenFilePicker()",-1),W={href:"https://developer.mozilla.org/zh-CN/docs/Web/API/window/showOpenFilePicker#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7",target:"_blank",rel:"noopener noreferrer"},w=e("h2",{id:"总结",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#总结","aria-hidden":"true"},"#"),i(" 总结")],-1),k=e("p",null,"MicroCity Web 版的推出使得软件更加易用和普及,让更多的用户可以从中受益。同时,MicroCity 桌面版本仍然可用,使得那些已经习惯于使用该版本的用户可以继续使用,并让他们更容易地过渡到 MicroCity Web 版。",-1),x=e("p",null,"本文作者在写这篇笔记的时候 MicroCity Web 正在被第一次用于教学环境中,已经基本能够正常运行并实现一定的仿真功能。本文作者的学习经历如下:",-1),E=e("ul",null,[e("li",null,"MicroCity(桌面版):物流信息管理"),e("li",null,"MicroCity Web :物流系统仿真")],-1),O={href:"https://github.com/huuhghhgyg/MicroCityNotes/pulls",target:"_blank",rel:"noopener noreferrer"};function v(F,S){const t=c("ExternalLinkIcon");return s(),n("div",null,[h,d,e("p",null,[p,i(),e("a",u,[_,o(t)])]),e("p",null,[i("MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者("),e("a",b,[i("@mixwind"),o(t)]),i(")意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他操作系统,比如MacOS、Linux等。")]),m,y,e("p",null,[i("🎯"),e("a",g,[i("访问MicroCity Web"),o(t)]),i(" 📍"),e("a",C,[i("(离线版)下载"),o(t)])]),M,e("blockquote",null,[e("p",null,[i("关于 "),f,i(" 方法的影响参见 "),e("a",W,[i("MDN Web Docs | showOpenFilePicker()"),o(t)])])]),w,k,x,E,e("p",null,[i("本站笔记内容仅供参考。如果本文内容由于时间的因素出现偏差,也欢迎各位在 Github 上通过 "),e("a",O,[i("Pull Request"),o(t)]),i(" 的方式对本站内容进行修正🥳")])])}const N=r(a,[["render",v],["__file","versions.html.vue"]]);export{N as default}; diff --git a/assets/versions.html-diw0opQu.js b/assets/versions.html-diw0opQu.js new file mode 100644 index 00000000..04cecfa8 --- /dev/null +++ b/assets/versions.html-diw0opQu.js @@ -0,0 +1 @@ +import{_ as s,r,o as n,c as a,a as e,b as t,d as i,e as l}from"./app-LOf__QKq.js";const c={},h=e("h1",{id:"versions-of-microcity",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#versions-of-microcity","aria-hidden":"true"},"#"),t(" Versions of MicroCity")],-1),d=e("h2",{id:"microcity",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcity","aria-hidden":"true"},"#"),t(" MicroCity")],-1),u=e("img",{src:"https://img.shields.io/github/v/release/microcity/Desktop",alt:"GitHub release (latest by date)"},null,-1),p={href:"https://github.com/microcity/Desktop/releases/latest",target:"_blank",rel:"noopener noreferrer"},m=e("img",{src:"https://img.shields.io/github/downloads/microcity/Desktop/latest/total",alt:"GitHub release (by tag)"},null,-1),b={href:"https://github.com/sunzhuo",target:"_blank",rel:"noopener noreferrer"},f=e("h2",{id:"microcityweb",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#microcityweb","aria-hidden":"true"},"#"),t(" MicroCityWeb")],-1),y=e("p",null,[e("img",{src:"https://img.shields.io/github/last-commit/microcity/microcity.github.io/master",alt:"GitHub last commit (branch)"})],-1),g={href:"https://microcityweb.gitee.io",target:"_blank",rel:"noopener noreferrer"},w={href:"https://gitee.com/microcityweb/microcityweb/releases/latest",target:"_blank",rel:"noopener noreferrer"},_=l('

To address this issue, the developer decided to develop MicroCityWeb, which is a version that can be directly run in a web browser. MicroCityWeb does not require any installation, just access its website using a modern browser such as Google Chrome or Microsoft Edge. Although running in a browser may cause some performance loss compared to the desktop version, it allows users to use the software on almost any operating system, such as Windows, MacOS, Linux for computers, and Android for mobile devices and tablets.

Although MicroCityWeb has been developed by the creators of MicroCity, you can still continue to use the previously developed desktop version of MicroCity. However, the desktop version will no longer receive updates for new features. All new features and improvements will be focused on the MicroCityWeb version. This decision aims to ensure that MicroCity can focus on one version and provide the best possible experience in that version. It also makes it easier to manage and maintain MicroCity, avoiding version control issues.

It should be noted that although the desktop version will no longer receive updates for new features, it can still be used. If users are already accustomed to using the desktop version, they can continue to do so. However, if users want to experience the latest features and improvements, they will need to switch to the MicroCityWeb version.

The MicroCityWeb version also provides an offline version packaged for browsers (see link above 🔗link).

Note

However, due to updates to the Chromium browser engine, certain outdated system versions may not be supported (such as Windows versions 8.1 and below, 32-bit Windows operating systems, etc.).

Compatibility

Due to the use of experimental JavaScript functions, MicroCityWeb may have compatibility issues running on the following browser engines:

  • Most browsers on iOS and iPadOS (due to Apple's requirement to use Safari's browser engine)
  • Firefox browser

Compatibility issues and some technical details encountered during testing on 29th September 2023

  • iOS and iPadOS:
    • Unable to open local files (due to the use of showOpenFilePicker() method)
  • Firefox:
    • Unable to open local files (due to the use of showOpenFilePicker() method)
',10),v=e("code",null,"showOpenFilePicker()",-1),k={href:"https://developer.mozilla.org/zh-CN/docs/Web/API/window/showOpenFilePicker#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7",target:"_blank",rel:"noopener noreferrer"},C=e("h2",{id:"summary",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#summary","aria-hidden":"true"},"#"),t(" Summary")],-1),M=e("p",null,"The launch of MicroCityWeb version makes the software more user-friendly and popular, benefiting a wider range of users. At the same time, the MicroCity desktop version is still available, allowing users who are accustomed to this version to continue using it and facilitating their transition to the MicroCityWeb version.",-1),x=e("p",null,"At the time of writing this note, the MicroCityWeb is being used for the first time in a teaching environment and is able to function properly and provide certain simulation capabilities. The author's learning experience with MicroCity is as follows:",-1),W=e("ul",null,[e("li",null,"MicroCity (desktop version): Logistics information management"),e("li",null,"MicroCityWeb: Logistics system simulation")],-1),O={href:"https://github.com/huuhghhgyg/MicroCityNotes/pulls",target:"_blank",rel:"noopener noreferrer"},A={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},P=e("strong",null,"feedback",-1);function E(S,N){const o=r("ExternalLinkIcon");return n(),a("div",null,[h,d,e("p",null,[u,t(),e("a",p,[m,i(o)])]),e("p",null,[t("When MicroCity software was initially launched, there was only a desktop version available, which could only run on Windows operating systems. Over time, the developer ("),e("a",b,[t("@mixwind"),i(o)]),t(") realized that this limitation prevented many potential users from using the software because they might be using other operating systems such as MacOS, Linux, and others.")]),f,y,e("p",null,[t("🎯"),e("a",g,[t("Visit MicroCity Web"),i(o)]),t(" 📍"),e("a",w,[t("(Offline version) Download"),i(o)])]),_,e("p",null,[t("Regarding the impact of the "),v,t(" method, please refer to "),e("a",k,[t("MDN Web Docs | showOpenFilePicker()"),i(o)]),t(".")]),C,M,x,W,e("p",null,[t("The content of this note is for reference only. If there are any discrepancies in the content due to time factors, you are also welcome to make corrections to the content of this note on Github through a Pull Request 🥳. Please check the "),e("a",O,[t("Pull Request"),i(o)]),t(" for further details.")]),e("blockquote",null,[e("p",null,[t("This post is translated using ChatGPT, please "),e("a",A,[P,i(o)]),t(" if any omissions.")])])])}const F=s(c,[["render",E],["__file","versions.html.vue"]]);export{F as default}; diff --git a/assets/visualization.html--w3hFG24.js b/assets/visualization.html--w3hFG24.js deleted file mode 100644 index f178c337..00000000 --- a/assets/visualization.html--w3hFG24.js +++ /dev/null @@ -1,4 +0,0 @@ -import{_ as c,r as n,o as d,c as i,a as o,b as e,d as a,w as s,e as r}from"./app-DaLjD81q.js";const p="/MicroCityNotes/assets/LookupTableProperties-P0W9jYQE.png",l="/MicroCityNotes/assets/TableSelect-jKGsdf_N.png",u="/MicroCityNotes/assets/LookupTableColor-VSXylHlz.png",g="/MicroCityNotes/assets/SelectLinksColor--zZDTT73.png",h="/MicroCityNotes/assets/GraduatedColorProperties-QL7AyCTd.png",_="/MicroCityNotes/assets/GraduatedColorResult-c1P6KfFi.png",m="/MicroCityNotes/assets/GraduatedColorSettings-sd7MRVbC.png",b="/MicroCityNotes/assets/RelateToMapBig-co0riIjm.png",S="/MicroCityNotes/assets/RelateToMapSmall-8yIwZc0w.png",C="/MicroCityNotes/assets/RelateToScreenBig-H3UhFI8t.png",k="/MicroCityNotes/assets/RelateToScreenSmall-RgyFR_Ap.png",T="/MicroCityNotes/assets/RangeDotRelateToMap-s6apr58V.png",E="/MicroCityNotes/assets/SizeProperties-xZe9_-WE.png",L="/MicroCityNotes/assets/LabelAttribProperties-BNSD9rBn.png",M="/MicroCityNotes/assets/SetParameterProperties-m8LPKWT1.png",f="/MicroCityNotes/assets/PlotPrice1-QAaVF6hQ.png",P="/MicroCityNotes/assets/PlotPrice2-DeodiEK_.png",y="/MicroCityNotes/assets/DL_Heatmap-uiGWW-lH.png",A={},B=r('

结果可视化

本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。

改变形状颜色

在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项:

  • Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。
  • Lookup Table:通过数值查询表格显示对应的颜色。
  • Graduated Color:根据表中数值大小设置渐变色。

Lookup Table 通过表中值改变颜色

Type的属性值改为Lookup Table,根据表格中的数值改变图形的颜色,达到选中指定图形的效果。

LookupTableProperties.png

此处示例将Lookup Table中的Attribute改为表格中的SELECT,通过表中的SELECT列值控制线的颜色(属性设置见上图)。当值为0时显示黑色,值为1时显示红色。表格中SELECT列的值和Lookup Table中的具体设置如下图。

TableSelect.pngLookupTableColor.png

最终实现的效果 SelectLinksColor.png

Graduated Color 根据值的大小显示渐变色

Type的属性值改为Graduated Color,根据表格中不同数值的大小显示不同的颜色,达到显示渐变色的效果。

GraduatedColorProperties.png

此处示例根据每个国家的人口数量显示渐变色。可以看到中国人口数量大,因此显示红色,印度人口数量也较大,因此显示橙色。其他地区人口数量较低,但也能通过颜色看出一些差别。

GraduatedColorResult.png

Graduated Color下的Colors属性中还可以调整其他配色方案。设置界面如下图,此处就不不一一列举了。

GraduatedColorSettings.png

',18),N=r('

更改图形和标签的显示大小

参考系的选择

显示内容尺寸的参考系有2个,一个是以地图为参考系,一个是以屏幕为参考系。此处将图形和标签的显示尺寸都设置为相同的参考系。

内容以地图为参考系时,显示内容的大小会根据地图大小同步缩放,如下图:

RelateToMapBig.png (以地图为参考系放大)

RelateToMapSmall.png (以地图为参考系缩小)

内容以屏幕为参考系时,无论地图怎么缩放内容的大小都差不多,如下图:

RelateToScreenBig.png (以屏幕为参考系放大)

RelateToScreenSmall.png (以屏幕为参考系缩小)

因此,绘图的时候要根据绘图的目的选定参考系

  • 如果需要在地图上绘制确定尺寸的形状或者标明确定尺寸的标签,如绘制一个半径为10km的圆,此时应选用以地图为参考系
  • 如果仅需要在任何尺寸下都能清晰显示标签和图形,此时可以选择以屏幕为参考系

参考系应用实例

在图中绘制圆点,将圆的半径设置为圆的大小,并将圆的中心设置在每个绿点的中心上,灰色圆的大小表示每个绿点的覆盖范围大小

RangeDotRelateToMap.png

图中以地图为参考系(Map Units),以16为半径为每个绿点都绘制了一个灰色的圆,表示每个绿点的覆盖范围。这些灰色的圆存放在名为Range.shp的图层内,图层类型为Points

参考系的设定

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。 SizeProperties.png

如图标记的两个位置可以分别调整图形尺寸的参考系和标签尺寸的参考系。

  • 图形尺寸参考系设置Size栏目下的Size relates to...调整图形尺寸的参考系,Default Size调整图形的相对于坐标系的尺寸。
  • 标签尺寸参考系设置Labels栏目下的Size relates to...调整标签尺寸的参考系,Default Size调整的是标签(Labels)相对于坐标系的尺寸。

更改显示的标签

手动更改显示的标签

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。上图中显示的标签为ID,如果需要改为表格中的其他列,可以更改Lables栏目下的Attribute属性实现。

需要更改的属性位置如图,图中需要显示表中对应MSG列的值,只需要将Labels栏目下的Attribute属性值改为MSG即可。

LabelAttribProperties.png

但是每次更改图形并执行Update()函数后标签(Label)会取消显示。如果需要执行的脚本中含有此对于此图层的Update()函数,不必在每次执行完脚本后手动重新设置显示的标签,可以通过脚本自动选择显示的标签

自动更改显示的标签

通过SetParameter()函数可以更改属性值。以上图Labels栏目下的Attribute属性为例,选中这条属性后可以看到底栏显示其IDLABEL_ATTRIB,其类型为Choice

需要注意的是,当类型为Choice时,参数值从1开始编号,编号顺次对应下拉菜单的内容。

点开这条属性以后,可以看到MSG在第二个。

SetParameterProperties.png

由于Lua中编号一般由1开始,因此此处ID的编号对应1,MSG的编号对应2。需要操作对象为MSG,所以函数中需要填入Choice类型的参数值为2。

此时已经得到了所有需要的参数,可以使用SetParameter()函数对显示的标签进行更改。

-- transports为图形图层
-SetParameter(transports, "LABEL_ATTRIB", 2)
-

SetParameter()函数需要在Update()函数执行后再执行,否则效果会被Update()函数覆盖。

现在回过头来再看看SetParameter()函数的具体用法:

SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
-
参数含义
参数1输入的对象,可以是ShapesTableGridSceneModule
参数2其中的id为属性对应的ID。如果是上文的情况,就是LABEL_ATTRIB
参数3如果需要更改属性值,只接受数值(Number)、字符串(String)、对象(Object)三种类型
`,35),v=o("code",null,"SetParameter()",-1),R=o("h2",{id:"借助栅格图",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#借助栅格图","aria-hidden":"true"},"#"),e(" 借助栅格图")],-1),x=o("strong",null,"绘制热力图",-1),G=o("p",null,[e("一种使用栅格图绘制热力图的场景就是"),o("strong",null,"绘制地价图"),e("。在绘制地价图时,我们可以遍历栅格图上的每个格点,计算该格点到每个仓库的距离之和。然后将该格点的值设置为这个值,就可以得到一张热力图。这种方法可以帮助我们可视化地价的分布情况,并且可以用来发现地价的趋势和规律。")],-1),D=o("p",null,[o("img",{src:f,alt:"PlotPrice1.png"}),o("img",{src:P,alt:"PlotPrice2.png"}),o("img",{src:y,alt:"DL_Heatmap.png"})],-1);function q(z,I){const t=n("RouterLink");return d(),i("div",null,[B,o("p",null,[e("如果感兴趣可以参考文档"),a(t,{to:"/docs/2.1_showing_a_world_map.html"},{default:s(()=>[e("2.1 展示世界地图")]),_:1}),e("中的示例手动尝试更改此属性。")]),N,o("p",null,[v,e("函数的介绍出现在文档 "),a(t,{to:"/docs/4.2_ui_control.html"},{default:s(()=>[e("4.2 控制用户界面")]),_:1}),e(" 中,请参阅。")]),R,o("p",null,[e("栅格图也可以用于可视化,我认为栅格图最常用的场景就是"),x,e("。热力图的绘制主要通过修改栅格图上每个格子的值实现。如果不清楚栅格图的具体结构,可以先参考文档 "),a(t,{to:"/docs/3.3_raster_grids.html"},{default:s(()=>[e("3.3 栅格图")]),_:1}),e("。关于使用脚本控制栅格图,可以参考文档 "),a(t,{to:"/docs/4.4_grids.html"},{default:s(()=>[e("4.4 栅格图形")]),_:1}),e("。")]),G,D])}const V=c(A,[["render",q],["__file","visualization.html.vue"]]);export{V as default}; diff --git a/assets/visualization.html-2T-VgKWL.js b/assets/visualization.html-2T-VgKWL.js new file mode 100644 index 00000000..1d66bd2c --- /dev/null +++ b/assets/visualization.html-2T-VgKWL.js @@ -0,0 +1,4 @@ +import{_ as r,a as c,b as n,c as p,d as i,e as l,f as u,g as h,h as g,i as _,j as m,k as b,l as k,m as S,n as E,o as f,p as L,q as T}from"./DL_Heatmap-RXB-9ZZK.js";import{_ as v,r as A,o as B,c as C,a,b as e,d as t,w as s,e as d}from"./app-LOf__QKq.js";const x={},P=d('

结果可视化

本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。

改变形状颜色

在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项:

  • Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。
  • Lookup Table:通过数值查询表格显示对应的颜色。
  • Graduated Color:根据表中数值大小设置渐变色。

Lookup Table 通过表中值改变颜色

Type的属性值改为Lookup Table,根据表格中的数值改变图形的颜色,达到选中指定图形的效果。

LookupTableProperties.png

此处示例将Lookup Table中的Attribute改为表格中的SELECT,通过表中的SELECT列值控制线的颜色(属性设置见上图)。当值为0时显示黑色,值为1时显示红色。表格中SELECT列的值和Lookup Table中的具体设置如下图。

TableSelect.pngLookupTableColor.png

最终实现的效果 SelectLinksColor.png

Graduated Color 根据值的大小显示渐变色

Type的属性值改为Graduated Color,根据表格中不同数值的大小显示不同的颜色,达到显示渐变色的效果。

GraduatedColorProperties.png

此处示例根据每个国家的人口数量显示渐变色。可以看到中国人口数量大,因此显示红色,印度人口数量也较大,因此显示橙色。其他地区人口数量较低,但也能通过颜色看出一些差别。

GraduatedColorResult.png

Graduated Color下的Colors属性中还可以调整其他配色方案。设置界面如下图,此处就不不一一列举了。

GraduatedColorSettings.png

',18),G=d('

更改图形和标签的显示大小

参考系的选择

显示内容尺寸的参考系有2个,一个是以地图为参考系,一个是以屏幕为参考系。此处将图形和标签的显示尺寸都设置为相同的参考系。

内容以地图为参考系时,显示内容的大小会根据地图大小同步缩放,如下图:

RelateToMapBig.png (以地图为参考系放大)

RelateToMapSmall.png (以地图为参考系缩小)

内容以屏幕为参考系时,无论地图怎么缩放内容的大小都差不多,如下图:

RelateToScreenBig.png (以屏幕为参考系放大)

RelateToScreenSmall.png (以屏幕为参考系缩小)

因此,绘图的时候要根据绘图的目的选定参考系

  • 如果需要在地图上绘制确定尺寸的形状或者标明确定尺寸的标签,如绘制一个半径为10km的圆,此时应选用以地图为参考系
  • 如果仅需要在任何尺寸下都能清晰显示标签和图形,此时可以选择以屏幕为参考系

参考系应用实例

在图中绘制圆点,将圆的半径设置为圆的大小,并将圆的中心设置在每个绿点的中心上,灰色圆的大小表示每个绿点的覆盖范围大小

RangeDotRelateToMap.png

图中以地图为参考系(Map Units),以16为半径为每个绿点都绘制了一个灰色的圆,表示每个绿点的覆盖范围。这些灰色的圆存放在名为Range.shp的图层内,图层类型为Points

参考系的设定

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。 SizeProperties.png

如图标记的两个位置可以分别调整图形尺寸的参考系和标签尺寸的参考系。

  • 图形尺寸参考系设置Size栏目下的Size relates to...调整图形尺寸的参考系,Default Size调整图形的相对于坐标系的尺寸。
  • 标签尺寸参考系设置Labels栏目下的Size relates to...调整标签尺寸的参考系,Default Size调整的是标签(Labels)相对于坐标系的尺寸。

更改显示的标签

手动更改显示的标签

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。上图中显示的标签为ID,如果需要改为表格中的其他列,可以更改Lables栏目下的Attribute属性实现。

需要更改的属性位置如图,图中需要显示表中对应MSG列的值,只需要将Labels栏目下的Attribute属性值改为MSG即可。

LabelAttribProperties.png

但是每次更改图形并执行Update()函数后标签(Label)会取消显示。如果需要执行的脚本中含有此对于此图层的Update()函数,不必在每次执行完脚本后手动重新设置显示的标签,可以通过脚本自动选择显示的标签

自动更改显示的标签

通过SetParameter()函数可以更改属性值。以上图Labels栏目下的Attribute属性为例,选中这条属性后可以看到底栏显示其IDLABEL_ATTRIB,其类型为Choice

需要注意的是,当类型为Choice时,参数值从1开始编号,编号顺次对应下拉菜单的内容。

点开这条属性以后,可以看到MSG在第二个。

SetParameterProperties.png

由于Lua中编号一般由1开始,因此此处ID的编号对应1,MSG的编号对应2。需要操作对象为MSG,所以函数中需要填入Choice类型的参数值为2。

此时已经得到了所有需要的参数,可以使用SetParameter()函数对显示的标签进行更改。

-- transports为图形图层
+SetParameter(transports, "LABEL_ATTRIB", 2)
+

SetParameter()函数需要在Update()函数执行后再执行,否则效果会被Update()函数覆盖。

现在回过头来再看看SetParameter()函数的具体用法:

SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
+
参数含义
参数1输入的对象,可以是ShapesTableGridSceneModule
参数2其中的id为属性对应的ID。如果是上文的情况,就是LABEL_ATTRIB
参数3如果需要更改属性值,只接受数值(Number)、字符串(String)、对象(Object)三种类型
`,35),R=a("code",null,"SetParameter()",-1),q=a("h2",{id:"借助栅格图",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#借助栅格图","aria-hidden":"true"},"#"),e(" 借助栅格图")],-1),M=a("strong",null,"绘制热力图",-1),D=a("p",null,[e("一种使用栅格图绘制热力图的场景就是"),a("strong",null,"绘制地价图"),e("。在绘制地价图时,我们可以遍历栅格图上的每个格点,计算该格点到每个仓库的距离之和。然后将该格点的值设置为这个值,就可以得到一张热力图。这种方法可以帮助我们可视化地价的分布情况,并且可以用来发现地价的趋势和规律。")],-1),y=a("p",null,[a("img",{src:r,alt:"PlotPrice1.png"}),a("img",{src:c,alt:"PlotPrice2.png"}),a("img",{src:n,alt:"DL_Heatmap.png"})],-1);function z(I,N){const o=A("RouterLink");return B(),C("div",null,[P,a("p",null,[e("如果感兴趣可以参考文档"),t(o,{to:"/docs/2.1_showing_a_world_map.html"},{default:s(()=>[e("2.1 展示世界地图")]),_:1}),e("中的示例手动尝试更改此属性。")]),G,a("p",null,[R,e("函数的介绍出现在文档 "),t(o,{to:"/docs/4.2_ui_control.html"},{default:s(()=>[e("4.2 控制用户界面")]),_:1}),e(" 中,请参阅。")]),q,a("p",null,[e("栅格图也可以用于可视化,我认为栅格图最常用的场景就是"),M,e("。热力图的绘制主要通过修改栅格图上每个格子的值实现。如果不清楚栅格图的具体结构,可以先参考文档 "),t(o,{to:"/docs/3.3_raster_grids.html"},{default:s(()=>[e("3.3 栅格图")]),_:1}),e("。关于使用脚本控制栅格图,可以参考文档 "),t(o,{to:"/docs/4.4_grids.html"},{default:s(()=>[e("4.4 栅格图形")]),_:1}),e("。")]),D,y])}const F=v(x,[["render",z],["__file","visualization.html.vue"]]);export{F as default}; diff --git a/assets/visualization.html-URi_NNx7.js b/assets/visualization.html-URi_NNx7.js new file mode 100644 index 00000000..856ef3df --- /dev/null +++ b/assets/visualization.html-URi_NNx7.js @@ -0,0 +1,4 @@ +import{_ as c,a as l,b as d,c as h,d as p,e as u,f as g,g as f,h as m,i as b,j as y,k as _,l as v,m as T,n as w,o as k,p as S,q as z}from"./DL_Heatmap-RXB-9ZZK.js";import{_ as x,r as n,o as C,c as L,a as t,b as e,d as a,w as s,e as i}from"./app-LOf__QKq.js";const I={},P=i('

Visualization of Results

This article introduces various methods for visualizing computational results. This includes changing the color of the content, changing the size of shapes, and changing the attribute labels displayed for elements.

Changing Shape Color

In the graphic properties box located at the bottom left corner of the program interface, the type of color displayed can be changed by modifying the Type attribute under the Colors section. There are 3 options available:

  • Unique Symbol: Specifies a specific color for all graphics in the same layer, which will not be discussed further here.
  • Lookup Table: Displays the corresponding color based on a numerical query from a table.
  • Graduated Color: Sets a gradient color based on the numerical values in the table.

Lookup Table - Changing Color Based on Table Values

By changing the Type attribute to Lookup Table, the color of the graphics can be modified based on the values in the table, achieving the effect of selecting specific graphics.

LookupTableProperties.png

In this example, the Attribute of Lookup Table is changed to SELECT in order to control the color of lines based on the values in the SELECT column of the table (as shown in the above image of attribute settings). When the value is 0, the color is displayed as black, and when the value is 1, the color is displayed as red. The values in the SELECT column of the table and the specific settings in the Lookup Table are shown in the following images.

TableSelect.pngLookupTableColor.png

The final effect achieved is shown below. SelectLinksColor.png

Graduated Color - Displaying Gradient Color Based on Values

By changing the Type attribute to Graduated Color, different colors can be displayed based on the varying numerical values in the table, achieving the effect of displaying a gradient color.

GraduatedColorProperties.png

In this example, a gradient color is displayed based on the population size of each country. It can be observed that China has a large population, hence the color displayed is red, while India also has a significant population, resulting in an orange color. Other regions have smaller populations, but differences can still be discerned through the colors.

GraduatedColorResult.png

The Colors attribute under Graduated Color can also be adjusted with other color schemes. The settings interface is shown in the following image, but each individual setting will not be listed here.

GraduatedColorSettings.png

',18),G=i('

Changing the Display Size of Shapes and Labels

Selection of Reference System

There are 2 reference systems for displaying the size of content: one based on the map and one based on the screen. In this case, both the size of shapes and the display of labels are set to the same reference system.

When content is displayed based on the map, the size of the content will be synchronized and scaled according to the size of the map, as shown in the following images:

RelateToMapBig.png (Enlarging the content based on the map)

RelateToMapSmall.png (Shrinking the content based on the map)

When content is displayed based on the screen, the size of the content remains relatively consistent regardless of the map scaling, as shown in the following image:

RelateToScreenBig.png (Enlarging the content based on the screen)

Translate into English:

RelateToScreenSmall.png (Shrunk with the screen as the reference system)

Therefore, when drawing, the reference system should be selected according to the purpose of the drawing.

  • If you need to draw shapes with a specific size or label with a specific size on a map, such as drawing a circle with a radius of 10 km, you should use the map as the reference system.
  • If you only need labels and graphics to be displayed clearly at any size, you can choose the screen as the reference system.

Application examples of reference system

Draw dots in the picture, set the radius of the circle to be the same as the size of the circle, and set the center of the circle to be the center of each green dot. The size of the gray circle represents the coverage range of each green dot.

RangeDotRelateToMap.png

In the picture, the gray circle is drawn for each green dot with a radius of 16, representing the coverage range of each green dot. These gray circles are stored in a layer called Range.shp, and the layer type is Points.

Setting the reference system

The size reference system for graphics and labels can be set in the bottom left corner of the program interface. SizeProperties.png

The two positions marked in the picture can adjust the size reference system for graphics and the size reference system for labels respectively.

  • Setting the size reference system for graphics: Adjust the size reference system for graphics under the Size column in the Size relates to... section. Adjust the Default Size to adjust the size of the graphics relative to the coordinate system.
  • Setting the size reference system for labels: Adjust the size reference system for labels under the Labels column in the Size relates to... section. Adjust the Default Size to adjust the size of the labels relative to the coordinate system.

Changing the displayed labels

Manually changing the displayed labels

The size reference system for graphics and labels can be set in the bottom left corner of the program interface. The labels displayed in the picture above are ID. If you need to change it to other columns in the table, you can change the Attribute property under the Labels column to achieve it.

The position to be changed is shown in the picture. If you need to display the value in the corresponding MSG column in the table, you only need to change the Attribute property value under the Labels column to MSG.

LabelAttribProperties.png

However, every time the graphics are changed and the Update() function is executed, the label will be hidden. If the script to be executed contains the Update() function for this layer, there is no need to manually reconfigure the displayed labels after each script execution. The displayed labels can be automatically selected through the script.

Automatically changing the displayed labels

The value of an attribute can be changed using the SetParameter() function. Taking the Attribute property under the Labels column in the picture above as an example, you can see that its ID is LABEL_ATTRIB and its type is Choice in the bottom bar.

It should be noted that when the type is Choice, the parameter values are numbered starting from 1 and the numbering corresponds to the contents of the drop-down menu in order.

After clicking on this property, you can see that MSG is in the second position.

SetParameterProperties.png

Since the numbering in Lua usually starts from 1, the number for ID here corresponds to 1, and the number for MSG corresponds to 2. The object to be operated on is MSG, so the function needs to fill in the parameter value of type Choice as 2.

Now that all the required parameters have been obtained, the SetParameter() function can be used to change the displayed labels.

-- transports is the graphic layer
+SetParameter(transports, "LABEL_ATTRIB", 2)
+

The SetParameter() function needs to be executed after the Update() function, otherwise the effect will be overwritten by the Update() function.

Now let's take a closer look at the specific usage of the SetParameter() function:

SetParameter(Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
+
ParameterMeaning
Parameter1The input object, which can be Shapes, Table, Grid, Scene, or Module
Parameter2The id corresponding to the attribute. In the previous context, it is LABEL_ATTRIB
Parameter3If you need to change the attribute value, it only accepts three types: Number, String, and Object
`,35),A=t("code",null,"SetParameter()",-1),R=t("h2",{id:"using-raster-grids",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#using-raster-grids","aria-hidden":"true"},"#"),e(" Using Raster Grids")],-1),q=t("strong",null,"draw heat maps",-1),B=t("p",null,[e("One scenario of using raster grids to draw heat maps is "),t("strong",null,"plotting price maps"),e(". When plotting a price map, we can iterate through each grid point on the raster grid, calculate the sum of distances from that grid point to each warehouse, and set the value of that grid point to this sum. This way, we can obtain a heat map. This method helps us visualize the distribution of prices and discover the trends and patterns of prices.")],-1),E=t("p",null,[t("img",{src:c,alt:"PlotPrice1.png"}),t("img",{src:l,alt:"PlotPrice2.png"}),t("img",{src:d,alt:"DL_Heatmap.png"})],-1),M={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},j=t("strong",null,"feedback",-1);function D(N,U){const o=n("RouterLink"),r=n("ExternalLinkIcon");return C(),L("div",null,[P,t("p",null,[e("If interested, the manual can be referred to for example "),a(o,{to:"/en/docs/2.1_showing_a_world_map.html"},{default:s(()=>[e("2.1 Showing a World Map")]),_:1}),e(" to manually experiment with changing this attribute.")]),G,t("p",null,[e("The introduction of the "),A,e(" function can be found in the "),a(o,{to:"/en/docs/4.2_ui_control.html"},{default:s(()=>[e("4.2 User Interface Control")]),_:1}),e(" document, please refer to it.")]),R,t("p",null,[e("Raster grids can also be used for visualization, and I believe the most common application of raster grids is to "),q,e(". The generation of a heat map is mainly achieved by modifying the value of each cell on the raster grid. If you are not familiar with the specific structure of raster grids, you can refer to the "),a(o,{to:"/en/docs/3.3_raster_grids.html"},{default:s(()=>[e("3.3 Raster Grids")]),_:1}),e(" document. For controlling raster grids using scripts, you can refer to the "),a(o,{to:"/en/docs/4.4_grids.html"},{default:s(()=>[e("4.4 Grids")]),_:1}),e(" document.")]),B,E,t("blockquote",null,[t("p",null,[e("This post is translated using ChatGPT, please "),t("a",M,[j,a(r)]),e(" if any omissions.")])])])}const O=x(I,[["render",D],["__file","visualization.html.vue"]]);export{O as default}; diff --git a/assets/visualization.html-skftd09s.js b/assets/visualization.html-skftd09s.js new file mode 100644 index 00000000..a4982c77 --- /dev/null +++ b/assets/visualization.html-skftd09s.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-385f9c3c","path":"/notes/visualization.html","title":"结果可视化","lang":"zh-CN","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,结果,可视化"}],["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/visualization.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/visualization.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"结果可视化"}],["meta",{"property":"og:description","content":"本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。 改变形状颜色 在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项: Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。; Lookup Table (#lookup-..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"结果可视化\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]],"description":"本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。 改变形状颜色 在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项: Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。; Lookup Table (#lookup-..."},"headers":[{"level":2,"title":"改变形状颜色","slug":"改变形状颜色","link":"#改变形状颜色","children":[{"level":3,"title":"Lookup Table 通过表中值改变颜色","slug":"lookup-table-通过表中值改变颜色","link":"#lookup-table-通过表中值改变颜色","children":[]},{"level":3,"title":"Graduated Color 根据值的大小显示渐变色","slug":"graduated-color-根据值的大小显示渐变色","link":"#graduated-color-根据值的大小显示渐变色","children":[]}]},{"level":2,"title":"更改图形和标签的显示大小","slug":"更改图形和标签的显示大小","link":"#更改图形和标签的显示大小","children":[{"level":3,"title":"参考系的选择","slug":"参考系的选择","link":"#参考系的选择","children":[]},{"level":3,"title":"参考系的设定","slug":"参考系的设定","link":"#参考系的设定","children":[]}]},{"level":2,"title":"更改显示的标签","slug":"更改显示的标签","link":"#更改显示的标签","children":[{"level":3,"title":"手动更改显示的标签","slug":"手动更改显示的标签","link":"#手动更改显示的标签","children":[]},{"level":3,"title":"自动更改显示的标签","slug":"自动更改显示的标签","link":"#自动更改显示的标签","children":[]}]},{"level":2,"title":"借助栅格图","slug":"借助栅格图","link":"#借助栅格图","children":[]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":9}]},"filePathRelative":"notes/visualization.md","autoDesc":true}');export{e as data}; diff --git a/assets/visualization.html-t9WbOvdj.js b/assets/visualization.html-t9WbOvdj.js new file mode 100644 index 00000000..d4ae3aef --- /dev/null +++ b/assets/visualization.html-t9WbOvdj.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-00ed9760","path":"/en/notes/visualization.html","title":"Visualization of Results","lang":"en-US","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,结果,可视化"}],["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/visualization.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/visualization.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Visualization of Results"}],["meta",{"property":"og:description","content":"This article introduces various methods for visualizing computational results. This includes changing the color of the content, changing the size of shapes, and changing the att..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Visualization of Results\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]],"description":"This article introduces various methods for visualizing computational results. This includes changing the color of the content, changing the size of shapes, and changing the att..."},"headers":[{"level":2,"title":"Changing Shape Color","slug":"changing-shape-color","link":"#changing-shape-color","children":[{"level":3,"title":"Lookup Table - Changing Color Based on Table Values","slug":"lookup-table-changing-color-based-on-table-values","link":"#lookup-table-changing-color-based-on-table-values","children":[]},{"level":3,"title":"Graduated Color - Displaying Gradient Color Based on Values","slug":"graduated-color-displaying-gradient-color-based-on-values","link":"#graduated-color-displaying-gradient-color-based-on-values","children":[]}]},{"level":2,"title":"Changing the Display Size of Shapes and Labels","slug":"changing-the-display-size-of-shapes-and-labels","link":"#changing-the-display-size-of-shapes-and-labels","children":[{"level":3,"title":"Selection of Reference System","slug":"selection-of-reference-system","link":"#selection-of-reference-system","children":[]},{"level":3,"title":"Setting the reference system","slug":"setting-the-reference-system","link":"#setting-the-reference-system","children":[]}]},{"level":2,"title":"Changing the displayed labels","slug":"changing-the-displayed-labels","link":"#changing-the-displayed-labels","children":[{"level":3,"title":"Manually changing the displayed labels","slug":"manually-changing-the-displayed-labels","link":"#manually-changing-the-displayed-labels","children":[]},{"level":3,"title":"Automatically changing the displayed labels","slug":"automatically-changing-the-displayed-labels","link":"#automatically-changing-the-displayed-labels","children":[]}]},{"level":2,"title":"Using Raster Grids","slug":"using-raster-grids","link":"#using-raster-grids","children":[]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/visualization.md","autoDesc":true}');export{e as data}; diff --git a/assets/visualization.html-xF8N-_EY.js b/assets/visualization.html-xF8N-_EY.js deleted file mode 100644 index ee3fbe59..00000000 --- a/assets/visualization.html-xF8N-_EY.js +++ /dev/null @@ -1 +0,0 @@ -const t=JSON.parse('{"key":"v-385f9c3c","path":"/notes/visualization.html","title":"结果可视化","lang":"zh-CN","frontmatter":{"head":[["meta",{"name":"keywords","content":"MicroCity,结果,可视化"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/visualization.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"结果可视化"}],["meta",{"property":"og:description","content":"本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。 改变形状颜色 在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项: Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。; Lookup Table (#lookup-..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2022-12-24T07:33:47.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"结果可视化"}],["meta",{"property":"article:modified_time","content":"2022-12-24T07:33:47.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"结果可视化\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2022-12-24T07:33:47.000Z\\",\\"author\\":[]}"]],"description":"本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。 改变形状颜色 在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项: Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。; Lookup Table (#lookup-..."},"headers":[{"level":2,"title":"改变形状颜色","slug":"改变形状颜色","link":"#改变形状颜色","children":[{"level":3,"title":"Lookup Table 通过表中值改变颜色","slug":"lookup-table-通过表中值改变颜色","link":"#lookup-table-通过表中值改变颜色","children":[]},{"level":3,"title":"Graduated Color 根据值的大小显示渐变色","slug":"graduated-color-根据值的大小显示渐变色","link":"#graduated-color-根据值的大小显示渐变色","children":[]}]},{"level":2,"title":"更改图形和标签的显示大小","slug":"更改图形和标签的显示大小","link":"#更改图形和标签的显示大小","children":[{"level":3,"title":"参考系的选择","slug":"参考系的选择","link":"#参考系的选择","children":[]},{"level":3,"title":"参考系的设定","slug":"参考系的设定","link":"#参考系的设定","children":[]}]},{"level":2,"title":"更改显示的标签","slug":"更改显示的标签","link":"#更改显示的标签","children":[{"level":3,"title":"手动更改显示的标签","slug":"手动更改显示的标签","link":"#手动更改显示的标签","children":[]},{"level":3,"title":"自动更改显示的标签","slug":"自动更改显示的标签","link":"#自动更改显示的标签","children":[]}]},{"level":2,"title":"借助栅格图","slug":"借助栅格图","link":"#借助栅格图","children":[]}],"git":{"updatedTime":1671867227000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":8}]},"filePathRelative":"notes/visualization.md","autoDesc":true}');export{t as data}; diff --git a/assets/warehouse-simulation.html-3NwF3MxT.js b/assets/warehouse-simulation.html-3NwF3MxT.js deleted file mode 100644 index 84919b36..00000000 --- a/assets/warehouse-simulation.html-3NwF3MxT.js +++ /dev/null @@ -1,32 +0,0 @@ -import{_ as o,r as p,o as c,c as r,a as s,b as a,d as n,w as i,e as t}from"./app-DaLjD81q.js";const u="/MicroCityNotes/assets/problem1-AJuFUHVQ.webp",m="/MicroCityNotes/assets/无预判障碍-p5itt-RJ.gif",d="/MicroCityNotes/assets/预判障碍-hw2PZ_-s.gif",h="/MicroCityNotes/assets/optimal_layout-bCy9JRge.webp",k="/MicroCityNotes/assets/8cargo-pBqp-1Yq.gif",g="/MicroCityNotes/assets/color5-PRdlG8aV.gif",b="/MicroCityNotes/assets/color8-KLKGFsL4.gif",_="/MicroCityNotes/assets/problem2-KunKgJbC.webp",x="/MicroCityNotes/assets/old-FpQSFo63.gif",y="/MicroCityNotes/assets/new-GF873AfJ.gif",v="/MicroCityNotes/assets/auto_test-ttcTMf95.webp",w="/MicroCityNotes/assets/test_layout-3LvNhD-0.webp",E="/MicroCityNotes/assets/3trend-e8Vz-nOo.webp",f="/MicroCityNotes/assets/6trend-tHF37BNC.webp",A="/MicroCityNotes/assets/sim-result-nEPKqIkR.webp",B="/MicroCityNotes/assets/6-1trend-iFlvvd90.webp",M={},q=t('

自动化仓库仿真思路

本文思路仅供参考,建议做出适当改进。

具体问题:基于元胞自动机的仓库仿真

Problem1

其中,出入库位置可以更改,叉车为AGV。

也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。

基本假设

  • 所有货架上的货物相同
  • 一个货架只放一个货物

因此,出库和入库可以看做完全相反的过程,所以此处只需要详细讨论出库的情况。即默认货架上本身就有货物。

总体实现思路

',10),C=s("ul",null,[s("li",null,[a("将整个 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"3"),s("mo",null,"×"),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"3\\times3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(" 的仓库中每个元胞的位置赋予 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mi",null,"y"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(x,y)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},")")])])]),a(" 坐标,方便后续的移动操作。")]),s("li",null,"以AGV为核心,对货架进行操作。AGV处于升起状态移动货架时,只需要将货架的坐标位置同步设为AGV的位置即可达到AGV移动货架的效果。")],-1),G=s("h4",{id:"业务流程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#业务流程","aria-hidden":"true"},"#"),a(" 业务流程")],-1),V=s("p",null,"先按照需求数量乱序生成订单列表,AGV根据订单顺序依次将货架移动到出库点进行出库操作。",-1),L=s("h4",{id:"业务逻辑",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#业务逻辑","aria-hidden":"true"},"#"),a(" 业务逻辑")],-1),N=s("p",null,"当执行出库时,AGV先找到最近的货架并移动到那个货架的位置,抬起货架。为货架(AGV)设定移动的终点,计算曼哈顿距离差值。",-1),F=s("ul",null,[s("li",null,[a("每次移动前都通过是否有障碍物判断货架移动的方向("),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"x")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])]),a(" 方向或 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"},"y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),a(" 方向)。")]),s("li",null,[a("如果两个方向都被堵塞,则优先选择 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"},"y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),a(" 方向(人为规定),将这个方向的障碍物递归移走,为货架移动腾出空间。如果 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"},"y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),a(" 方向没有空间才选择移动 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"x")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])]),a(" 方向。")])],-1),J=s("h3",{id:"过程优化-关于旧方法和新方法",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#过程优化-关于旧方法和新方法","aria-hidden":"true"},"#"),a(" 过程优化:关于旧方法和新方法")],-1),T=s("p",null,[a("这两种方法都是可用的方法,但是 "),s("strong",null,"新方法对特定场景进行了优化,通过对障碍进行预判减少了操作步骤。"),a(" 问题见下图")],-1),K=s("p",null,[s("strong",null,"旧方法:无障碍预判"),a("(进出货点在 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("mn",null,"3"),s("mo",{separator:"true"},","),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"x=3,y=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(" 的位置)")],-1),U=s("div",{style:{"text-align":"center"}},[s("p",null,[s("img",{src:m,alt:"旧方法效果动图"})])],-1),R=s("p",null,"👉 AGV完成第一个货架的出库后,向第二个货架移动,但是发现第一个货架挡住了去路,因此又回到第一个货架的位置将其移开,再回到第二个货架进行出库操作。",-1),P=s("p",null,[s("strong",null,"新方法:预判障碍"),a("(进出货点在 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("mn",null,"3"),s("mo",{separator:"true"},","),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"x=3,y=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(" 的位置)")],-1),j=t('

新方法效果动图

👉 AGV完成第一个货架的出库操作后判断后一个货架是否需要移动其他位置的货架才能到达出入库点。如果需要,则移动障碍货架后才前往后一个货架进行出库。

相关信息

本着尽量少占用出入库点的原则,当有空位时AGV将把在出入口的货架移走。因此某些看起来冗余的操作并非没有考虑全面。

不同数量货架对应的最优布局方案(动图) 8个货架的情况,上面已经进行了展示。下面仅展示表中货架数为5和7的情况。其他情况详见附件。

仿真数据收集分析

出入库效率最高

仿真结果如下图所示,表示相同货架数量下得到的效率最佳货架的货架布局

  • 最佳货架布局:相同货架数量下,取出所有货物操作次数(ticks)最小

布局图说明

  • 白色:没有放置货架
  • 浅灰色:货架,但是AGV一开始位于这个货架下方
  • 灰色:货架。

表格说明

  • 货架数量:存在于布局图中的货架数量
  • 旧ticks:使用旧方法(无预判障碍)实现取货的操作次数。
  • 新ticks:使用新方法(预判障碍)实现取货的操作次数。后面将对新方法进行说明。
  • 黄色高亮:相同布局下操作次数最少(ticks最小)的方案

最佳布局

空间利用率最大

如果所有位置都放置货架,则无法访问到所有货架。因此,空间利用率最大的方法是放置8个货架。

颜色说明

  • 绿色:有货物的货架
  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

有时候刷新太快可能看不出AGV抬起

进出货点在x=2,y=3的位置

8个货架动图

创新点

  • 额外考虑货物种类不同的情况。
  • 每次仿真会根据货架上的货物乱序生成需求。
  • 面向对象编程。使用面向对象的思想编程有助于将问题抽象化、有助于流程细节的改进;再加上好的命名方式会让整个程序的流程和逻辑清晰很多,不至于睡一觉起来就忘了😂

不同的货物类型用不同的颜色表示。AGV状态颜色、空货架的颜色、进出库点的颜色含义与之前相同。

  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

5个货架的情况示例

不同种类货物-5个货架

8个货架的情况示例

不同种类货物-8个货架

仿真改进:三维化自动仓库仿真

Problem2

在这一部分题目也稍微有所变化,要求将元胞自动机仿真仓库案例三维化,进行自动化仓库仿真。具体要求如上图。

总体思路

三维化

基于元胞自动机的仓库仿真为核心,将其中元胞自动机仿真的部分改写为内部数据表,作为内部数据模型,对整个仿真过程的状态进行监视和控制。

由于基于元胞自动机的仓库仿真使用了面向对象的方法封装对象,业务逻辑和流程的构建中大面积使用了对象方法,因此此处只需要改写对象方法(如 Agv:Move(dx, dy) 等)即可实现由元胞自动机仿真到三维化自动仓库的仿真。

如果程序整体结构设计优良,应用“面向对象”将会大幅提升程序的可维护性,降低移植难度。

对于AGV、货架直接套用现成模型;对于货物,只需要设置其距离货架的相对高度列表即可实现货物自动存放于指定高度。

',37),S={class:"hint-container tip"},z=s("p",{class:"hint-container-title"},"提示",-1),X=t('

出入库需求波动极大

  • 根据题目要求,基本上只存在有限的2种情况:3个货架、6个货架。
  • 由于货架数量情况有限,而基于元胞自动机的仓库仿真中得到了性能最佳的仓库布局,因此可以直接套用对应货架数量的最佳布局,本问题中只需要考虑固定货架布局下货物的位置摆放问题。
  • 对于3个货架的情况,其最佳布局属于高度对称的形态,距离出入库点的距离都为1,因此这种情况下只需要对1种情况进行仿真、收集其数据。
  • 对于6个货架的情况,选取了3种情况进行多次仿真,得到每种情况出入库耗费Ticks的平均值、最大值、最小值。

    当前Ticks是AGV移动的次数,相当于单位操作时间。后文改进空间中提到了可以进行的改进

  • 经过以上分析可以看出情况有限,因此可以通过控制货物需求总数不变,每次随机生成需求货物种类的方式对各种货物摆放位置进行仿真、对得到数据进行分析,最终确定最佳的货物布局方案。

改进

在测试的过程中发现原有移动货架的策略不合理,改进了移动货架的策略。

旧策略: 找到离AGV最近的装有需求货物的货架,将其移动到出入库点。

旧策略

可以看到AGV已经将需要出库的同种货物(青色方块)移动到了出入库点,但是由于AGV移动的货架对象是旁边的货架,因此没有对已经在出入库点的货物进行出库。

新策略: 找到离出入库点最近的装有需求货物的货架,将其移动到出入库点。改变策略后,没有发现以上提到的不合理情况出现。

新策略

创新

由于测试的次数较多,因此将主体流程写入函数并进行适应性改进,实现自动对所有情况进行仿真测试并将数据输出。下图为自动仿真测试运行为示例。

自动测试

自动仿真测试流程代码,仅供参考

-- 批量测试
-local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- 测试需求(上限)序列
-
-local output_string_list = {} -- 测试结果列表字符串
-for k, v in ipairs(cargo_ubs) do
-    local test_result = {} -- 本需求上限测试结果序列
-    cargo_ub = v -- 设置需求数量上限
-    for j = 1, test_count do
-        scene.setenv({
-            grid = 'plane',
-            clear = true
-        }) -- 清空场景内容
-
-        print("测试(", j, "/", test_count, "):需求数量为", cargo_ub)
-        local tick = ModelRun() -- 运行仿真模型返回测试结果
-        table.insert(test_result, tick) -- 将测试结果插入测试结果序列
-    end
-
-    local output_string = ""
-    print("需求数量为", cargo_ub, "的测试结果序列:")
-    for i = 1, #test_result do -- 输出测试结果序列到列表字符串
-        output_string = output_string .. test_result[i] .. "\\t"
-    end
-    print(output_string)
-    table.insert(output_string_list, output_string)
-end
-
--- 输出测试测试结果列表
-for i, str in ipairs(output_string_list) do
-    print("需求数量为", cargo_ubs[i], "的测试结果序列:", str)
-end
-

在自动仿真测试的过程中发现了BUG,详见下文说明。

货架布局方案

货架布局方案

颜色说明

  • 浅蓝色:出入库点
  • 白色:空格
  • 深蓝、红、黄:3种货物对应的颜色

条件假设

  • 每个货架上都放有2个同类货物
  • 货物需求随机,没有种类偏好
  • 每次只取出一个货物

仿真结果及分析

对每个货物布局方案中每种需求数量的情况仿真测试30次,求单方案结果中的最大值、最小值、平均值。最终得到结论为在6个货架的情况中,方案2的布局表现最优。

方案3:3个货架

方案3

方案6

方案6平均Ticks总趋势图 方案6平均Ticks总趋势图

方案6最优布局方案:方案2 方案6最优布局方案

还应绘制分方案的“需求量-最短平均服务时间”单位趋势图。以下以方案6-1为例,横坐标为货物需求数量,纵轴为最短平均服务时间(Ticks)。

方案6-1

改进空间

由于题目没有给定具体事件的执行时间,也没有指定时间单位,因此此处只计量货架的操作次数作为耗费的时间。也就是说,时间是后计算的,我想大部分同学做到这里可能都是这样的思路。虽然最终得出的结果没有问题,但是思路还可以转变一下,适应于后面的学习。

当前思路是以任务驱动的。虽然能够得到一个正确的结果,但是没有利用仿真时间,这种做法在只控制一个实体的时候不会出现问题。当要同时处理多个实体的时候,当前思路就无法做到同时操作多个实体完成任务,只能实现多个实体依次完成任务的情况。当前思路的具体流程如下:

',33),D=s("p",null,"由于应用的是时间推进法,因此仿真世界中有属于它自己的时间。对于我们来说,我们可以通过在仿真时间上乘一个倍率实现控制仿真速度,这个倍率就是仿真速度。此外,这种做法更加容易支持考虑多对象的情况。具体流程如下:",-1),I=s("p",null,"这样就改为了以时间为核心的仿真,在刷新任务执行进度的时候就可以直接刷新场景中的所有实体。由于仿真以时间为核心,因此就需要设定各种操作的速率/时间,保证时间计算的准确性。在MicroCityWeb中,有一些技巧可以用于时间推进法的仿真。",-1),Y=s("h4",{id:"使用系统时间更新仿真时间",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#使用系统时间更新仿真时间","aria-hidden":"true"},"#"),a(" 使用系统时间更新仿真时间")],-1),Q=s("code",null,"os.clock()",-1),Z=s("p",null,"由于整个仿真的核心为时间,因此需要对之前没有规定的操作规定其需要花费的时间长度。在改进的部分中,又额外考虑了以下操作所要花费的时间:",-1),H=s("ul",null,[s("li",null,"货物出入库所要花费的时间"),s("li",null,"AGV举起和降落货架所要花费的时间")],-1);function W(O,$){const e=p("RouterLink"),l=p("FlowChart");return c(),r("div",null,[q,C,G,V,L,N,F,J,T,K,U,R,P,j,s("div",S,[z,s("p",null,[a("如果需要套用现成模型,或者申请上传模型到本文作者维护的仓库,请参考文档 "),n(e,{to:"/notes/3d-objects.html#%E5%A4%96%E9%83%A8%E6%A8%A1%E5%9E%8B"},{default:i(()=>[a("3D对象-外部模型")]),_:1})])]),X,n(l,{id:"flowchart-475",code:"eJxLLUvNK7G1Ky5JLCqxUniye/fTroUvZ8x/2jGdCyyVnJ+XYmsHIjNLMvPzrBRe7J/xbE4nRCFXakVqsq1dfkFqUSJE9lnn8hcLe57unfy0sxeqJjElpSQzNxVF2Yt1C5+vm/6iYfqLLTufTd/2cvoWruLSXIiy1LwUK4Wn+6Y/7djwrGE3VBbiGF07uJsQrtOoTC3WyUlNK9EESgPdo2sHtRG76rx8naT8kpL8XKByqJ1cAJD+ePk=",preset:"vue"}),D,n(l,{id:"flowchart-479",code:"eJxLLUvNK7G1Ky5JLCqxUniye/fTroUvZ8x/2jGdCyyVnJ+XYmsHIjNLMvPzrBRe7J/xbE4nRCFXSWZuqq1dfkFqUSJUtm/70/5pT/dOftrZ+2z6tpfTt7zf0/GiofnFzIlPdu9/Pmf+y4b5T3cte7+nkyu1IjUZRe/Tju3Ppm2AmPysc/mLhT0v9s8GKuYqLs2FWJSalwJUtm/6044Nzxp2Q8zngrhT1w7uXITDNSpTi3VyUtNKNHXtQCYAFQEtxa40L18nKb+kJD8XqBZqIRcAJqKMLw==",preset:"vue"}),I,Y,s("p",null,[Q,a("函数可以获取系统当前的时间(以秒为单位,但是是小数)。有了这个函数就可以做到仿真与现实时间的同步。用法示例可以参考"),n(e,{to:"/notes/timelapse.html#%E4%B8%BB%E5%AF%BC%E6%97%B6%E9%92%9F%E6%8E%A8%E8%BF%9B%E6%B3%95"},{default:i(()=>[a("时间推进法")]),_:1})]),Z,H])}const as=o(M,[["render",W],["__file","warehouse-simulation.html.vue"]]);export{as as default}; diff --git a/assets/warehouse-simulation.html-5OK9wBKc.js b/assets/warehouse-simulation.html-5OK9wBKc.js new file mode 100644 index 00000000..7334b2ad --- /dev/null +++ b/assets/warehouse-simulation.html-5OK9wBKc.js @@ -0,0 +1,32 @@ +import{_ as o,a as c,b as r,c as u,d as m,e as d,f as h,g as k,h as g,i as _,j as x,k as b,l as v,m as y,n as E,o as w}from"./6-1trend-atJpgMOK.js";import{_ as A,r as p,o as f,c as B,a as s,b as a,d as n,w as i,e as t}from"./app-LOf__QKq.js";const q={},G=t('

自动化仓库仿真思路

本文思路仅供参考,建议做出适当改进。

具体问题:基于元胞自动机的仓库仿真

Problem1

其中,出入库位置可以更改,叉车为AGV。

也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。

基本假设

  • 所有货架上的货物相同
  • 一个货架只放一个货物

因此,出库和入库可以看做完全相反的过程,所以此处只需要详细讨论出库的情况。即默认货架上本身就有货物。

总体实现思路

',10),V=s("ul",null,[s("li",null,[a("将整个 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"3"),s("mo",null,"×"),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"3\\times3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"×"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(" 的仓库中每个元胞的位置赋予 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mo",{stretchy:"false"},"("),s("mi",null,"x"),s("mo",{separator:"true"},","),s("mi",null,"y"),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"},"(x,y)")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),s("span",{class:"mopen"},"("),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mclose"},")")])])]),a(" 坐标,方便后续的移动操作。")]),s("li",null,"以AGV为核心,对货架进行操作。AGV处于升起状态移动货架时,只需要将货架的坐标位置同步设为AGV的位置即可达到AGV移动货架的效果。")],-1),M=s("h4",{id:"业务流程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#业务流程","aria-hidden":"true"},"#"),a(" 业务流程")],-1),L=s("p",null,"先按照需求数量乱序生成订单列表,AGV根据订单顺序依次将货架移动到出库点进行出库操作。",-1),F=s("h4",{id:"业务逻辑",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#业务逻辑","aria-hidden":"true"},"#"),a(" 业务逻辑")],-1),C=s("p",null,"当执行出库时,AGV先找到最近的货架并移动到那个货架的位置,抬起货架。为货架(AGV)设定移动的终点,计算曼哈顿距离差值。",-1),T=s("ul",null,[s("li",null,[a("每次移动前都通过是否有障碍物判断货架移动的方向("),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"x")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])]),a(" 方向或 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"},"y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),a(" 方向)。")]),s("li",null,[a("如果两个方向都被堵塞,则优先选择 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"},"y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),a(" 方向(人为规定),将这个方向的障碍物递归移走,为货架移动腾出空间。如果 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"},"y")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),a(" 方向没有空间才选择移动 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x")]),s("annotation",{encoding:"application/x-tex"},"x")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x")])])]),a(" 方向。")])],-1),J=s("h3",{id:"过程优化-关于旧方法和新方法",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#过程优化-关于旧方法和新方法","aria-hidden":"true"},"#"),a(" 过程优化:关于旧方法和新方法")],-1),U=s("p",null,[a("这两种方法都是可用的方法,但是 "),s("strong",null,"新方法对特定场景进行了优化,通过对障碍进行预判减少了操作步骤。"),a(" 问题见下图")],-1),N=s("p",null,[s("strong",null,"旧方法:无障碍预判"),a("(进出货点在 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("mn",null,"3"),s("mo",{separator:"true"},","),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"x=3,y=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(" 的位置)")],-1),j=s("div",{style:{"text-align":"center"}},[s("p",null,[s("img",{src:o,alt:"旧方法效果动图"})])],-1),K=s("p",null,"👉 AGV完成第一个货架的出库后,向第二个货架移动,但是发现第一个货架挡住了去路,因此又回到第一个货架的位置将其移开,再回到第二个货架进行出库操作。",-1),P=s("p",null,[s("strong",null,"新方法:预判障碍"),a("(进出货点在 "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"x"),s("mo",null,"="),s("mn",null,"3"),s("mo",{separator:"true"},","),s("mi",null,"y"),s("mo",null,"="),s("mn",null,"3")]),s("annotation",{encoding:"application/x-tex"},"x=3,y=3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.4306em"}}),s("span",{class:"mord mathnormal"},"x"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"3"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"3")])])]),a(" 的位置)")],-1),R=t('

新方法效果动图

👉 AGV完成第一个货架的出库操作后判断后一个货架是否需要移动其他位置的货架才能到达出入库点。如果需要,则移动障碍货架后才前往后一个货架进行出库。

相关信息

本着尽量少占用出入库点的原则,当有空位时AGV将把在出入口的货架移走。因此某些看起来冗余的操作并非没有考虑全面。

不同数量货架对应的最优布局方案(动图) 8个货架的情况,上面已经进行了展示。下面仅展示表中货架数为5和7的情况。其他情况详见附件。

仿真数据收集分析

出入库效率最高

仿真结果如下图所示,表示相同货架数量下得到的效率最佳货架的货架布局

  • 最佳货架布局:相同货架数量下,取出所有货物操作次数(ticks)最小

布局图说明

  • 白色:没有放置货架
  • 浅灰色:货架,但是AGV一开始位于这个货架下方
  • 灰色:货架。

表格说明

  • 货架数量:存在于布局图中的货架数量
  • 旧ticks:使用旧方法(无预判障碍)实现取货的操作次数。
  • 新ticks:使用新方法(预判障碍)实现取货的操作次数。后面将对新方法进行说明。
  • 黄色高亮:相同布局下操作次数最少(ticks最小)的方案

最佳布局

空间利用率最大

如果所有位置都放置货架,则无法访问到所有货架。因此,空间利用率最大的方法是放置8个货架。

颜色说明

  • 绿色:有货物的货架
  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

有时候刷新太快可能看不出AGV抬起

进出货点在x=2,y=3的位置

8个货架动图

创新点

  • 额外考虑货物种类不同的情况。
  • 每次仿真会根据货架上的货物乱序生成需求。
  • 面向对象编程。使用面向对象的思想编程有助于将问题抽象化、有助于流程细节的改进;再加上好的命名方式会让整个程序的流程和逻辑清晰很多,不至于睡一觉起来就忘了😂

不同的货物类型用不同的颜色表示。AGV状态颜色、空货架的颜色、进出库点的颜色含义与之前相同。

  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

5个货架的情况示例

不同种类货物-5个货架

8个货架的情况示例

不同种类货物-8个货架

仿真改进:三维化自动仓库仿真

Problem2

在这一部分题目也稍微有所变化,要求将元胞自动机仿真仓库案例三维化,进行自动化仓库仿真。具体要求如上图。

总体思路

三维化

基于元胞自动机的仓库仿真为核心,将其中元胞自动机仿真的部分改写为内部数据表,作为内部数据模型,对整个仿真过程的状态进行监视和控制。

由于基于元胞自动机的仓库仿真使用了面向对象的方法封装对象,业务逻辑和流程的构建中大面积使用了对象方法,因此此处只需要改写对象方法(如 Agv:Move(dx, dy) 等)即可实现由元胞自动机仿真到三维化自动仓库的仿真。

如果程序整体结构设计优良,应用“面向对象”将会大幅提升程序的可维护性,降低移植难度。

对于AGV、货架直接套用现成模型;对于货物,只需要设置其距离货架的相对高度列表即可实现货物自动存放于指定高度。

',37),S={class:"hint-container tip"},X=s("p",{class:"hint-container-title"},"提示",-1),z=t('

出入库需求波动极大

  • 根据题目要求,基本上只存在有限的2种情况:3个货架、6个货架。
  • 由于货架数量情况有限,而基于元胞自动机的仓库仿真中得到了性能最佳的仓库布局,因此可以直接套用对应货架数量的最佳布局,本问题中只需要考虑固定货架布局下货物的位置摆放问题。
  • 对于3个货架的情况,其最佳布局属于高度对称的形态,距离出入库点的距离都为1,因此这种情况下只需要对1种情况进行仿真、收集其数据。
  • 对于6个货架的情况,选取了3种情况进行多次仿真,得到每种情况出入库耗费Ticks的平均值、最大值、最小值。

    当前Ticks是AGV移动的次数,相当于单位操作时间。后文改进空间中提到了可以进行的改进

  • 经过以上分析可以看出情况有限,因此可以通过控制货物需求总数不变,每次随机生成需求货物种类的方式对各种货物摆放位置进行仿真、对得到数据进行分析,最终确定最佳的货物布局方案。

改进

在测试的过程中发现原有移动货架的策略不合理,改进了移动货架的策略。

旧策略: 找到离AGV最近的装有需求货物的货架,将其移动到出入库点。

旧策略

可以看到AGV已经将需要出库的同种货物(青色方块)移动到了出入库点,但是由于AGV移动的货架对象是旁边的货架,因此没有对已经在出入库点的货物进行出库。

新策略: 找到离出入库点最近的装有需求货物的货架,将其移动到出入库点。改变策略后,没有发现以上提到的不合理情况出现。

新策略

创新

由于测试的次数较多,因此将主体流程写入函数并进行适应性改进,实现自动对所有情况进行仿真测试并将数据输出。下图为自动仿真测试运行为示例。

自动测试

自动仿真测试流程代码,仅供参考

-- 批量测试
+local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- 测试需求(上限)序列
+
+local output_string_list = {} -- 测试结果列表字符串
+for k, v in ipairs(cargo_ubs) do
+    local test_result = {} -- 本需求上限测试结果序列
+    cargo_ub = v -- 设置需求数量上限
+    for j = 1, test_count do
+        scene.setenv({
+            grid = 'plane',
+            clear = true
+        }) -- 清空场景内容
+
+        print("测试(", j, "/", test_count, "):需求数量为", cargo_ub)
+        local tick = ModelRun() -- 运行仿真模型返回测试结果
+        table.insert(test_result, tick) -- 将测试结果插入测试结果序列
+    end
+
+    local output_string = ""
+    print("需求数量为", cargo_ub, "的测试结果序列:")
+    for i = 1, #test_result do -- 输出测试结果序列到列表字符串
+        output_string = output_string .. test_result[i] .. "\\t"
+    end
+    print(output_string)
+    table.insert(output_string_list, output_string)
+end
+
+-- 输出测试测试结果列表
+for i, str in ipairs(output_string_list) do
+    print("需求数量为", cargo_ubs[i], "的测试结果序列:", str)
+end
+

在自动仿真测试的过程中发现了BUG,详见下文说明。

货架布局方案

货架布局方案

颜色说明

  • 浅蓝色:出入库点
  • 白色:空格
  • 深蓝、红、黄:3种货物对应的颜色

条件假设

  • 每个货架上都放有2个同类货物
  • 货物需求随机,没有种类偏好
  • 每次只取出一个货物

仿真结果及分析

对每个货物布局方案中每种需求数量的情况仿真测试30次,求单方案结果中的最大值、最小值、平均值。最终得到结论为在6个货架的情况中,方案2的布局表现最优。

方案3:3个货架

方案3

方案6

方案6平均Ticks总趋势图 方案6平均Ticks总趋势图

方案6最优布局方案:方案2 方案6最优布局方案

还应绘制分方案的“需求量-最短平均服务时间”单位趋势图。以下以方案6-1为例,横坐标为货物需求数量,纵轴为最短平均服务时间(Ticks)。

方案6-1

改进空间

由于题目没有给定具体事件的执行时间,也没有指定时间单位,因此此处只计量货架的操作次数作为耗费的时间。也就是说,时间是后计算的,我想大部分同学做到这里可能都是这样的思路。虽然最终得出的结果没有问题,但是思路还可以转变一下,适应于后面的学习。

当前思路是以任务驱动的。虽然能够得到一个正确的结果,但是没有利用仿真时间,这种做法在只控制一个实体的时候不会出现问题。当要同时处理多个实体的时候,当前思路就无法做到同时操作多个实体完成任务,只能实现多个实体依次完成任务的情况。当前思路的具体流程如下:

',33),D=s("p",null,"由于应用的是时间推进法,因此仿真世界中有属于它自己的时间。对于我们来说,我们可以通过在仿真时间上乘一个倍率实现控制仿真速度,这个倍率就是仿真速度。此外,这种做法更加容易支持考虑多对象的情况。具体流程如下:",-1),I=s("p",null,"这样就改为了以时间为核心的仿真,在刷新任务执行进度的时候就可以直接刷新场景中的所有实体。由于仿真以时间为核心,因此就需要设定各种操作的速率/时间,保证时间计算的准确性。在MicroCityWeb中,有一些技巧可以用于时间推进法的仿真。",-1),Y=s("h4",{id:"使用系统时间更新仿真时间",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#使用系统时间更新仿真时间","aria-hidden":"true"},"#"),a(" 使用系统时间更新仿真时间")],-1),W=s("code",null,"os.clock()",-1),Z=s("p",null,"由于整个仿真的核心为时间,因此需要对之前没有规定的操作规定其需要花费的时间长度。在改进的部分中,又额外考虑了以下操作所要花费的时间:",-1),Q=s("ul",null,[s("li",null,"货物出入库所要花费的时间"),s("li",null,"AGV举起和降落货架所要花费的时间")],-1);function H(O,$){const e=p("RouterLink"),l=p("FlowChart");return f(),B("div",null,[G,V,M,L,F,C,T,J,U,N,j,K,P,R,s("div",S,[X,s("p",null,[a("如果需要套用现成模型,或者申请上传模型到本文作者维护的仓库,请参考文档 "),n(e,{to:"/notes/3d-objects.html#%E5%A4%96%E9%83%A8%E6%A8%A1%E5%9E%8B"},{default:i(()=>[a("3D对象-外部模型")]),_:1})])]),z,n(l,{id:"flowchart-475",code:"eJxLLUvNK7G1Ky5JLCqxUniye/fTroUvZ8x/2jGdCyyVnJ+XYmsHIjNLMvPzrBRe7J/xbE4nRCFXakVqsq1dfkFqUSJE9lnn8hcLe57unfy0sxeqJjElpSQzNxVF2Yt1C5+vm/6iYfqLLTufTd/2cvoWruLSXIiy1LwUK4Wn+6Y/7djwrGE3VBbiGF07uJsQrtOoTC3WyUlNK9EESgPdo2sHtRG76rx8naT8kpL8XKByqJ1cAJD+ePk=",preset:"vue"}),D,n(l,{id:"flowchart-479",code:"eJxLLUvNK7G1Ky5JLCqxUniye/fTroUvZ8x/2jGdCyyVnJ+XYmsHIjNLMvPzrBRe7J/xbE4nRCFXSWZuqq1dfkFqUSJUtm/70/5pT/dOftrZ+2z6tpfTt7zf0/GiofnFzIlPdu9/Pmf+y4b5T3cte7+nkyu1IjUZRe/Tju3Ppm2AmPysc/mLhT0v9s8GKuYqLs2FWJSalwJUtm/6044Nzxp2Q8zngrhT1w7uXITDNSpTi3VyUtNKNHXtQCYAFQEtxa40L18nKb+kJD8XqBZqIRcAJqKMLw==",preset:"vue"}),I,Y,s("p",null,[W,a("函数可以获取系统当前的时间(以秒为单位,但是是小数)。有了这个函数就可以做到仿真与现实时间的同步。用法示例可以参考"),n(e,{to:"/notes/timelapse.html#%E4%B8%BB%E5%AF%BC%E6%97%B6%E9%92%9F%E6%8E%A8%E8%BF%9B%E6%B3%95"},{default:i(()=>[a("时间推进法")]),_:1})]),Z,Q])}const ns=A(q,[["render",H],["__file","warehouse-simulation.html.vue"]]);export{ns as default}; diff --git a/assets/warehouse-simulation.html-6ARLBksA.js b/assets/warehouse-simulation.html-6ARLBksA.js new file mode 100644 index 00000000..8cf0ab8e --- /dev/null +++ b/assets/warehouse-simulation.html-6ARLBksA.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-716da5ad","path":"/en/notes/warehouse-simulation.html","title":"Ideas for Warehouse Automation Simulation","lang":"en-US","frontmatter":{"description":"The ideas in this article are for reference only and it is recommended to make appropriate improvements. Specific Problem: Warehouse Simulation based on Cellular Automata Proble...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/warehouse-simulation.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/warehouse-simulation.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Ideas for Warehouse Automation Simulation"}],["meta",{"property":"og:description","content":"The ideas in this article are for reference only and it is recommended to make appropriate improvements. Specific Problem: Warehouse Simulation based on Cellular Automata Proble..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-27T04:37:02.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-27T04:37:02.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Ideas for Warehouse Automation Simulation\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-27T04:37:02.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Specific Problem: Warehouse Simulation based on Cellular Automata","slug":"specific-problem-warehouse-simulation-based-on-cellular-automata","link":"#specific-problem-warehouse-simulation-based-on-cellular-automata","children":[{"level":3,"title":"Basic Assumptions","slug":"basic-assumptions","link":"#basic-assumptions","children":[]},{"level":3,"title":"Overall Implementation Idea","slug":"overall-implementation-idea","link":"#overall-implementation-idea","children":[]},{"level":3,"title":"Process Optimization: About the Old Method and the New Method","slug":"process-optimization-about-the-old-method-and-the-new-method","link":"#process-optimization-about-the-old-method-and-the-new-method","children":[]},{"level":3,"title":"Collection and Analysis of Simulation Data","slug":"collection-and-analysis-of-simulation-data","link":"#collection-and-analysis-of-simulation-data","children":[]},{"level":3,"title":"Innovations","slug":"innovations","link":"#innovations","children":[]}]},{"level":2,"title":"Simulation Enhancement: 3D Automated Warehouse Simulation","slug":"simulation-enhancement-3d-automated-warehouse-simulation","link":"#simulation-enhancement-3d-automated-warehouse-simulation","children":[{"level":3,"title":"Overall Approach","slug":"overall-approach","link":"#overall-approach","children":[]},{"level":3,"title":"Enhancements","slug":"enhancements","link":"#enhancements","children":[]},{"level":3,"title":"Innovation","slug":"innovation","link":"#innovation","children":[]},{"level":3,"title":"Shelf Layout Scheme","slug":"shelf-layout-scheme","link":"#shelf-layout-scheme","children":[]},{"level":3,"title":"Simulation Results and Analysis","slug":"simulation-results-and-analysis","link":"#simulation-results-and-analysis","children":[]},{"level":3,"title":"Improvement Space","slug":"improvement-space","link":"#improvement-space","children":[]}]}],"git":{"updatedTime":1701059822000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/warehouse-simulation.md","autoDesc":true}');export{e as data}; diff --git a/assets/warehouse-simulation.html-GfcmApNM.js b/assets/warehouse-simulation.html-GfcmApNM.js deleted file mode 100644 index 276d0cd8..00000000 --- a/assets/warehouse-simulation.html-GfcmApNM.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-187abc41","path":"/notes/warehouse-simulation.html","title":"自动化仓库仿真思路","lang":"zh-CN","frontmatter":{"description":"本文思路仅供参考,建议做出适当改进。 具体问题:基于元胞自动机的仓库仿真 Problem1 其中,出入库位置可以更改,叉车为AGV。 也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。 基本假设 所有货架上的货物相同; 一个货架只放一个货物; 因此,出库和入库可以看做完全相反的...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/warehouse-simulation.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"自动化仓库仿真思路"}],["meta",{"property":"og:description","content":"本文思路仅供参考,建议做出适当改进。 具体问题:基于元胞自动机的仓库仿真 Problem1 其中,出入库位置可以更改,叉车为AGV。 也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。 基本假设 所有货架上的货物相同; 一个货架只放一个货物; 因此,出库和入库可以看做完全相反的..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-05-21T08:42:49.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"自动化仓库仿真思路"}],["meta",{"property":"article:modified_time","content":"2023-05-21T08:42:49.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"自动化仓库仿真思路\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-05-21T08:42:49.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"具体问题:基于元胞自动机的仓库仿真","slug":"具体问题-基于元胞自动机的仓库仿真","link":"#具体问题-基于元胞自动机的仓库仿真","children":[{"level":3,"title":"基本假设","slug":"基本假设","link":"#基本假设","children":[]},{"level":3,"title":"总体实现思路","slug":"总体实现思路","link":"#总体实现思路","children":[]},{"level":3,"title":"过程优化:关于旧方法和新方法","slug":"过程优化-关于旧方法和新方法","link":"#过程优化-关于旧方法和新方法","children":[]},{"level":3,"title":"仿真数据收集分析","slug":"仿真数据收集分析","link":"#仿真数据收集分析","children":[]},{"level":3,"title":"创新点","slug":"创新点","link":"#创新点","children":[]}]},{"level":2,"title":"仿真改进:三维化自动仓库仿真","slug":"仿真改进-三维化自动仓库仿真","link":"#仿真改进-三维化自动仓库仿真","children":[{"level":3,"title":"总体思路","slug":"总体思路","link":"#总体思路","children":[]},{"level":3,"title":"改进","slug":"改进","link":"#改进","children":[]},{"level":3,"title":"创新","slug":"创新","link":"#创新","children":[]},{"level":3,"title":"货架布局方案","slug":"货架布局方案","link":"#货架布局方案","children":[]},{"level":3,"title":"仿真结果及分析","slug":"仿真结果及分析","link":"#仿真结果及分析","children":[]},{"level":3,"title":"改进空间","slug":"改进空间","link":"#改进空间","children":[]}]}],"git":{"updatedTime":1684658569000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/warehouse-simulation.md","autoDesc":true}');export{e as data}; diff --git a/assets/warehouse-simulation.html-I2Ep6WY5.js b/assets/warehouse-simulation.html-I2Ep6WY5.js new file mode 100644 index 00000000..174ef8e1 --- /dev/null +++ b/assets/warehouse-simulation.html-I2Ep6WY5.js @@ -0,0 +1,32 @@ +import{_ as c,a as p,b as h,c as u,d as m,e as d,f,g,h as k,i as b,j as y,k as v,l as w,m as x,n as _,o as A}from"./6-1trend-atJpgMOK.js";import{_ as q,r as a,o as S,c as T,a as e,b as t,d as s,w as l,e as n}from"./app-LOf__QKq.js";const M={},I=n('

Ideas for Warehouse Automation Simulation

The ideas in this article are for reference only and it is recommended to make appropriate improvements.

Specific Problem: Warehouse Simulation based on Cellular Automata

Problem1

In this problem, the locations of inbound and outbound can be changed, and the forklift is an AGV.

In other words, this is actually a cellular automata simulation of a mobile rack warehouse. The AGV can pass through the bottom of the rack, move to the bottom of the rack, lift the rack, and transport it to the inbound/outbound point.

Basic Assumptions

  • All items on the racks are the same.
  • Only one item is placed on each rack.

Therefore, outbound and inbound can be considered as completely opposite processes, so here we only need to discuss the outbound case in detail. It is assumed that there is already an item on the rack by default.

Overall Implementation Idea

',10),G=e("ul",null,[e("li",null,[t("Assign "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mo",{stretchy:"false"},"("),e("mi",null,"x"),e("mo",{separator:"true"},","),e("mi",null,"y"),e("mo",{stretchy:"false"},")")]),e("annotation",{encoding:"application/x-tex"},"(x, y)")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"1em","vertical-align":"-0.25em"}}),e("span",{class:"mopen"},"("),e("span",{class:"mord mathnormal"},"x"),e("span",{class:"mpunct"},","),e("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),e("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),e("span",{class:"mclose"},")")])])]),t(" coordinates to each cell in the entire "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mn",null,"3"),e("mo",null,"×"),e("mn",null,"3")]),e("annotation",{encoding:"application/x-tex"},"3\\times3")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),e("span",{class:"mord"},"3"),e("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),e("span",{class:"mbin"},"×"),e("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.6444em"}}),e("span",{class:"mord"},"3")])])]),t(" warehouse to facilitate subsequent movement operations.")]),e("li",null,"With AGV as the core, operate the racks. When the AGV is in the lifted state and moves the rack, you only need to synchronize the coordinate position of the rack with the position of the AGV to achieve the effect of AGV moving the rack.")],-1),B=e("h4",{id:"business-process",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#business-process","aria-hidden":"true"},"#"),t(" Business Process")],-1),E=e("p",null,"Randomly generate the order list according to the required quantity, and the AGV moves the racks to the outbound point in order based on the order list.",-1),V=e("h4",{id:"business-logic",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#business-logic","aria-hidden":"true"},"#"),t(" Business Logic")],-1),O=e("p",null,"When performing outbound, the AGV first finds the nearest rack and moves to the position of that rack, lifts the rack. For the rack (AGV), set the destination for movement and calculate the difference in Manhattan distance.",-1),L=e("ul",null,[e("li",null,[t("Before each movement, determine the direction of rack movement ("),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"x")]),e("annotation",{encoding:"application/x-tex"},"x")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.4306em"}}),e("span",{class:"mord mathnormal"},"x")])])]),t(" or "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"y")]),e("annotation",{encoding:"application/x-tex"},"y")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),e("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),t(" direction) by checking for obstacles.")]),e("li",null,[t("If both directions are blocked, prioritize the "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"y")]),e("annotation",{encoding:"application/x-tex"},"y")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),e("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),t(" direction (as specified) and recursively move away the obstacles in this direction to make space for the rack to move. If there is no space in the "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"y")]),e("annotation",{encoding:"application/x-tex"},"y")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.625em","vertical-align":"-0.1944em"}}),e("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])]),t(" direction, then move in the "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"x")]),e("annotation",{encoding:"application/x-tex"},"x")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.4306em"}}),e("span",{class:"mord mathnormal"},"x")])])]),t(" direction.")])],-1),D=e("h3",{id:"process-optimization-about-the-old-method-and-the-new-method",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#process-optimization-about-the-old-method-and-the-new-method","aria-hidden":"true"},"#"),t(" Process Optimization: About the Old Method and the New Method")],-1),z=e("p",null,[t("Both of these methods are viable, but the "),e("strong",null,"new method optimizes for specific scenarios by reducing the number of steps through obstacle prediction"),t(". See the problem in the figure below:")],-1),C=e("p",null,[e("strong",null,"Old Method: No Obstacle Prediction"),t(" (Inbound and outbound points are at position "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"x"),e("mo",null,"="),e("mn",null,"3"),e("mo",{separator:"true"},","),e("mi",null,"y"),e("mo",null,"="),e("mn",null,"3")]),e("annotation",{encoding:"application/x-tex"},"x=3,y=3")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.4306em"}}),e("span",{class:"mord mathnormal"},"x"),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),e("span",{class:"mrel"},"="),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),e("span",{class:"mord"},"3"),e("span",{class:"mpunct"},","),e("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),e("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),e("span",{class:"mrel"},"="),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.6444em"}}),e("span",{class:"mord"},"3")])])]),t(")")],-1),j=e("div",{style:{"text-align":"center"}},[e("p",null,[e("img",{src:c,alt:"Effect of the old method"})])],-1),F=e("p",null,"👉 After the AGV completes the outbound operation for the first rack and moves towards the second rack, it finds that the first rack blocks the way, so it goes back to move the first rack away, and then proceeds to do the outbound operation for the second rack.",-1),R=e("p",null,[e("strong",null,"New Method: Obstacle Prediction"),t(" (Inbound and outbound points are at position "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mi",null,"x"),e("mo",null,"="),e("mn",null,"3"),e("mo",{separator:"true"},","),e("mi",null,"y"),e("mo",null,"="),e("mn",null,"3")]),e("annotation",{encoding:"application/x-tex"},"x=3,y=3")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.4306em"}}),e("span",{class:"mord mathnormal"},"x"),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),e("span",{class:"mrel"},"="),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),e("span",{class:"mord"},"3"),e("span",{class:"mpunct"},","),e("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),e("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),e("span",{class:"mrel"},"="),e("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.6444em"}}),e("span",{class:"mord"},"3")])])]),t(")")],-1),N=n('

Effect of the new method

👉 After the AGV completes the outbound operation for the first rack, it checks if other racks need to be moved before it can reach the inbound/outbound point. If necessary, it moves the obstructed racks and then proceeds to do the outbound operation for the next rack.

Info

In line with the principle of minimizing the occupation of the inbound/outbound points, when there is an empty space, the AGV will move the rack at the inbound/outbound point. Therefore, some seemingly redundant operations are not without comprehensive considerations.

Optimal layout schemes for different numbers of racks (animated graphics) The case with 8 racks has already been shown above. Here, we only show the cases with 5 and 7 racks from the table. For other cases, please refer to the appendix.

Collection and Analysis of Simulation Data

Maximum Inbound/Outbound Efficiency

The simulation results are shown in the figure below, representing the layout of racks with the best efficiency for the same number of racks.

  • Optimal rack layout: For the same number of racks, the layout with the minimum number of operations (ticks) to retrieve all items.

Explanation of the Layout Diagram

  • White: No rack is placed.
  • Light gray: Rack, but the AGV is initially positioned below this rack.
  • Gray: Rack.

Explanation of the Table

  • Rack Quantity: Number of racks in the layout diagram.
  • Old Ticks: Number of operations to retrieve items using the old method (no obstacle prediction).
  • New Ticks: Number of operations to retrieve items using the new method (with obstacle prediction). The new method will be explained later.
  • Highlighted in yellow: Scheme with the minimum number of operations (minimum ticks) in the same layout.

Optimal Layout

Maximum Space Utilization

If all positions are filled with racks, it will not be possible to access all racks. Therefore, the method with the highest space utilization is to place 8 racks.

Color Indications

  • Green: Rack with items.
  • Purple: Rack without items.
  • Light purple: Rack lifted by the AGV.
  • Dark purple: AGV below this rack, but the rack is not lifted.
  • Dark gray: Inbound/outbound points.

Sometimes, when the refresh rate is too fast, it may not be possible to see the rack being lifted by the AGV.

The entry and exit points are located at position x=2, y=3.

8 cargo shelves animation

Innovations

  • Additional consideration for different types of goods.
  • Each simulation generates demand based on the random arrangement of goods on the shelves.
  • Object-oriented programming. Using an object-oriented approach helps in abstracting the problem and improving the flow of the process. Good naming conventions make the program's logic and flow clear, ensuring that you won't forget everything after a night's sleep 😂

Different types of goods are represented by different colors. The meaning of AGV state colors, empty shelf colors, and entry/exit point colors remains the same.

  • Purple: Shelf without goods
  • Light purple: Shelf lifted by AGV
  • Dark purple: AGV is positioned beneath the shelf but hasn't lifted it
  • Dark gray: Entry/exit point

Example with 5 shelves:

Different types of goods - 5 shelves

Example with 8 shelves:

Different types of goods - 8 shelves

Simulation Enhancement: 3D Automated Warehouse Simulation

Problem2

In this part, the question has slightly changed. The requirement is to add a third dimension to the cellular automaton warehouse simulation and create a simulation of an automated warehouse. The specific requirement is shown in the image above.

Overall Approach

Adding the Third Dimension

Based on the core of the Cellular Automaton-based Warehouse Simulation, the part of the simulation that uses cellular automata will be rewritten as an internal data table to serve as an internal data model, monitoring and controlling the state of the entire simulation process.

Since the Cellular Automaton-based Warehouse Simulation uses an object-oriented approach to encapsulate objects, and object methods are extensively used in building the business logic and flow, only the object methods need to be rewritten (e.g., Agv:Move(dx, dy)) to achieve the transition from cellular automaton simulation to 3D automated warehouse simulation.

If the overall program structure is well-designed, applying "object-oriented" techniques will significantly improve maintainability and reduce the difficulty of migration.

The AGV and shelf models can be directly reused. For the goods, you only need to set the relative height list from the shelves to achieve automatic placement of goods at the specified height.

',37),P={class:"hint-container tip"},Q=e("p",{class:"hint-container-title"},"Tips",-1),W=n('

Significant Fluctuation in the Demand for Inbound and Outbound Goods

  • According to the requirements, there are basically only two scenarios: 3 shelves and 6 shelves.
  • Since the number of shelves is limited and the Cellular Automaton-based Warehouse Simulation has obtained the best layout for warehouse performance, the corresponding optimal layouts for the respective number of shelves can be directly reused. In this problem, only the placement of goods in fixed shelf layouts needs to be considered.
  • For the case of 3 shelves, the optimal layout is a symmetrical configuration in terms of height, with a distance of 1 from the entry/exit point. Therefore, only one scenario needs to be simulated, and the data collected from it.
  • For the case of 6 shelves, three scenarios were selected for multiple simulations to obtain the average, maximum, and minimum Ticks consumed by each scenario for inbound and outbound operations.

    Ticks represents the number of times the AGV moves and serves as a unit of operation time. Further improvements are mentioned in the following section: Areas for Enhancement.

  • Based on the above analysis, since there are limited scenarios, the best layout for goods can be determined by simulating the placement of goods at various positions, randomizing the types of demanded goods while keeping the total demand constant, and analyzing the obtained data.

Enhancements

During testing, it was found that the original strategy of moving shelves was not reasonable. Therefore, the shelf movement strategy was improved.

Old Strategy: Find the shelf closest to the AGV that contains the requested goods and move it to the entry/exit point.

Old Strategy

As seen in the animation, the AGV has moved the shelf containing the required goods (represented by blue blocks) to the entry/exit point. However, because the AGV moves the shelf adjacent to the one with the requested goods, it doesn't perform the outbound operation on the goods already at the entry/exit point.

New Strategy: Find the shelf closest to the entry/exit point that contains the requested goods and move it to the entry/exit point. By changing the strategy, the aforementioned issue has been resolved.

New Strategy

Innovation

Due to the large number of tests, the main process is written into a function for adaptive improvement, achieving automatic simulation tests for all cases and outputting data. The following figure is an example of running the automatic simulation test.

Automatic Test

Code for the automatic simulation test process, for reference only:

-- Batch test
+local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- Test demands (upper limit) sequence
+
+local output_string_list = {} -- List of test result strings
+for k, v in ipairs(cargo_ubs) do
+    local test_result = {} -- Test result sequence for this demand upper limit
+    cargo_ub = v -- Set the quantity upper limit
+    for j = 1, test_count do
+        scene.setenv({
+            grid = 'plane',
+            clear = true
+        }) -- Clear the scene
+
+        print("Test (", j, "/", test_count, "): Demand quantity is", cargo_ub)
+        local tick = ModelRun() -- Run the simulation model and return the test result
+        table.insert(test_result, tick) -- Insert the test result into the test result sequence
+    end
+
+    local output_string = ""
+    print("Test result sequence for demand quantity", cargo_ub, ":")
+    for i = 1, #test_result do -- Output the test result sequence to the list string
+        output_string = output_string .. test_result[i] .. "\\t"
+    end
+    print(output_string)
+    table.insert(output_string_list, output_string)
+end
+
+-- Output the list of test results
+for i, str in ipairs(output_string_list) do
+    print("Test result sequence for demand quantity", cargo_ubs[i], ":", str)
+end
+

A bug was discovered during the automatic simulation test process, as described in the following text.

Shelf Layout Scheme

Shelf Layout Scheme

Color Legend

  • Light Blue: Inbound and outbound points
  • White: Empty space
  • Dark Blue, Red, Yellow: Colors corresponding to 3 types of goods

Assumptions

  • Each shelf contains 2 items of the same type
  • Random demand for goods, no preference for type
  • Only one item is taken out at a time

Simulation Results and Analysis

Simulate and test each quantity scenario in the layout scheme for each item 30 times, and calculate the maximum, minimum, and average values of the results for each scenario. The final conclusion is that in the case of 6 shelves, Layout Scheme 2 performs the best.

Scheme 3: 3 shelves

Scheme 3

Scheme 6

Trend in Average Ticks for Scheme 6 Trend in Average Ticks for Scheme 6

Optimal layout scheme for Scheme 6: Scheme 2 Optimal layout scheme for Scheme 6

Trend graph of "Demand Quantity - Shortest Average Service Time" for each sub-scheme should also be plotted. Taking Scheme 6-1 as an example, the x-axis represents the quantity of goods demanded, and the y-axis represents the shortest average service time (Ticks).

Scheme 6-1

Improvement Space

Since the specific execution time of the event is not given in the title, and the time unit is not specified, we only measure the number of operations on the shelves as the time cost. In other words, the time is calculated afterwards, and I think most of the students might have the same idea at this point. Although there is no problem with the final result, the idea can be changed to adapt to later studies.

The current approach is task-driven. Although it can obtain the correct result, it does not make use of simulation time. This approach does not have any issues when controlling only one entity. However, when dealing with multiple entities simultaneously, the current approach cannot handle the situation where multiple entities complete tasks at the same time, and can only achieve the situation where multiple entities complete tasks one after another. The specific process of the current approach is as follows:

',33),K=e("p",null,"Since the time advance method is used, the simulation world has its own time. For us, we can control the simulation speed by multiplying a multiplier on the simulation time, which is the simulation speed. In addition, this approach is more flexible in supporting multiple objects. The specific process is as follows:",-1),Y=e("p",null,"This way, the simulation is changed to be time-centric, and the progress of all entities in the scene can be refreshed directly when refreshing the task execution progress. Since the simulation is time-centric, it is necessary to set the rate/time of various operations to ensure the accuracy of time calculation. In MicroCityWeb, there are some techniques that can be used for time advance simulation.",-1),H=e("h4",{id:"update-simulation-time-with-system-time",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#update-simulation-time-with-system-time","aria-hidden":"true"},"#"),t(" Update simulation time with system time")],-1),J=e("code",null,"os.clock()",-1),U=e("p",null,"Since time is the core of the entire simulation, it is necessary to specify the time required for operations that were not previously defined. In the improved part, the additional time required for the following operations is considered:",-1),Z=e("ul",null,[e("li",null,"Time required for goods to enter and leave the storage"),e("li",null,"Time required for the AGV to lift and lower the shelves")],-1),X={href:"https://github.com/huuhghhgyg/MicroCityNotes/issues/new",target:"_blank",rel:"noopener noreferrer"},$=e("strong",null,"feedback",-1);function ee(te,se){const o=a("RouterLink"),i=a("FlowChart"),r=a("ExternalLinkIcon");return S(),T("div",null,[I,G,B,E,V,O,L,D,z,C,j,F,R,N,e("div",P,[Q,e("p",null,[t("If you need to reuse existing models, or if you want to upload models to the repository maintained by the author of this document, please refer to the documentation on "),s(o,{to:"/en/notes/3d-objects.html#external-models"},{default:l(()=>[t("3D Objects - External Models")]),_:1}),t(".")])]),W,s(i,{id:"flowchart-475",code:"eJxtzkEOwiAQBdA9p2CpSXuBJmVjjBfwAiOMhghMhcHo7Z2WRmPSDQv+m5mPT0w8msKQedBnKHf9qFhRLYGl5EYzv549pQaKzhjBJ59uCl9oR0MTZmjgKB+VUduasyzQLAMKnGMf8Q8eINgaQOgc6TKJVqXGBjG5QZ9Q5okhLES1Sr35Nvt13L2xdAGvvJdYGvRmPbmtE3UXYqYofD2pPtpIYVA=",preset:"vue"}),K,s(i,{id:"flowchart-479",code:"eJxtj7EOwjAMRPd8hUcqtT+A1KzsiB8I7bVENEmJHQR/T9IgEBKLB9873xl3eOk1i4myp5PhK90SEtQmDMGPvS7Tig2+AkwRzlhv/azEOvQ6rIimAgcIDSnGbKYi0i672Y6IxNalZcOIV2BsFB4YftxHTBF8ISk9ipo2fI1hzntWnFxNhB9rlgQxy5akauVOf5p/f9g9we2CSZpOFzZD+fh/1If2HESCy+w7T70AptBsKQ==",preset:"vue"}),Y,H,e("p",null,[t("The "),J,t(" function can get the current system time (in seconds, but in decimal). With this function, synchronization between simulation time and real time can be achieved. Usage examples can be found in "),s(o,{to:"/en/notes/timelapse.html#%E4%B8%BB%E5%AF%BC%E6%97%B6%E9%92%9F%E6%8E%A8%E8%BF%9B%E6%B3%95"},{default:l(()=>[t("Time Lapse")]),_:1}),t(" (Chinese only).")]),U,Z,e("blockquote",null,[e("p",null,[t("This post is translated using ChatGPT, please "),e("a",X,[$,s(r)]),t(" if any omissions.")])])])}const oe=q(M,[["render",ee],["__file","warehouse-simulation.html.vue"]]);export{oe as default}; diff --git a/assets/warehouse-simulation.html-rJTy601K.js b/assets/warehouse-simulation.html-rJTy601K.js new file mode 100644 index 00000000..cbf7353c --- /dev/null +++ b/assets/warehouse-simulation.html-rJTy601K.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-187abc41","path":"/notes/warehouse-simulation.html","title":"自动化仓库仿真思路","lang":"zh-CN","frontmatter":{"description":"本文思路仅供参考,建议做出适当改进。 具体问题:基于元胞自动机的仓库仿真 Problem1 其中,出入库位置可以更改,叉车为AGV。 也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。 基本假设 所有货架上的货物相同; 一个货架只放一个货物; 因此,出库和入库可以看做完全相反的...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/warehouse-simulation.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/warehouse-simulation.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"自动化仓库仿真思路"}],["meta",{"property":"og:description","content":"本文思路仅供参考,建议做出适当改进。 具体问题:基于元胞自动机的仓库仿真 Problem1 其中,出入库位置可以更改,叉车为AGV。 也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。 基本假设 所有货架上的货物相同; 一个货架只放一个货物; 因此,出库和入库可以看做完全相反的..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T16:30:53.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T16:30:53.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"自动化仓库仿真思路\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T16:30:53.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"具体问题:基于元胞自动机的仓库仿真","slug":"具体问题-基于元胞自动机的仓库仿真","link":"#具体问题-基于元胞自动机的仓库仿真","children":[{"level":3,"title":"基本假设","slug":"基本假设","link":"#基本假设","children":[]},{"level":3,"title":"总体实现思路","slug":"总体实现思路","link":"#总体实现思路","children":[]},{"level":3,"title":"过程优化:关于旧方法和新方法","slug":"过程优化-关于旧方法和新方法","link":"#过程优化-关于旧方法和新方法","children":[]},{"level":3,"title":"仿真数据收集分析","slug":"仿真数据收集分析","link":"#仿真数据收集分析","children":[]},{"level":3,"title":"创新点","slug":"创新点","link":"#创新点","children":[]}]},{"level":2,"title":"仿真改进:三维化自动仓库仿真","slug":"仿真改进-三维化自动仓库仿真","link":"#仿真改进-三维化自动仓库仿真","children":[{"level":3,"title":"总体思路","slug":"总体思路","link":"#总体思路","children":[]},{"level":3,"title":"改进","slug":"改进","link":"#改进","children":[]},{"level":3,"title":"创新","slug":"创新","link":"#创新","children":[]},{"level":3,"title":"货架布局方案","slug":"货架布局方案","link":"#货架布局方案","children":[]},{"level":3,"title":"仿真结果及分析","slug":"仿真结果及分析","link":"#仿真结果及分析","children":[]},{"level":3,"title":"改进空间","slug":"改进空间","link":"#改进空间","children":[]}]}],"git":{"updatedTime":1701016253000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":4}]},"filePathRelative":"notes/warehouse-simulation.md","autoDesc":true}');export{e as data}; diff --git a/assets/web-ui-en.html-FPAIksJ9.js b/assets/web-ui-en.html-FPAIksJ9.js deleted file mode 100644 index 00f91992..00000000 --- a/assets/web-ui-en.html-FPAIksJ9.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-51d74d37","path":"/notes/web-ui-en.html","title":"Introduction to the User Interface","lang":"zh-CN","frontmatter":{"description":"The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb. ...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui-en.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"Introduction to the User Interface"}],["meta",{"property":"og:description","content":"The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb. ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-05-21T06:17:26.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"Introduction to the User Interface"}],["meta",{"property":"article:modified_time","content":"2023-05-21T06:17:26.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Introduction to the User Interface\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-05-21T06:17:26.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Overview of Interface Zones","slug":"overview-of-interface-zones","link":"#overview-of-interface-zones","children":[]},{"level":2,"title":"Blue: Command Area","slug":"blue-command-area","link":"#blue-command-area","children":[{"level":3,"title":"Program Control","slug":"program-control","link":"#program-control","children":[]},{"level":3,"title":"Code Editing","slug":"code-editing","link":"#code-editing","children":[]},{"level":3,"title":"Others","slug":"others","link":"#others","children":[]}]},{"level":2,"title":"Green: Code Editor","slug":"green-code-editor","link":"#green-code-editor","children":[{"level":3,"title":"Keyboard Shortcuts","slug":"keyboard-shortcuts","link":"#keyboard-shortcuts","children":[]}]},{"level":2,"title":"Red: Canvas area","slug":"red-canvas-area","link":"#red-canvas-area","children":[{"level":3,"title":"Scene Operations","slug":"scene-operations","link":"#scene-operations","children":[]}]},{"level":2,"title":"Yellow: Code Output Area","slug":"yellow-code-output-area","link":"#yellow-code-output-area","children":[]},{"level":2,"title":"Notes","slug":"notes","link":"#notes","children":[]}],"git":{"updatedTime":1684649846000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"notes/web-ui-en.md","autoDesc":true}');export{e as data}; diff --git a/assets/web-ui.html--l1JvFq2.js b/assets/web-ui.html--l1JvFq2.js new file mode 100644 index 00000000..f8a4a879 --- /dev/null +++ b/assets/web-ui.html--l1JvFq2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-eaa2a0de","path":"/en/notes/web-ui.html","title":"Introduction to the User Interface","lang":"en-US","frontmatter":{"description":"The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb. ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/web-ui.html"}],["meta",{"property":"og:site_name","content":"MicroCity Notes"}],["meta",{"property":"og:title","content":"Introduction to the User Interface"}],["meta",{"property":"og:description","content":"The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb. ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Introduction to the User Interface\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"Overview of Interface Zones","slug":"overview-of-interface-zones","link":"#overview-of-interface-zones","children":[]},{"level":2,"title":"Blue: Command Area","slug":"blue-command-area","link":"#blue-command-area","children":[{"level":3,"title":"Program Control","slug":"program-control","link":"#program-control","children":[]},{"level":3,"title":"Code Editing","slug":"code-editing","link":"#code-editing","children":[]},{"level":3,"title":"Others","slug":"others","link":"#others","children":[]}]},{"level":2,"title":"Green: Code Editor","slug":"green-code-editor","link":"#green-code-editor","children":[{"level":3,"title":"Keyboard Shortcuts","slug":"keyboard-shortcuts","link":"#keyboard-shortcuts","children":[]}]},{"level":2,"title":"Red: Canvas area","slug":"red-canvas-area","link":"#red-canvas-area","children":[{"level":3,"title":"Scene Operations","slug":"scene-operations","link":"#scene-operations","children":[]}]},{"level":2,"title":"Yellow: Code Output Area","slug":"yellow-code-output-area","link":"#yellow-code-output-area","children":[]},{"level":2,"title":"Notes","slug":"notes","link":"#notes","children":[]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":1}]},"filePathRelative":"en/notes/web-ui.md","autoDesc":true}');export{e as data}; diff --git a/assets/web-ui-en.html-9hWYZBEN.js b/assets/web-ui.html-MXj0sqtU.js similarity index 98% rename from assets/web-ui-en.html-9hWYZBEN.js rename to assets/web-ui.html-MXj0sqtU.js index 7415834d..8448b9b0 100644 --- a/assets/web-ui-en.html-9hWYZBEN.js +++ b/assets/web-ui.html-MXj0sqtU.js @@ -1 +1 @@ -import{_ as e,a as t,b as o,c as i,d as n,e as r,f as a,g as s,h as l,i as d}from"./AutoTranslate-DxMBsWAh.js";import{_ as c}from"./CommandBar-jgj8yIQP.js";import{_ as h,o as u,c as p,e as f}from"./app-DaLjD81q.js";const g={},b=f('

Introduction to the User Interface

The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb.

Overall interface

Overview of Interface Zones

Overall, the interface of MicroCityWeb can be roughly divided into four areas:

Interface zones

Next, we will provide a detailed description of the usage and functions of these areas.

Blue: Command Area

The content of this area is shown in the following figure, with nine available buttons.

Command bar

Program Control

The first three buttons are mainly used to control program execution. Their specific functions are as follows:

  1. Run/Debug: Clicking the left mouse button will run the code in the code editor on the left-hand side of the webpage, while right-clicking will debug the code.

  2. Pause: If the program is running, clicking this button will pause its execution (if supported).

  3. Stop/Force Stop: If the program is running, clicking the left mouse button will stop its execution. If left-clicking does not stop the script, right-clicking can forcibly terminate its execution.

Program control

Code Editing

Buttons 4-7 are mainly related to code editing.

  1. Show/Hide Editor: If the left code editor is open, clicking this button will close it. If it's closed, clicking it will reopen it. If you right-click, the editor can be expanded to full screen.

  2. Open Built-In Code: You can directly load built-in code (import built-in models), such as cubes, trucks, earth, world maps, etc. The specific models will be introduced in detail when the red canvas area is introduced.

Built-in code

Built-in code list

  1. Open Local Code:

    Left-click: A dialog box will pop up when you left-click, and you can choose a code file (.lua) on your local machine. After confirming the selection to open the file, the text of the code file will be automatically imported into the code editor on the left.

    Right-click: You can select one or more files to upload to MicroCityWeb by right-clicking. The "Save" button (⑦) on the right can be clicked to view the list of uploaded files.

  2. Save Code:

    Left-click: When you save a file for the first time, a save file dialog box will pop up after you click the save button. You can choose the save location and fill in the file name. If you have previously saved the file locally and you have made modifications to the file and want to save the changes, you can simply click the save button to save the changes directly to the previously saved file.

    Right-click: You can view the list of uploaded files, and you can click on a file in the list and download it to your local machine.

Others

  1. Share. After clicking the button, a dialog box for entering a password will pop up. Afterwards, you will receive a link that anyone can use to access your share.

    If you enter a password in the dialog box, others who open the link can only run your program code and observe the running result, but cannot view your code (unless you tell them the password); if you do not enter a password, others can not only run your code to view the running result but also view the code you have written.

  2. View help documentation.

Green: Code Editor

Code Editor

The integrated code editor on the left side of MicroCityWeb is based on AceEditor and therefore has some of its features.

Keyboard Shortcuts

Below are some commonly used keyboard shortcuts to help you edit code more efficiently.

Most Common

Ctrl+Z: Undo

Line Operations

Ctrl+D: Delete a line Ctrl+Shift+D: Duplicate a line

Alt+: Move line of code up Alt+: Move line of code down

Find Content

Ctrl+K: Find the next occurrence of selected content in the code

Indentation

Ctrl+[: Increase code indentation Ctrl+]: Decrease code indentation

Modify Values

Ctrl+Shift+: Increase the numeric value before the cursor by 1 Ctrl+Shift+: Decrease the numeric value before the cursor by 1

Red: Canvas area

Built-in code can be imported into the scene, see Command Area - Code Editing for details.

After importing the scene code, click the "Run" button to load the scene.

Built-in car model

Built-in car model

Built-in Earth model

Built-in Earth model

Scene Operations

Scene operations, including viewpoint movement and rotation, need to be performed in the canvas area. Therefore, the following will introduce the basic operations of the canvas area.

  • Zooming in and out of the scene: Scroll the mouse wheel up to zoom in and down to zoom out.
  • Translation: Hold down the right mouse button and drag.
  • Rotation
    • Scene rotation: Hold down the left mouse button and drag to rotate from your viewpoint.
    • Object rotation: Click on the object, the color of the object changes, and then hold down the left mouse button on the object to rotate around the object's center. Rotate object

These operation rules apply to both two-dimensional and three-dimensional objects.

Yellow: Code Output Area

After opening MicroCityWeb, the code output area is shown below. Clicking on the code output area will cause the entire area to move up, allowing you to see more historical output information.

Bottom bar

Regarding the information output in this area, the code output area will output the following information:

  • Script output: The left side is the output of the script, including the output time and content.
  • Script running status: The first line on the right side shows the script running status. "state: ready" indicates that the script is ready to start running (not yet running), and "state: running" indicates that the script is running.
  • MicroCityWeb version number: Indicates the current version number of MicroCityWeb being used. If there is a difference from the known version, you can force a refresh to load the latest version.

Notes

Turn off automatic translation

Turn off automatic translation: If your operating system language is not English and the browser has automatic translation enabled, it needs to be manually disabled, otherwise there will be errors when running the code.

',54),m=[b];function k(w,y){return u(),p("div",null,m)}const x=h(g,[["render",k],["__file","web-ui-en.html.vue"]]);export{x as default}; +import{_ as e,a as t,b as o,c as i,d as n,e as r,f as a,g as s,h as l,i as d}from"./AutoTranslate-DxMBsWAh.js";import{_ as c}from"./CommandBar-jgj8yIQP.js";import{_ as h,o as u,c as p,e as f}from"./app-LOf__QKq.js";const g={},b=f('

Introduction to the User Interface

The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb.

Overall interface

Overview of Interface Zones

Overall, the interface of MicroCityWeb can be roughly divided into four areas:

Interface zones

Next, we will provide a detailed description of the usage and functions of these areas.

Blue: Command Area

The content of this area is shown in the following figure, with nine available buttons.

Command bar

Program Control

The first three buttons are mainly used to control program execution. Their specific functions are as follows:

  1. Run/Debug: Clicking the left mouse button will run the code in the code editor on the left-hand side of the webpage, while right-clicking will debug the code.

  2. Pause: If the program is running, clicking this button will pause its execution (if supported).

  3. Stop/Force Stop: If the program is running, clicking the left mouse button will stop its execution. If left-clicking does not stop the script, right-clicking can forcibly terminate its execution.

Program control

Code Editing

Buttons 4-7 are mainly related to code editing.

  1. Show/Hide Editor: If the left code editor is open, clicking this button will close it. If it's closed, clicking it will reopen it. If you right-click, the editor can be expanded to full screen.

  2. Open Built-In Code: You can directly load built-in code (import built-in models), such as cubes, trucks, earth, world maps, etc. The specific models will be introduced in detail when the red canvas area is introduced.

Built-in code

Built-in code list

  1. Open Local Code:

    Left-click: A dialog box will pop up when you left-click, and you can choose a code file (.lua) on your local machine. After confirming the selection to open the file, the text of the code file will be automatically imported into the code editor on the left.

    Right-click: You can select one or more files to upload to MicroCityWeb by right-clicking. The "Save" button (⑦) on the right can be clicked to view the list of uploaded files.

  2. Save Code:

    Left-click: When you save a file for the first time, a save file dialog box will pop up after you click the save button. You can choose the save location and fill in the file name. If you have previously saved the file locally and you have made modifications to the file and want to save the changes, you can simply click the save button to save the changes directly to the previously saved file.

    Right-click: You can view the list of uploaded files, and you can click on a file in the list and download it to your local machine.

Others

  1. Share. After clicking the button, a dialog box for entering a password will pop up. Afterwards, you will receive a link that anyone can use to access your share.

    If you enter a password in the dialog box, others who open the link can only run your program code and observe the running result, but cannot view your code (unless you tell them the password); if you do not enter a password, others can not only run your code to view the running result but also view the code you have written.

  2. View help documentation.

Green: Code Editor

Code Editor

The integrated code editor on the left side of MicroCityWeb is based on AceEditor and therefore has some of its features.

Keyboard Shortcuts

Below are some commonly used keyboard shortcuts to help you edit code more efficiently.

Most Common

Ctrl+Z: Undo

Line Operations

Ctrl+D: Delete a line Ctrl+Shift+D: Duplicate a line

Alt+: Move line of code up Alt+: Move line of code down

Find Content

Ctrl+K: Find the next occurrence of selected content in the code

Indentation

Ctrl+[: Increase code indentation Ctrl+]: Decrease code indentation

Modify Values

Ctrl+Shift+: Increase the numeric value before the cursor by 1 Ctrl+Shift+: Decrease the numeric value before the cursor by 1

Red: Canvas area

Built-in code can be imported into the scene, see Command Area - Code Editing for details.

After importing the scene code, click the "Run" button to load the scene.

Built-in car model

Built-in car model

Built-in Earth model

Built-in Earth model

Scene Operations

Scene operations, including viewpoint movement and rotation, need to be performed in the canvas area. Therefore, the following will introduce the basic operations of the canvas area.

  • Zooming in and out of the scene: Scroll the mouse wheel up to zoom in and down to zoom out.
  • Translation: Hold down the right mouse button and drag.
  • Rotation
    • Scene rotation: Hold down the left mouse button and drag to rotate from your viewpoint.
    • Object rotation: Click on the object, the color of the object changes, and then hold down the left mouse button on the object to rotate around the object's center. Rotate object

These operation rules apply to both two-dimensional and three-dimensional objects.

Yellow: Code Output Area

After opening MicroCityWeb, the code output area is shown below. Clicking on the code output area will cause the entire area to move up, allowing you to see more historical output information.

Bottom bar

Regarding the information output in this area, the code output area will output the following information:

  • Script output: The left side is the output of the script, including the output time and content.
  • Script running status: The first line on the right side shows the script running status. "state: ready" indicates that the script is ready to start running (not yet running), and "state: running" indicates that the script is running.
  • MicroCityWeb version number: Indicates the current version number of MicroCityWeb being used. If there is a difference from the known version, you can force a refresh to load the latest version.

Notes

Turn off automatic translation

Turn off automatic translation: If your operating system language is not English and the browser has automatic translation enabled, it needs to be manually disabled, otherwise there will be errors when running the code.

',54),m=[b];function k(w,y){return u(),p("div",null,m)}const x=h(g,[["render",k],["__file","web-ui.html.vue"]]);export{x as default}; diff --git a/assets/web-ui.html-zrAeLt4a.js b/assets/web-ui.html-Ub-X1RXi.js similarity index 99% rename from assets/web-ui.html-zrAeLt4a.js rename to assets/web-ui.html-Ub-X1RXi.js index 15040e6d..0c1514f7 100644 --- a/assets/web-ui.html-zrAeLt4a.js +++ b/assets/web-ui.html-Ub-X1RXi.js @@ -1 +1 @@ -import{_ as r,a as i,b as t,c as a,d as l,e,f as d,g as s,h as o,i as p}from"./AutoTranslate-DxMBsWAh.js";import{_ as n}from"./CommandBar-jgj8yIQP.js";import{_ as h,o as b,c,e as g}from"./app-DaLjD81q.js";const E={},k=g('

用户界面简介

MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。

总体界面

界面分区概览

整体来看,MicroCity Web的界面大致可以划分为4个区域。

界面分区

下面将详细介绍这几个区域的用法和功能。

蓝色:命令区域

此区域的的内容如下图所示,共有9个可用按钮。

命令栏

程序控制

前3个按钮的功能大致都用于控制程序运行。详细作用分别如下:

  1. 开始运行/debug: 左键点击后将运行网页左侧代码编辑器内的代码;右键点击后进行代码调试(debug)

  2. 暂停运行: 如果程序正在运行,点击后程序将暂停运行(如果程序支持)。

  3. 停止运行/强行停止: 如果程序正在运行,左键点击后程序将停止运行。有时存在左键点击无法停止运行脚本的情况,右键点击可以强行终止其运行。

程序控制

代码编辑

编号4~7的按钮主要与代码编辑有关。

  1. 显示/隐藏编辑器。 如果左侧的代码编辑器为开启状态,点击这个按钮后将关闭。如果为关闭状态,点击后会重新打开。如果使用右键点击,编辑器可以展开到全屏状态。

  2. 打开内置的代码 可以直接载入内置的代码(导入内置模型),如立方体、卡车、地球、世界地图等。具体的模型将在介绍画布区域时详细介绍。

内置代码

内置代码列表

  1. 打开本地代码/上传文件

    左键点击:弹出打开文件的对话框,您可以选择本机上的某个代码文件(.lua)。确定打开文件后,代码文件文本将自动导入到左侧代码编辑器中。

    右键点击:可以选择一个或多个文件上传到MicroCity Web中。右键“保存”按钮(⑦)可以查看已上传的文件列表。

  2. 保存代码/下载

    左键点击:当您第一次保存文件时,点击保存按钮后会弹出保存文件对话框,您可以选择保存位置并填写文件名。如果您之前已经将该文件保存到本地,而此时您又对该文件进行了修改并想要保存更改,直接点击保存按钮即可直接将更改保存到之前保存的文件中。

    右键点击:可以查看已上传的文件列表,您可以点击列表中的文件并下载到本地。

其他

  1. 共享。 点击按钮后,将会弹出一个输入密码的对话框。随后,您将会得到一个链接,任何人都可以通过这个链接打开您的共享。

    如果您在弹出的对话框中输入了密码,那么在其他人打开链接后,他们只能运行您的程序代码并观察运行结果,而无法查看您的代码(除非您告知他们密码);如果您没有输入密码,则其他人不仅可以运行您的代码查看运行结果,还可以查看您编写的代码。

  2. 查看帮助文档。

绿色:代码编辑器

代码编辑器

MicroCity Web左侧整合的代码编辑器源于AceEditor,因此也具有AceEditor的一些特性。

快捷键

下面将介绍一些常用的快捷键,帮助你更好地编辑代码。

最常用

  • Ctrl+Z:撤销

行操作

  • Ctrl+D:删除一行
  • Ctrl+Shift+D:复制一行
  • Alt+:行代码上移
  • Alt+:行代码下移

查找内容

  • Ctrl+K:在代码中查找下一个与选中内容

代码缩进

  • Ctrl+[:增加代码缩进
  • Ctrl+]:减少代码缩进

修改数值

  • Ctrl+Shift+:光标前的数字数值+1
  • Ctrl+Shift+:光标前的数字数值-1

红色:画布区域

可以从内置代码导入场景,详见 命令区域 - 代码编辑

导入场景代码后要点击“运行”按钮才会载入场景

内置代码_方块 内置汽车模型

内置代码_方块 内置地球模型

场景操作

对场景的操作包括视角移动、旋转都需要在画布区域进行。因此,下面将介绍画布区域的基本操作。

  • 场景的放大缩小:鼠标滚轮向上滚动为放大,向下滚动为缩小。
  • 平移:按住鼠标右键拖动。
  • 旋转
    • 场景旋转:按住鼠标左键拖动,以你的视角进行旋转
    • 对象旋转:点击对象,对象颜色改变后从对象上按住鼠标左键拖动,以对象为中心旋转。 旋转对象

无论是二维对象还是三维对象都遵循上述操作逻辑。

黄色:代码输出区域

打开MicroCity Web后,代码输出区域如下。点击代码输出区域后整个区域会上移,能够看到更多的历史输出信息。

底栏

说到这个区域输出的信息,代码输出区域会输出以下信息:

  • 脚本输出: 左侧是脚本的输出,包含输出时间、脚本输出内容。
  • 脚本运行状态: 右边第一行为脚本运行状态。state:ready表示脚本已经准备好开始运行(未运行),state:running表示脚本正在运行。
  • MicroCityWeb版本号: 表示当前使用的MicroCityWeb版本号。如果与已知版本有差异,可以通过强制刷新加载最新版本。

注意事项

关闭自动翻译

关闭自动翻译: 如果你的操作系统语言不是英语且浏览器开启了自动翻译,需要手动关闭,否则代码运行将出现错误。

',53),B=[k];function u(_,f){return b(),c("div",null,B)}const x=h(E,[["render",u],["__file","web-ui.html.vue"]]);export{x as default}; +import{_ as r,a as i,b as t,c as a,d as l,e,f as d,g as s,h as o,i as p}from"./AutoTranslate-DxMBsWAh.js";import{_ as n}from"./CommandBar-jgj8yIQP.js";import{_ as h,o as b,c,e as g}from"./app-LOf__QKq.js";const E={},k=g('

用户界面简介

MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。

总体界面

界面分区概览

整体来看,MicroCity Web的界面大致可以划分为4个区域。

界面分区

下面将详细介绍这几个区域的用法和功能。

蓝色:命令区域

此区域的的内容如下图所示,共有9个可用按钮。

命令栏

程序控制

前3个按钮的功能大致都用于控制程序运行。详细作用分别如下:

  1. 开始运行/debug: 左键点击后将运行网页左侧代码编辑器内的代码;右键点击后进行代码调试(debug)

  2. 暂停运行: 如果程序正在运行,点击后程序将暂停运行(如果程序支持)。

  3. 停止运行/强行停止: 如果程序正在运行,左键点击后程序将停止运行。有时存在左键点击无法停止运行脚本的情况,右键点击可以强行终止其运行。

程序控制

代码编辑

编号4~7的按钮主要与代码编辑有关。

  1. 显示/隐藏编辑器。 如果左侧的代码编辑器为开启状态,点击这个按钮后将关闭。如果为关闭状态,点击后会重新打开。如果使用右键点击,编辑器可以展开到全屏状态。

  2. 打开内置的代码 可以直接载入内置的代码(导入内置模型),如立方体、卡车、地球、世界地图等。具体的模型将在介绍画布区域时详细介绍。

内置代码

内置代码列表

  1. 打开本地代码/上传文件

    左键点击:弹出打开文件的对话框,您可以选择本机上的某个代码文件(.lua)。确定打开文件后,代码文件文本将自动导入到左侧代码编辑器中。

    右键点击:可以选择一个或多个文件上传到MicroCity Web中。右键“保存”按钮(⑦)可以查看已上传的文件列表。

  2. 保存代码/下载

    左键点击:当您第一次保存文件时,点击保存按钮后会弹出保存文件对话框,您可以选择保存位置并填写文件名。如果您之前已经将该文件保存到本地,而此时您又对该文件进行了修改并想要保存更改,直接点击保存按钮即可直接将更改保存到之前保存的文件中。

    右键点击:可以查看已上传的文件列表,您可以点击列表中的文件并下载到本地。

其他

  1. 共享。 点击按钮后,将会弹出一个输入密码的对话框。随后,您将会得到一个链接,任何人都可以通过这个链接打开您的共享。

    如果您在弹出的对话框中输入了密码,那么在其他人打开链接后,他们只能运行您的程序代码并观察运行结果,而无法查看您的代码(除非您告知他们密码);如果您没有输入密码,则其他人不仅可以运行您的代码查看运行结果,还可以查看您编写的代码。

  2. 查看帮助文档。

绿色:代码编辑器

代码编辑器

MicroCity Web左侧整合的代码编辑器源于AceEditor,因此也具有AceEditor的一些特性。

快捷键

下面将介绍一些常用的快捷键,帮助你更好地编辑代码。

最常用

  • Ctrl+Z:撤销

行操作

  • Ctrl+D:删除一行
  • Ctrl+Shift+D:复制一行
  • Alt+:行代码上移
  • Alt+:行代码下移

查找内容

  • Ctrl+K:在代码中查找下一个与选中内容

代码缩进

  • Ctrl+[:增加代码缩进
  • Ctrl+]:减少代码缩进

修改数值

  • Ctrl+Shift+:光标前的数字数值+1
  • Ctrl+Shift+:光标前的数字数值-1

红色:画布区域

可以从内置代码导入场景,详见 命令区域 - 代码编辑

导入场景代码后要点击“运行”按钮才会载入场景

内置代码_方块 内置汽车模型

内置代码_方块 内置地球模型

场景操作

对场景的操作包括视角移动、旋转都需要在画布区域进行。因此,下面将介绍画布区域的基本操作。

  • 场景的放大缩小:鼠标滚轮向上滚动为放大,向下滚动为缩小。
  • 平移:按住鼠标右键拖动。
  • 旋转
    • 场景旋转:按住鼠标左键拖动,以你的视角进行旋转
    • 对象旋转:点击对象,对象颜色改变后从对象上按住鼠标左键拖动,以对象为中心旋转。 旋转对象

无论是二维对象还是三维对象都遵循上述操作逻辑。

黄色:代码输出区域

打开MicroCity Web后,代码输出区域如下。点击代码输出区域后整个区域会上移,能够看到更多的历史输出信息。

底栏

说到这个区域输出的信息,代码输出区域会输出以下信息:

  • 脚本输出: 左侧是脚本的输出,包含输出时间、脚本输出内容。
  • 脚本运行状态: 右边第一行为脚本运行状态。state:ready表示脚本已经准备好开始运行(未运行),state:running表示脚本正在运行。
  • MicroCityWeb版本号: 表示当前使用的MicroCityWeb版本号。如果与已知版本有差异,可以通过强制刷新加载最新版本。

注意事项

关闭自动翻译

关闭自动翻译: 如果你的操作系统语言不是英语且浏览器开启了自动翻译,需要手动关闭,否则代码运行将出现错误。

',53),B=[k];function u(_,f){return b(),c("div",null,B)}const x=h(E,[["render",u],["__file","web-ui.html.vue"]]);export{x as default}; diff --git a/assets/web-ui.html-cjOV8UTz.js b/assets/web-ui.html-cjOV8UTz.js deleted file mode 100644 index 5c635e99..00000000 --- a/assets/web-ui.html-cjOV8UTz.js +++ /dev/null @@ -1 +0,0 @@ -const e=JSON.parse('{"key":"v-1ae3cdb6","path":"/notes/web-ui.html","title":"用户界面简介","lang":"zh-CN","frontmatter":{"description":"MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。 总体界面 界面分区概览 整体来看,MicroCity Web的界面大致可以划分为4个区域。 顶部-蓝色区域 (#蓝色-命令区域):对代码、文件执行各种操作; 左侧-绿色区域 (#绿色-代码编辑器):代码编辑器; 右侧-红色区域 (#红色-画布区...","head":[["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"用户界面简介"}],["meta",{"property":"og:description","content":"MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。 总体界面 界面分区概览 整体来看,MicroCity Web的界面大致可以划分为4个区域。 顶部-蓝色区域 (#蓝色-命令区域):对代码、文件执行各种操作; 左侧-绿色区域 (#绿色-代码编辑器):代码编辑器; 右侧-红色区域 (#红色-画布区..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://huuhghhgyg.github.io/MicroCityNotes/"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2023-11-14T13:50:52.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"用户界面简介"}],["meta",{"property":"article:modified_time","content":"2023-11-14T13:50:52.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"用户界面简介\\",\\"image\\":[\\"https://huuhghhgyg.github.io/MicroCityNotes/\\"],\\"dateModified\\":\\"2023-11-14T13:50:52.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"界面分区概览","slug":"界面分区概览","link":"#界面分区概览","children":[]},{"level":2,"title":"蓝色:命令区域","slug":"蓝色-命令区域","link":"#蓝色-命令区域","children":[{"level":3,"title":"程序控制","slug":"程序控制","link":"#程序控制","children":[]},{"level":3,"title":"代码编辑","slug":"代码编辑","link":"#代码编辑","children":[]},{"level":3,"title":"其他","slug":"其他","link":"#其他","children":[]}]},{"level":2,"title":"绿色:代码编辑器","slug":"绿色-代码编辑器","link":"#绿色-代码编辑器","children":[{"level":3,"title":"快捷键","slug":"快捷键","link":"#快捷键","children":[]}]},{"level":2,"title":"红色:画布区域","slug":"红色-画布区域","link":"#红色-画布区域","children":[{"level":3,"title":"场景操作","slug":"场景操作","link":"#场景操作","children":[]}]},{"level":2,"title":"黄色:代码输出区域","slug":"黄色-代码输出区域","link":"#黄色-代码输出区域","children":[]},{"level":2,"title":"注意事项","slug":"注意事项","link":"#注意事项","children":[]}],"git":{"updatedTime":1699969852000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":2}]},"filePathRelative":"notes/web-ui.md","autoDesc":true}');export{e as data}; diff --git a/assets/web-ui.html-gL6LgUwH.js b/assets/web-ui.html-gL6LgUwH.js new file mode 100644 index 00000000..f4cdab5e --- /dev/null +++ b/assets/web-ui.html-gL6LgUwH.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-1ae3cdb6","path":"/notes/web-ui.html","title":"用户界面简介","lang":"zh-CN","frontmatter":{"description":"MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。 总体界面 界面分区概览 整体来看,MicroCity Web的界面大致可以划分为4个区域。 顶部-蓝色区域 (#蓝色-命令区域):对代码、文件执行各种操作; 左侧-绿色区域 (#绿色-代码编辑器):代码编辑器; 右侧-红色区域 (#红色-画布区...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://huuhghhgyg.github.io/MicroCityNotes/en/notes/web-ui.html"}],["meta",{"property":"og:url","content":"https://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui.html"}],["meta",{"property":"og:site_name","content":"MicroCity笔记"}],["meta",{"property":"og:title","content":"用户界面简介"}],["meta",{"property":"og:description","content":"MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。 总体界面 界面分区概览 整体来看,MicroCity Web的界面大致可以划分为4个区域。 顶部-蓝色区域 (#蓝色-命令区域):对代码、文件执行各种操作; 左侧-绿色区域 (#绿色-代码编辑器):代码编辑器; 右侧-红色区域 (#红色-画布区..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2023-11-26T15:09:59.000Z"}],["meta",{"property":"article:modified_time","content":"2023-11-26T15:09:59.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"用户界面简介\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2023-11-26T15:09:59.000Z\\",\\"author\\":[]}"]]},"headers":[{"level":2,"title":"界面分区概览","slug":"界面分区概览","link":"#界面分区概览","children":[]},{"level":2,"title":"蓝色:命令区域","slug":"蓝色-命令区域","link":"#蓝色-命令区域","children":[{"level":3,"title":"程序控制","slug":"程序控制","link":"#程序控制","children":[]},{"level":3,"title":"代码编辑","slug":"代码编辑","link":"#代码编辑","children":[]},{"level":3,"title":"其他","slug":"其他","link":"#其他","children":[]}]},{"level":2,"title":"绿色:代码编辑器","slug":"绿色-代码编辑器","link":"#绿色-代码编辑器","children":[{"level":3,"title":"快捷键","slug":"快捷键","link":"#快捷键","children":[]}]},{"level":2,"title":"红色:画布区域","slug":"红色-画布区域","link":"#红色-画布区域","children":[{"level":3,"title":"场景操作","slug":"场景操作","link":"#场景操作","children":[]}]},{"level":2,"title":"黄色:代码输出区域","slug":"黄色-代码输出区域","link":"#黄色-代码输出区域","children":[]},{"level":2,"title":"注意事项","slug":"注意事项","link":"#注意事项","children":[]}],"git":{"updatedTime":1701011399000,"contributors":[{"name":"huuhghhgyg","email":"huuhghhgyg@outlook.com","commits":3}]},"filePathRelative":"notes/web-ui.md","autoDesc":true}');export{e as data}; diff --git a/docs/1.1_what_microcity_can_do.html b/docs/1.1_what_microcity_can_do.html index a5050bbc..b04938b9 100644 --- a/docs/1.1_what_microcity_can_do.html +++ b/docs/1.1_what_microcity_can_do.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 1.1 MicroCity能做什么 | MicroCity笔记 + 1.1 MicroCity的功能 | MicroCity笔记 - + -

1.1 MicroCity能做什么

MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast.

A Modeling Framework

Based on GIS, Networks and Mixed Integer Programming libraries, MicroCity can be used as a modeling framework to solve transporation problems, such as City Logistics and Shipping Planning:

city_logistic   

shipping_planning

A Simulation Platform

Based on 3D CGI and Discrete Event Simulation Engine, MicroCity can be used as a simulation platform to evaluate logistic scenarios, such as Automated Warehouses and Container Terminals:

warehouse_simulation

terminal_simulation

Customized by Scriptable Modules

MicroCity can extend its functionality with modules which can be inherited from SAGAopen in new window or scripted and debugged in Script Editor:
modules    shot

Currently, MicroCity is mainly used in teaching and research. It can be freely distributed.

Last Updated:
Contributors: huuhghhgyg
- +

1.1 MicroCity的功能

MicroCity被设计为一款方便的空间规划工具,具有便携、紧凑和快速的特点。

一个建模框架

基于GIS、网络和混合整数规划库,MicroCity可以作为一个建模框架来解决交通运输问题,例如城市物流和航运规划

city_logistic   

shipping_planning

一个仿真平台

基于3D计算机图形和离散事件仿真引擎,MicroCity可以作为一个仿真平台来评估物流场景,例如自动化仓库和集装箱码头

warehouse_simulation

terminal_simulation

通过脚本模块定制

MicroCity可以通过模块来扩展其功能,这些模块可以从SAGAopen in new window继承或在脚本编辑器中进行脚本编写和调试:
modules    shot

目前,MicroCity主要用于教学和研究,可以自由分发。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/2.1_showing_a_world_map.html b/docs/2.1_showing_a_world_map.html index 2564a5c6..24c2fa63 100644 --- a/docs/2.1_showing_a_world_map.html +++ b/docs/2.1_showing_a_world_map.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 2.1 展示世界地图 | MicroCity笔记 + 2.1 显示世界地图 | MicroCity笔记 - + -

2.1 展示世界地图

This tutorial will guide you in manipulating and visualizing GIS data in MicroCity.

Loading Data and Creating a Map

Download the countries.shpopen in new window (ArcGIS shapefile) and the countries.dbfopen in new window (dBase file) in a same folder. Open icon_microcityMicroCity and load button_load or drag the countries.shp into MicroCity and select Data Tab in Workspace panel. Double click Data->Shapes->Polygon->01. countries in Workspace panel. Screenshot

Visualizing Coutries' Properties

Right click icon 01. countries in the Workspace panel. Click Attributes->Table->Show in the popup menu. In the Settings Panel, find the Colors->Type option and select Graduated Color. In its sub-option Attribute, select POP_EST which is population property of countries. In the Setting Panel, find the Chart option and click the ... button. In the popup dialog, select pie in Chart Type option and select GDP_MD_EST in Attribute (Size) option and select EXPORT and IMPORT checkboxs in Fields option and click Okay button. Screenshot

Editing Shapes

Select buttonAction button at toolbar. Left click some country and right click it and select Edit Selected Shape in the popup menu. Then the shape will be in editing mode. You can change its polygon points and finish your editing by right click and select Edit Selected Shape again.

Last Updated:
Contributors: huuhghhgyg
- +

2.1 显示世界地图

本教程将指导您在 MicroCity 中操作和可视化地理信息系统(GIS)数据。

加载数据和创建地图

下载 countries.shpopen in new window(ArcGIS shapefile)和 countries.dbfopen in new window(dBase 文件)到同一个文件夹中。打开 icon_microcityMicroCity,点击 button_load或将 countries.shp 拖入 MicroCity,然后在工作区面板中选择 Data Tab。双击工作区面板中的 Data->Shapes->Polygon->01. countriesScreenshot

可视化国家属性

右键点击 icon 01. countries工作区面板中。在弹出菜单中选择 Attributes->Table->Show。在 Settings 面板中,找到 Colors->Type 选项并选择 Graduated Color。在其子选项 Attribute 中,选择国家的人口属性 POP_EST。在 Settings 面板中,找到 Chart 选项并点击 ... 按钮。在弹出对话框中,选择饼图(pie)作为图表类型,选择 GDP_MD_EST 作为属性(大小),并在 Fields 选项中选择 EXPORTIMPORT 复选框,然后点击 Okay 按钮。 Screenshot

编辑形状

在工具栏上选择 buttonAction 按钮。左键点击某个国家,右键点击它并在弹出菜单中选择 Edit Selected Shape,然后该形状将进入编辑模式。您可以更改其多边形的点,并在右键点击并再次选择 Edit Selected Shape 来完成编辑。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/2.2_searching_for_countries.html b/docs/2.2_searching_for_countries.html index 312b90c3..93dbfab6 100644 --- a/docs/2.2_searching_for_countries.html +++ b/docs/2.2_searching_for_countries.html @@ -22,31 +22,31 @@ document.documentElement.classList.toggle('dark', true); } - 2.2 寻找国家 | MicroCity笔记 + 2.2 寻找国家 | MicroCity笔记 - + -

2.2 寻找国家

This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed.

GIS Data Structure

In MicroCity, GIS data consists of three types of Shapes: Point, Polyline and Polygon, each of which can be visualized as a Map Layer. In a layer, a Shape object consists of one or more Parts, and every Part consists of one or more Points. A Shape object is also associated to a record in the Attributes Table. You can also edit the shape or its attributes (see 3.2). structure If you want perform a complex editing or handle a batch of shapes, you can use MicroCity Script, in which many built-in functions can be used.

Making a Query

Suppose we want to find countries, each of which has a population of more than 100 million and is entirely in the northern hemisphere. So we need to check every point's coordinate in each shape and the population attribute of the shape. Open ScriptEditor icon_script_editor and type following codes:

local Countries = Open("countries.shp")                 --Try to open the shapes layer
-for i = 1, GetRecCount(Countries) do                    --Loop all the shape objects in the layer
-    local country = GetShape(Countries, i)              --Get the shape object of a country
-    local north = true                                  --Assume the country is in the northern hemisphere
-    for j = 1, GetPartCount(country) do                 --Loop all of the parts in the shape
-        for k = 1, GetPointCount(country, j) do         --Loop all of the points in the shape part
-            local x, y = GetPointXY(country, k, j)      --Get coordinate of the point j
-            if y < 0 then                               --If the latitude is less than 0
-                north = false                           --The north assumption is false
+    

2.2 寻找国家

本教程将指导您使用 MicroCity Script 对GIS数据进行编码操作。您需要完成 2.1 内容以继续。

GIS 数据结构

在 MicroCity 中,GIS 数据由三种类型的形状组成:点、折线和多边形,每种类型都可以视为地图图层。在图层中,形状对象由一个或多个部分组成,而每个部分又由一个或多个组成。形状对象还与属性表中的记录相关联。您还可以编辑形状或其属性(请参阅 3.2)。

gis_data_structure

如果您想要执行复杂的编辑或处理一批形状,可以使用 MicroCity Script,其中包含许多内置函数可供使用。

进行查询

假设我们想要找出人口超过1亿且完全位于北半球的国家。因此,我们需要检查每个形状中每个点的坐标以及形状的人口属性。打开 ScriptEditor icon_script_editor,然后输入以下代码:

local Countries = Open("countries.shp")                 --尝试打开形状图层
+for i = 1, GetRecCount(Countries) do                    --循环遍历图层中的所有形状对象
+    local country = GetShape(Countries, i)              --获取一个国家的形状对象
+    local north = true                                  --假设该国家位于北半球
+    for j = 1, GetPartCount(country) do                 --循环遍历所有形状中的部分
+        for k = 1, GetPointCount(country, j) do         --循环遍历该部分中的所有点
+            local x, y = GetPointXY(country, k, j)      --获取点的坐标
+            if y < 0 then                               --如果纬度小于0
+                north = false                           --北半球的假设为假
             end
         end
     end
-    local pop = GetValue(country, "POP_EST")            --Get the population property
-    local name = GetValue(country, "NAME")              --Get the country name
-    if pop > 100000000 and north  then                  --Check the two conditions
-        Print(name, ": ", pop/100000000)                --Print out the result
+    local pop = GetValue(country, "POP_EST")            --获取人口属性
+    local name = GetValue(country, "NAME")              --获取国家名称
+    if pop > 100000000 and north  then                  --检查两个条件
+        Print(name, ": ", pop/100000000)                --打印结果
     end
 end
-

Running the Script

Save the script to query.mcs and open it with MicroCity or drag it to MicroCity. Then you will find a query item appears in Modules Tab in Workspace panel. Double click the sub-item main. If a dialog pops up, select 01. countries and click Okay. The results will be shown in Messages panel. results

Last Updated:
Contributors: huuhghhgyg
- +

运行脚本

将脚本保存为 query.mcs,并使用 MicroCity 打开它,或将其拖到 MicroCity。然后您将在 Workspace 面板的模块选项卡中找到一个名为query的项目。双击子项main。如果弹出对话框,请选择01. countries,然后点击确定。结果将显示在消息面板中。

query_results

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.1_ui_overview.html b/docs/3.1_ui_overview.html index 4e32a7ee..5a57e946 100644 --- a/docs/3.1_ui_overview.html +++ b/docs/3.1_ui_overview.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.1 用户界面概览 | MicroCity笔记 + 3.1 用户界面概览 | MicroCity笔记 - + -

3.1 用户界面概览

MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules.

The Main Window and Components

Screenshot

Supported Files

MicroCity can open ArcGIS shapefile (*.shp), Grids file (*.sgrd), dBase file (*.dbf), Tabular text file (*.csv, *.txt), Point clouds (*.spc), Image file (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) and MicroCity 3D Scene (*.m3d). These data files are maintained in the Data Tab of the Workspace Panel. Module libraries (*.dll, *.mcs) are maintained and executed through the Modules Tab of the Workspace Panel.

Project Management

The information of opened data files, module libraries, settings and sub-windows can be saved or opened in a MicroCity Project (*.mprj) through the menu File->Project. The mprj file does not contain any file's data. For easy maintenance, files in a project should be put into the same folder or sub-folders of the mprj file.

Last Updated:
Contributors: huuhghhgyg
- +

3.1 用户界面概览

MicroCity提供了一个简洁的图形窗口界面,以便于对数据和模块进行操作。

主窗口及其组件

截图

支持的文件类型

MicroCity可以打开ArcGIS shapefile文件(*.shp),Grids文件(*.sgrd),dBase文件(*.dbf),Tabular文本文件(*.csv, *.txt),Point clouds点云文件(*.spc),影像文件(*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx)以及MicroCity 3D场景文件(*.m3d)。这些数据文件可以在工作区面板的数据选项卡中进行管理。模块库文件(*.dll, *.mcs)可以在工作区面板的模块选项卡中进行管理和执行。

项目管理

已打开的数据文件、模块库文件、设置和子窗口信息可以通过文件->项目菜单保存或打开一个MicroCity项目(*.mprj)。mprj文件不包含任何文件数据。为方便维护,项目中的文件应放置在同一文件夹或mprj文件的子文件夹中。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.2_vector_shapes.html b/docs/3.2_vector_shapes.html index 784f867b..a033e7ce 100644 --- a/docs/3.2_vector_shapes.html +++ b/docs/3.2_vector_shapes.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.2 矢量图 | MicroCity笔记 + 3.2 矢量图 | MicroCity笔记 - + -

3.2 矢量图

MicroCity can open, create and edit ArcGIS shapefiles (*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7) other vector file formats, such like Scalable Vector Graphics (*.svg) and AutoCAD Drawing Exchange Format (*.dxf), can also be imported or exported.

Opening, Creating, Saving and Closing Shapes

Users can click buttonLoad button or File->Shapes->Load menu item to open an ArcGIS shapefile (*.shp) as a Shapes. Creating a new Shapes can be done from menu File->Shapes->New and the pop-up dialog as shown below. Users can choose one shapes type from icon_shapes_pointPoint, icon_shapes_lineLine and icon_shapes_polygonPolygon. The relationship between a ArcGIS shapefile (*.shp) and a same named dBase file (*.dbf) is also shown.

new shapes    shape_files

Saving a Shapes can be done from the right click context menu Save or Save As. You can also close a Shapes from the menu and get a prompt dialog to save it.

shapes menu    close and save

Showing and Editing Shapes

Double click a Shapes from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle buttonAction botton and right click a Shape in a Shapes layer and choose Edit Selected Shape then go to the Editing Mode. In this mode users can add/delete parts and add/delete points in a shape (for data structure of a shape see 2.2). The associated attributes table (*.dbf) of a Shapes can be accessed through right-clicking context menu Attributes->Table->Show (see the tutorial 2.1).

edit shape    edit point

Display Settings and Data Visualization

Users can change Shapes outline, fill, labels and other display settins from the Settings Panel. Some options can connect attribute data and give visualization functionalities (for example 2.1).

Last Updated:
Contributors: huuhghhgyg
- +

3.2 矢量图

MicroCity可以打开、创建和编辑ArcGIS shapefiles(*.shp),即所谓的Shapes,并在Workspace面板的Data选项卡中进行维护。通过使用模块(参见3.7),还可以导入或导出其他矢量文件格式,例如可伸缩矢量图形(*.svg)和AutoCAD绘图交换格式(*.dxf)。

打开、创建、保存和关闭Shapes

用户可以单击button加载按钮或文件->Shapes->加载菜单项来打开ArcGIS shapefile(*.shp)作为Shapes。从菜单中选择文件->Shapes->新建,弹出对话框如下所示,可以创建新的Shapes。用户可以从icon_shapes_pointicon_shapes_line线icon_shapes_polygon中选择其中一种形状类型。还显示了ArcGIS shapefile(*.shp)与同名dBase文件(*.dbf)之间的关系。

new shapes    shape_files

保存Shapes可以通过右键单击上下文菜单中的保存或另存为来完成。也可以从菜单中关闭Shapes并弹出提示对话框以保存它。

shapes menu    close and save

显示和编辑形状

数据选项卡中双击一个形状将为您提供地图视图(有关地图和图层,请参见3.6)。切换到按钮操作按钮,然后右键单击形状图层中的一个形状,选择编辑所选形状,然后进入编辑模式。在这个模式下,用户可以添加/删除部分以及添加/删除形状中的点(关于形状的数据结构,请参见2.2)。通过右键单击上下文菜单属性->表格->显示可以访问形状的相关属性表格(*.dbf)(请参见教程2.1)。

编辑形状    编辑点

显示设置和数据可视化

用户可以从设置面板中更改形状的轮廓、填充、标签和其他显示设置。一些选项可以连接属性数据并提供可视化功能(例如2.1)。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.3_raster_grids.html b/docs/3.3_raster_grids.html index 7c00a99c..f1ea5005 100644 --- a/docs/3.3_raster_grids.html +++ b/docs/3.3_raster_grids.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.3 栅格图 | MicroCity笔记 + 3.3 栅格图 | MicroCity笔记 - + -

3.3 栅格图

MicroCity can open, create and edit SAGA Grid (*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) can be opened as Grid as well. By using modules (see 3.7) other raster file formats, such like ESRI Arc/Info Grid (*.adf) and Surfer Grid (*.grd), can also be imported or exported.

Opening, Creating, Saving and Closing Grids

Users can click buttonLoad button or File->Grid->Load menu item to open a Grid. Creating new Grid can be done from menu File->Grid->New and the pop-up dialog:

new grid    grid_structure The above right figure is the data structure and definitions of a Grid. A Grid starts from its bottom left corner which has coordinate (xMin, yMin), contains NX*NY Square Cells. Each cell has its own Integer Coordinate (X, Y), in the range of (0, 0) to (XMax, YMax).

Saving Grid can be done from the right click context menu Save or Save As. You can also close a Grid from the menu and get a prompt dialog to save it.

grid menu    close and save

Showing and Editing Grids

Double click a Grid from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle Action botton button and select a range of cells in a Grid. Then the value of these cells can be edited in the Attributes Tab of the Settings Panel.

grid selection    grid_attributes

Display Settings and 3D View

Users can show cell values, change color and set transparency of a Grid by using Settings Panel. Using button button can creat a 3D surface of a Grid in which cell values are translated to elevation (see 3.6).

Last Updated:
Contributors: huuhghhgyg
- +

3.3 栅格图

MicroCity可以打开、创建和编辑SAGA Grid(*.sgrd),在工作空间面板数据选项卡中被称为Grid并进行维护。图像文件(*.bmp、*.gif、*.jpg、*.png、*.tif、*.pcx)也可以被作为Grid打开。通过使用模块(参见[3.7](3.7_modules.md)),其他栅格文件格式,例如ESRI Arc/Info Grid(*.adf)和Surfer Grid(*.grd),也可以被导入或导出。

打开、创建、保存和关闭Grid

用户可以点击按钮Load按钮或File->Grid->Load菜单项来打开一个Grid。从菜单File->Grid->New中可以创建一个新的Grid,然后弹出对话框:

new grid    grid_structure

上图是一个Grid的数据结构和定义。Grid从其左下角开始,具有坐标**(xMin, yMin),包含NX*NY个方形单元格**。每个单元格有自己的整数坐标(X, Y),范围从(0, 0)到(XMax, YMax)。

保存Grid可通过右键上下文菜单Save or Save As来完成。也可以通过菜单关闭Grid,并获得一个提示对话框来保存它。

grid menu    close and save

显示和编辑Grids

双击数据选项卡中的一个Grid将为您提供一个地图视图(有关地图和图层,请参见3.6)。切换Action按钮 按钮,然后在Grid中选择一系列单元格。然后可以在设置面板属性选项卡中编辑这些单元格的值。

grid selection    grid_attributes

显示设置和3D视图

用户可以使用设置面板来显示单元格的值,更改颜色并设置网格的透明度。使用button按钮可以创建一个网格的3D表面,其中单元格的值被转换为高程(见3.6)。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.4_3d_scenes.html b/docs/3.4_3d_scenes.html index 5ea0bdfc..1d95edc9 100644 --- a/docs/3.4_3d_scenes.html +++ b/docs/3.4_3d_scenes.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.4 3D场景 | MicroCity笔记 + 3.4 3D场景 | MicroCity笔记 - + -

3.4 3D场景

MicroCity 3D Scene (*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (*.3ds), Wavefront OBJ (*.obj) and Stereolithography (*.stl) can be loaded as objects in a scene (see below) but not be stored in the .m3d file.

Opening, Creating, Saving and Closing 3D Scenes

Users can click Load button button or File->Scene->Load menu item to open a Scene. Creating new Scene can be done from menu File->Scene->New and fill the pop-up dialog as shown below. After pressing Okay button an item will appear in the Data Tab of the Workspace Panel. Then Scene can be saved or closed through right-click menu:

new scene    scene_menu

Showing and Editing 3D Scenes

Double click a Scene from the Data tab will give you a scene view. Left-mouse-dragging in a scene veiw will rotate the camera and right-mouse-dragging will translate the camera. Double-left-clicking a scene view can select objects and Double-right-clicking a scene view can popup a context menu (shown below). One can add objects, load objects and set objects, etc.. Note that the Rotation in the coordinate system should obey Left-hand rule. The illustration of the coordinate system and an example of the rotation around y-axis is shown below:

object_menu    scene_coordinate

The coordinate used in the position and rotation of an object is relative to its parent object. By default, the parent of a new object is null.

Display Settings

Users can change the background color, reference grid or other display options of a Scene by using Settings Panel.

Last Updated:
Contributors: huuhghhgyg
- +

3.4 3D场景

MicroCity 3D场景(*.m3d)是一种存储3D场景信息的数据文件格式。流行的3D文件格式包括3D Studio Max(*.3ds),Wavefront OBJ(*.obj)和立体光刻(*.stl)可以作为场景中的对象进行加载(详见下文中的显示和编辑3D场景),但不能存储在.m3d文件中。

打开、创建、保存和关闭3D场景

用户可以点击加载按钮 button,或选择文件->场景->加载菜单项来打开一个场景。从菜单项文件->场景->新建可以创建新的场景并填写弹出对话框中的信息,如下所示。点击确定按钮之后,工作区面板数据选项卡中会出现一个项目。然后可以通过右键单击菜单来保存关闭场景:

new scene    scene_menu

显示和编辑3D场景

数据选项卡双击一个场景会显示一个场景视图。在场景视图中,用鼠标左键拖拽可以旋转相机,用鼠标右键拖拽可以平移相机。在场景视图上用双击左键可以选择对象,在场景视图上用双击右键可以弹出上下文菜单(如下图所示)。可以添加对象、加载对象和设置对象等等。请注意,坐标系中的旋转应该遵循左手规则。下图展示了坐标系的示例和沿y轴旋转的示例:

object_menu    scene_coordinate

在对象的位置和旋转中使用的坐标是相对于其父对象的。默认情况下,新对象的父对象为空。

显示设置

用户可以通过使用设置面板更改场景的背景色、参考网格或其他显示选项。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.5_tables.html b/docs/3.5_tables.html index 1b28d5ec..f27d69f3 100644 --- a/docs/3.5_tables.html +++ b/docs/3.5_tables.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.5 表格 | MicroCity笔记 + 3.5 表格 | MicroCity笔记 - + -

3.5 表格

Tabular files including dBase files (*.dbf), Text file (*.txt) and Comma Separated Values (*.csv) can be opened as Table and saved with MicroCity.

Opening, Creating, Saving and Closing Tables

Users can click Load button button or File->Table->Load menu item to open a tabular file. Creating a new Table can be done from menu File->Table->New and the pop-up dialog as shown below. Saving a Table can be done from the right click context menu Save or Save As.

new table    table_menu

Showing and Editing Tables

Double click a Table from the Data Tab will give you a table view. Altering a table's stucture can be done by right click the table's head. If you click "Add Field" then, a dialog which guide you (as shown below). If you want insert a record to the table, you can right click the left numbers of the table and select a context menu item.

table_view_menu    add_field

Last Updated:
Contributors: huuhghhgyg
- +

3.5 表格

包括 dBase 文件 (*.dbf)、文本文件 (*.txt) 和逗号分隔值 (*.csv) 在内的表格文件可以在 MicroCity 中打开并保存为表格

打开、创建、保存和关闭表格

用户可以单击加载按钮 button,或选择文件->表格->加载菜单项来打开一个表格文件。可以从文件->表格->新建菜单项中创建一个新的表格,如下图所示的弹出对话框。要保存一个表格,可以右键单击上下文菜单中的保存另存为选项。

new table    table_menu

显示和编辑表格

双击数据选项卡中的表格,将显示一个表格视图。通过右键单击表头可以修改表格的结构。如果单击"添加字段",将显示一个引导对话框(如下图所示)。如果要向表格中插入一条记录,可以右键单击表格左侧的数字,并选择一个上下文菜单项。

table_view_menu    add_field

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.6_maps_and_layers.html b/docs/3.6_maps_and_layers.html index 22bdb790..6192877e 100644 --- a/docs/3.6_maps_and_layers.html +++ b/docs/3.6_maps_and_layers.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.6 地图和图层 | MicroCity笔记 + 3.6 地图和图层 | MicroCity笔记 - + -

3.6 地图和图层

In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid.

Opening, Creating, Saving, Printing and Closing Maps

Because Maps are based on Shapes and Grids, they can not be saved or opened independently, but can be saved or opened along with a MicroCity Project (*.mprj). Creating a Map is by double clicking a Shapes or Grid from the Data Tab of the Workspace Panel. A Map window contains four coordinate bars which can be used to locate objects (see below). A Map can also be printed or closed from the context menu of the Maps Tab of the Workspace Panel.

map_coordinates   map_menu

Adding, Moving, Hiding and Closing Layers in a Map

A Map can have multiple Layers, each of them represents a data item. One can add a Layer to a Map by double clicking a Shapes or a Grid from the Data Tab. A lower layer can be obscured by upper layers. One can move a layer by dragging, hide a layer by double clicking and close a layer through the menu (as shown below).

add_layer    layer_menu

Controlling Map Views

When a data item or a layer is selected, this layer is called the active layer. One can toggle the Action button b_action to select and edit an object in the active layer. By toggling the Zoom b_zoom or Pan b_pan botton, the map can zoomed in, zoomed out or panned. If one lose in a map, he can use the Zoom to Full Extent b_zfull button to get a full view of the map. Other zoom controlling buttons b_zlastb_znextb_zactiveb_zsel can be used to facilitate the map browsing.

The Synchronise b_sync button can be used if you want compare difference between two or more maps. The Ruler b_ruler button can be used to meassure distances. Note that, by default, the unit of the distances measured is kilometer under the coordinate system of Earth. One can change the coordinate system to Non-Earth from the Settings Panel of the Map, and get Cartesian distance without unit.

One can create a 3D surface map by clicking 3D b_3d button, which need a appropriately sized Grid (see 3.3).

Last Updated:
Contributors: huuhghhgyg
- +

3.6 地图和图层

在MicroCity中,形状网格可以显示在地图中。每个地图可以包含多个图层,每个图层对应一个形状或一个网格

打开、创建、保存、打印和关闭地图

由于地图是基于形状网格的,它们不能独立保存或打开,但可以与一个MicroCity项目(*.mprj)一同保存或打开。创建一个地图是通过在工作区面板的数据选项卡中双击一个形状网格来实现的。地图窗口包含四个坐标栏,可用于定位对象(见下文)。地图也可以通过工作区面板的地图选项卡的上下文菜单进行打印或关闭。

map_coordinates   map_menu

在地图中添加、移动、隐藏和关闭图层

一个地图可以有多个图层,每个图层表示一个数据项。可以通过在数据选项卡中双击一个形状网格来将一个图层添加到一个地图中。较低的图层可以被上面的图层遮挡。可以通过拖动来移动一个图层,通过双击来隐藏一个图层,通过菜单来关闭一个图层(如下所示)。

add_layer    layer_menu

控制地图视图

当选择一个数据项或图层时,该图层被称为活动图层。可以切换操作按钮b_action来选择和编辑活动图层中的对象。通过切换缩放按钮b_zoom平移按钮b_pan,可以对地图进行缩放和平移操作。如果在地图中迷失了方向,可以使用缩放至全图范围按钮b_zfull来查看整个地图。其他的缩放控制按钮b_zlastb_znextb_zactiveb_zsel可用于方便地浏览地图。

如果要比较两个或多个地图之间的差异,可以使用同步按钮b_sync。可以使用尺子按钮b_ruler测量距离。需要注意的是,默认情况下,在地球坐标系下测得的距离单位是公里。可以在地图的设置面板中将坐标系更改为非地球,从而获取没有单位的笛卡尔距离。

点击3D按钮b_3d可以创建一个3D表面地图,需要一个适当大小的网格(参见3.3)来实现。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/3.7_modules.html b/docs/3.7_modules.html index 898fb941..55174ee8 100644 --- a/docs/3.7_modules.html +++ b/docs/3.7_modules.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3.7 拓展模块 | MicroCity笔记 + 3.7 拓展模块 | MicroCity笔记 - + -

3.7 拓展模块

The functionality of MicroCity can be extended by modules, one type of which is SAGA Moduleopen in new window (*.dll). SAGA Modules contains many useful libraries for Shapes and Grids. Another type of Module is MicroCity Script (*.mcs), which can be edited and debugged with icon_script_editorScriptEditor (see 4.1).

Loading, Closing and Executing Modules

Modules can be loaded to MicroCity by clicking Load button button or Modules->Load Module Library menu item. The Modules Tab of the Workspace Panel will display the loaded Librariesicon_module_lib (each of which corresponding to a file) and their inside Modules icon_module. One can close or reload a Module Library from the context menu. Executing a moule has many ways: double clicking it, clicking the Execute button from the Settings Panel, or click the Execute context menu item. One can also Debug a MicroCity Script module by clicking the Debug context menu item, that needs the ScriptEditor running in the background. MicroCity can also capture runtime errors and pause the execution of modules.

module_file_menu    module_menu

Accelerating, Stopping the Execution of a Module

MicroCity Script module is created with Luaopen in new window language which is very fast. In some cases, if you want much more faster execution speed, you can click the icon_module_lib Module Libraries in the Modules Tab of the Workspace Panel and switch the Script Running Mode in the Settings Panel from the Safe Mode to the Fast Mode. Then MicroCity will use LuaJITopen in new window to execute modules.

If a module is being executed, one can stop it by click the Execute button in the corresponding Settings. In Safe Mode the execution can be immediately stopped, but in Fast Mode the stopping is depend on the GetReady() function called in the script (see 4.2.

module_libraries_settings    module_settings

Last Updated:
Contributors: huuhghhgyg
- +

3.7 拓展模块

MicroCity的功能可以通过模块进行拓展,其中之一是SAGA模块open in new window(*.dll)。SAGA模块包含许多有用的形状(Shapes)网格(Grids)库。另一种类型的模块是MicroCity脚本(*.mcs),可以使用ScriptEditor图标进行编辑和调试(请参阅4.1)。

加载、关闭和执行模块

可以通过点击加载按钮加载按钮模块->加载模块库菜单项将模块加载到MicroCity中。工作区面板的模块选项卡将显示已加载的库文件模块库图标(每个对应一个文件)及其包含的模块模块图标。可以通过上下文菜单关闭或重新加载模块库。执行模块有多种方式:双击模块,点击设置面板的执行按钮,或点击执行上下文菜单项。还可以通过点击调试上下文菜单项来调试MicroCity脚本模块,这需要后台运行ScriptEditor。MicroCity还可以捕获运行时错误并暂停模块的执行。

module_file_menu    module_menu

加速、停止模块的执行

MicroCity Script 模块是使用非常快速的 Luaopen in new window 语言创建的。在某些情况下,如果您想要更快的执行速度,可以在 工作区 面板的 模块 标签中点击 icon_module_lib 模块库,然后在 设置 面板中将 脚本运行模式安全模式 切换到 快速模式。然后 MicroCity 将使用 LuaJITopen in new window 来执行模块。

如果一个模块正在被执行,可以通过点击相应的 设置 中的 执行 按钮来停止它。在 安全模式 下,执行可以立即停止,但在 快速模式 下,停止操作取决于脚本中调用的 GetReady() 函数(参见 4.2)。

module_libraries_settings    module_settings

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.1_si_overview.html b/docs/4.1_si_overview.html index de35414d..a9b9a4ad 100644 --- a/docs/4.1_si_overview.html +++ b/docs/4.1_si_overview.html @@ -22,14 +22,14 @@ document.documentElement.classList.toggle('dark', true); } - 4.1 脚本概览 | MicroCity笔记 + 4.1 脚本概览 | MicroCity笔记 - + -

4.1 脚本概览

MicroCity uses Modules (see 3.7) to extend its functionalities. One type of the modules is MicroCity Script (*.mcs) which can be edited and debugged in the iconScriptEditor.

The Script Editor

scritp_editor

Coding and Debugging MicroCity Scripts

ScriptEditor is based on ZeroBraneopen in new window. One can find detailed information there. For debugging, you should keep iconScript Editor being opened. Then right click the module from iconMicroCity and choose Debug item in the context menu (see 3.7). The execution can be indicated in the Code View of ScriptEditor. You can control the execution and watch variables with Debug Buttons.

The Lua Language and Embedded Functions

MicroCity uses Lua 5.1open in new window as its script language. One can find the reference manual there. MicroCity embeds many useful funtions in Lua, which can not only control user interfaces, manipulate data, but also can solve mathematical models and sun simulations. You should read following chapters for more information.

Conventions in this reference:
There are four major data types in Lua can be passed though embedded functions as parameters, namely Number, Boolean, String and Object. The type Object includes builtin Lua objects, such as Table, Function adn Thread..., as well as MicroCity objects, such as Shapes, Grid, Table and Scene.... To clarify the parameter type in embedded functions, we use capitalization, quotation mark and semantic information to avoid ambiguities in function descriptions. A lowercase word of a paramter means a Number. Sometimes, to present an integer parameter, a letter 'i' followed by a word is used, like iField. Starting with the letter 'b' and followed by a word means a Boolean, like bShow. A quoted word means a String. A capitalized word means an Object or a keyword. Following is an example of a embedded function description.

AddParameter (Module, ParentNode, "Value",  "id" [, default = 0])
-

In this case, the Module parameter should be a Module object. The ParentNode parameter should be a Node object, but it act as a parent Node. The "Value" parameter is a string, but it represent the builtin type Value in MicroCity, so this string can not be changed. The "id" parameter should be a user specified string. The default parameter is a number. The contents in a pair of '[' and ']' are optional. The character '|' among parameters means "or".

Encoding formats:
MicroCity uses ANSI encoding format to read and write data, such as shp, txt, csv and dbf. ScriptEditor and the embedded funtions use UTF-8 encoding format to read and write data, such as txt or csv.

Last Updated:
Contributors: huuhghhgyg
- +

4.1 脚本概览

MicroCity使用模块(详见3.7)来扩展其功能。模块的一种类型是MicroCity脚本(*.mcs),可以在iconScriptEditor中进行编辑和调试。

脚本编辑器

scritp_editor

编码和调试MicroCity脚本

ScriptEditor基于ZeroBraneopen in new window。可以在那里找到详细的信息。要进行调试,您应该保持iconScript Editor打开。然后从iconMicroCity中右键点击模块,选择上下文菜单中的调试项(详见3.7)。执行过程可以在ScriptEditorCode View中显示。您可以使用调试按钮控制执行并查看变量。

Lua语言和嵌入函数

MicroCity使用Lua 5.1open in new window作为其脚本语言。可以在那里找到参考手册。MicroCity在Lua中嵌入了许多有用的函数,不仅可以控制用户界面、操作数据,还可以解决数学模型和太阳模拟等问题。请阅读以下章节以获取更多信息。

本参考资料中的约定:
Lua中有四种主要的数据类型可以作为参数通过嵌入函数传递,分别是数字(Number)布尔值(Boolean)字符串(String)对象(Object)对象类型包括内置的Lua对象,如表(Table)函数(Function)线程(Thread),以及MicroCity对象,如形状(Shapes)网格(Grid)表(Table)场景(Scene)。为了明确嵌入函数中的参数类型,在函数描述中我们使用大写、引号和语义信息来避免歧义。参数的小写单词表示数字。有时候为了表示整数参数,会在单词后面加上字母'i',如iField。以字母'b'开头并跟随一个单词表示布尔值,如bShow。用引号括起来的单词表示字符串。大写的单词表示对象或关键字。以下是一个嵌入函数描述的示例。

AddParameter(Module, ParentNode, "Value", "id" [, default = 0])
+

在这个例子中,Module参数应该是一个Module对象。ParentNode参数应该是一个Node对象,但它作为一个父节点。"Value"参数是一个字符串,但它代表MicroCity中的内置类型Value,因此这个字符串是不能改变的。*"id"*参数应该是一个用户指定的字符串。default参数是一个数字。方括号中的内容是可选的。参数之间的竖线表示"或"的关系。

编码格式:
MicroCity使用ANSI编码格式读写数据,比如shp、txt、csv和dbf等。ScriptEditor和嵌入函数使用UTF-8编码格式读写数据,比如txt或csv等。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.2_ui_control.html b/docs/4.2_ui_control.html index bc3b7a20..aa73e97e 100644 --- a/docs/4.2_ui_control.html +++ b/docs/4.2_ui_control.html @@ -22,42 +22,42 @@ document.documentElement.classList.toggle('dark', true); } - 4.2 控制用户界面 | MicroCity笔记 + 4.2 控制用户界面 | MicroCity笔记 - + -

4.2 控制用户界面

Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be found in the "user_interface" folder of the Project Tab in iconScriptEditor.

Basic User Interfaces

Print ("hello" [,...])
-

Prints values in the Messages Panel.

Note ("hello" [,...])
-

Notifies users and pauses the execution.

SetProcessText ("processing")
-

Sets a text at the bottom left corner of MicroCity.

SetProgress (position, range)
-

Sets the progress bar of position/range that locates at the bottom right conner of MicroCity.

Sleep (milliseconds)
-

Pauses the execution for milliseconds.

GetReady ()
-

MicroCity shares the same thread with the lua engine. Heavy calculations in lua will block the MicroCity interface. Use this function inside can let the MicroCity interface respond to user operations. Returns false if user cancel the current execution.

GetClickXY ()
-

Returns x,y where a user clicked at a Map View.

GetDragExtent ()
-

Returns bottom-left and top-right corner coordinate: Lx, By, Rx, Ty, which a user used mouse to drag a rectangle in a Map View.

Data Objects

PATH
-

Internal global variable that holds a string of current working directory, such as "c:\microcity".

Open (".\\shapes.shp" [, ".\\grid.sgrd" [, ".\\table.dbf" [, ".\\scene.m3d" , ...]]])
-

Opens and returns Shapes, Table, Grid and Scene object from current working directory or opened data.

Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel)
-

Closes an opened or created Shapes, Table, Grid, Scene, Network, RndEngine or LPModel object.

Update (Shapes|Grid|Table [, bShow = ture])
-

Update current changes of Shapes, Grid or Table object in MicroCity. The bShow indicates whether to create a view of the object. Returns false if user cancel the current execution.

CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...])
-

Creates a Map View to show objects which can be arranged in layers by their order in the parameters.

Modules and Parameters

AddModule ("Function" [, "name"]) 
-

This function can add a lua function as a module to current module library. The module's default name is the function's name. Returns a Module object.

AddParameter (Module, ParentNode, "Node",   "id")
-AddParameter (Module, ParentNode, "Value",  "id" [, default = 0])
-AddParameter (Module, ParentNode, "Range",  "id" [, low = 0 [,  high = 1]])
-AddParameter (Module, ParentNode, "Check",  "id" [, default = 0])
-AddParameter (Module, ParentNode, "String", "id" [, "string" = "")
-AddParameter (Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]])
-AddParameter (Module, ParentNode, "File",   "id" [, "c:\\default.txt" = ""])
-AddParameter (Module, ParentNode, "Color",  "id" [, "color" = "255 255 255")
-AddParameter (Module, ParentNode, "Shapes", "id")
-AddParameter (Module, ParentNode, "Grid",   "id")
-AddParameter (Module, ParentNode, "Scene",  "id")
-AddParameter (Module, ParentNode, "Table",  "id")
-AddParameter (Module, ParentNode, "Field",  "id")
-

These functions can add a parameter to a module's settings panel. Returns corresponding values or an object. The ParentNode can be set to the first return of a AddParameter function. If "Field" is set at the third place, the parent_node can be set to a Table or Shapes object to get its attributes table's head.

GetParameter (Shapes|Table|Grid|Scene|Module, "id")
-

Returns the parameter specified by "id" from the object's settings panel.

SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
-

Sets the parameter specified by "id" in the object's settings panel. Returns true if succeed. Note that the choice parameter should start from 1. A parameter's "id" can be found in the parameter's helper text shown as below.

shot

Last Updated:
Contributors: huuhghhgyg
- +

4.2 控制用户界面

Microcity Script 可用于控制用户界面上的一些功能,包括模块、数据对象、消息等等。在 iconScriptEditor项目标签的"user_interface"文件夹中可以找到一些示例代码。

基本用户界面

Print ("hello" [,...])
+

消息面板中打印数值。

Note ("hello" [,...])
+

通知用户并暂停执行。

SetProcessText ("processing")
+

MicroCity的左下角设置一个文本。

SetProgress (position, range)
+

设置位于MicroCity右下角的进度条的 position/range 值。

Sleep (milliseconds)
+

暂停执行 milliseconds 毫秒。

GetReady ()
+

MicroCity与Lua引擎共享同一线程。Lua中的计算量较大会阻塞MicroCity界面。在内部使用该函数可以使MicroCity界面响应用户操作。如果用户取消当前执行,则返回false。

GetClickXY ()
+

返回用户在地图视图中点击的 x,y 坐标。

GetDragExtent ()
+

返回用户使用鼠标在地图视图中拖动矩形时的底部左侧和顶部右侧坐标:Lx,By,Rx,Ty。

数据对象

PATH
+

内部全局变量,保存当前工作目录的字符串,例如"c:\microcity"。

Open (".\\shapes.shp" [, ".\\grid.sgrd" [, ".\\table.dbf" [, ".\\scene.m3d" , ...]]])
+

从当前工作目录或打开的数据中打开并返回ShapesTableGridScene对象。

Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel)
+

关闭已打开或创建的ShapesTableGridSceneNetworkRndEngineLPModel对象。

Update (Shapes|Grid|Table [, bShow = true])
+

MicroCity中更新ShapesGridTable对象的当前更改。bShow表示是否创建对象的视图。如果用户取消当前执行,返回false。

CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...])
+

创建一个地图视图,以显示按参数中的顺序分层排列的对象。

模块和参数

AddModule ("Function" [, "name"]) 
+

此函数可以将Lua函数作为模块添加到当前模块库。模块的默认名称是函数的名称。返回一个Module对象。

function AddParameter(Module, ParentNode, "Node", "id")
+function AddParameter(Module, ParentNode, "Value", "id" [, default = 0])
+function AddParameter(Module, ParentNode, "Range", "id" [, low = 0 [, high = 1]])
+function AddParameter(Module, ParentNode, "Check", "id" [, default = 0])
+function AddParameter(Module, ParentNode, "String", "id" [, "string" = "")
+function AddParameter(Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]])
+function AddParameter(Module, ParentNode, "File", "id" [, "c:\\default.txt" = ""])
+function AddParameter(Module, ParentNode, "Color", "id" [, "color" = "255 255 255")
+function AddParameter(Module, ParentNode, "Shapes", "id")
+function AddParameter(Module, ParentNode, "Grid", "id")
+function AddParameter(Module, ParentNode, "Scene", "id")
+function AddParameter(Module, ParentNode, "Table", "id")
+function AddParameter(Module, ParentNode, "Field", "id")
+

这些函数可以在模块的设置面板中添加参数。返回相应的值或对象。ParentNode 可以设置为 AddParameter 函数的第一个返回值。如果 "Field" 在第三个位置,则 parent_node 可以设置为 TableShapes 对象,以获取其属性表的头部。

GetParameter(Shapes|Table|Grid|Scene|Module, "id")
+

从对象的设置面板中返回指定的参数。

SetParameter(Shapes|Table|Grid|Scene|Module, "id", Number | "String" | Object)
+

在对象的设置面板中设置指定的参数。如果成功,则返回 true。请注意,选择参数应从1开始。可以在下图中的参数帮助文本中找到参数的 "id"

shot

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.3_shapes_and_tables.html b/docs/4.3_shapes_and_tables.html index 01eb6ecf..d9a94bd7 100644 --- a/docs/4.3_shapes_and_tables.html +++ b/docs/4.3_shapes_and_tables.html @@ -22,52 +22,52 @@ document.documentElement.classList.toggle('dark', true); } - 4.3 矢量图形和表格 | MicroCity笔记 + 4.3 矢量图形和表格 | MicroCity笔记 - + -

4.3 矢量图形和表格

Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 and 3.2. Because Shapes can be treated as Tables with extra field with geographic data, some of embeded functions for tabular data manipulation can be used both in Shapes and Tables. Sample codes for this chapter can be found in the "shapes_samples" folder of the Project Tab in iconScriptEditor.

Tabular Data Manipulation

CreateShapes ("name", "Point|Line|Polygon")
-

Returns a Shapes object.

CreateTable ("Name")
-

Returns a Table object.

GetFieldCount (Shapes|Table)
-

Returns the number of fields in a Shapes or Table

GetField (Shapes|Table, iField)
-

Inputs the index (starts from 1) of a field and returns the field name and type ("Int", "Float", "Double" or "String).

AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...])
-

Adds fields to a *Table or Shapes and returns booleans (true or false) by order.

DelField (Shapes|Table, iField)
-

Returns true if successfully delete a field.

GetRecCount (Shapes|Table)
-

Returns the total number of records in a Shapes or Table.

AddRecord (Shapes|Table)
-

Adds a record to a Shapes or Table and returns the index.

GetValue (Shapes|Table, "field_name", index1 [, index2, ...])
-

Retrieve values from a specified field and indexes of a Shapes or Table. Returns multiple values by the order of indexes.

SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...])
-

Sets values for a specified field and indexes of a Shapes or Table.

Geographic Data Manipulation

GetSelections (Shapes)
-

Returns selected shape objects from a Shapes.

GetShape (Shapes, index1 [, index2, ...])
-

Returns Shape objects from a Shapes by the order of indexes.

AddShape (Shapes, Shape)
-

Adds a Shape object to a Shapes and returns its index.

AddShape (Shapes [, x1, y1, x2, y2, ...])
-

Adds a Shape object to a Shapes which defined as points. Returns the Shape object and index.

DelShape (Shape|Shapes)
-

Deletes a Shape or Shapes object and returns ture if successful.

AddPoint (Shape, x, y [, iPart = 1])
-

Adds a point to a Shape and returns ture if successful.

InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
-

Inserts a point to a Shape and returns ture if successful.

SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
-

Sets a point coordinates in a Shape and returns ture if successful.

DelPoint (Shape, iPoint [, iPart=1])
-

Deletes a point at position iPoint from a Shape and returns ture if successful..

DelPart (Shape, iPart)
-

Deletes a part from a Shape and returns ture if successful.

GetPartCount (Shape)
-

Returns the number of parts in a Shape.

GetPointCount (Shape [, iPart])
-

Returns the number of points in a Shape.

GetPointXY (Shape [, iPoint [, iPart = 1]])
-

Returns all points' coordinates: x1, y1, x2, y2, ... from a Shape or a specified point's coordinate.

CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...])
-

Copys Shape objects to a target Shapes with relative translation (dx, dy) and returns new Shape objects.

MoveShapeTo (dx, dy, Shape1 [, Shape2, ...])
-

Translates Shape objects to its relative position (dx, dy).

GetCenterXY (Shapes)
-

Returns the center coordinate (x, y) of a Shapes.

GetCenterXY (Shapes, index1 [, index2, ...])
-

Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects specified by indexes in a Shapes.

GetCenterXY (Shape1 [, Shape2, ...])
-

Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects.

GetDistance (x1, y1, x2, y2 [, x3, y3, ...])
-

Returns the total distance between every two pairs of coordinates (x, y).

GetShapeLen (Shape1 [, Shape2, ...])
-

Returns lengths of Shape objects.

GetShapeArea (Shape1 [, Shape2, ...])
-

Returns areas of Shape objects.

GetShapeType (Shape|Shapes)
-

Returns the type ("Point", "Line" or "Polygon") of the a Shapes or Shape object.

GetExtent (Shapes)
-

Returns the extent coordinates (Lx, By, Rx, Ty) of a Shapes's extent.

GetExtent (Shapes, index)
-

Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape indexed in a Shapes.

GetExtent (Shape)
-

Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape.

GetIntersection (ShapeA, ShapeB)
-

Returns a Shape (Point, Line or Polygon) object of the intersection of two Shapes.

GetValue (Shape, "field_name")
-

Returns the value of specified field of a Shape.

SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...])
-

Sets values in different fiedds for a Shape.

SetCoorSys ("Earth"|"Non-Earth")
-

Sets coordinate system. If using "Earth", distances, lenths and areas are calculated according to the earth ellipsoid coordinate system. By default the "Non-Earth" is used, which is cartesian coordinate system.

Last Updated:
Contributors: huuhghhgyg
- +

4.3 矢量图形和表格

用户可以使用 MicroCity 脚本操作 形状(Shapes)表格(Tables)。有关形状(Shapes)的详细数据结构,您可以参考上一章节 2.23.2。由于形状(Shapes)可以被视为带有地理数据的表格(Tables),因此一些用于表格数据操作的嵌入函数可以在**形状(Shapes)表格(Tables)中同时使用。本章节的示例代码可以在项目(Project)**选项卡的"shapes_samples"文件夹中找到,该文件夹位于 iconScriptEditor

表格数据操作

CreateShapes ("name", "Point|Line|Polygon")
+

返回一个 Shapes 对象。

CreateTable ("Name")
+

返回一个 Table 对象。

GetFieldCount (Shapes|Table)
+

返回 ShapesTable 中字段的数量。

GetField (Shapes|Table, iField)
+

输入字段的索引(从 1 开始)并返回字段名和类型("Int"、"Float"、"Double" 或 "String")。

AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...])
+

向 *Table 或 Shapes 添加字段,并按照顺序返回布尔值(truefalse)。

DelField (Shapes|Table, iField)
+

成功删除字段时返回 true

GetRecCount (Shapes|Table)
+

返回 ShapesTable 中的记录总数。

AddRecord (Shapes|Table)
+

ShapesTable 添加一条记录,并返回该记录的索引。

GetValue (Shapes|Table, "field_name", index1 [, index2, ...])
+

从指定字段和 ShapesTable 的索引中检索值。按照索引的顺序返回多个值。

SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...])
+

为指定字段和 ShapesTable 的索引设置值。

地理数据操作

GetSelections (Shapes)
+

Shapes中返回所选的形状对象。

GetShape (Shapes, index1 [, index2, ...])
+

按索引顺序从Shapes中返回Shape对象。

AddShape (Shapes, Shape)
+

Shape对象添加到Shapes中并返回其索引。

AddShape (Shapes [, x1, y1, x2, y2, ...])
+

将定义为点的Shape对象添加到Shapes中。返回Shape对象和索引。

DelShape (Shape|Shapes)
+

删除一个ShapeShapes对象,如果成功则返回true。

AddPoint (Shape, x, y [, iPart = 1])
+

Shape中添加一个点,如果成功则返回true。

InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
+

Shape中插入一个点,如果成功则返回true。

SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
+

设置Shape中的点坐标,如果成功则返回true。

DelPoint (Shape, iPoint [, iPart=1])
+

Shape中删除位置为iPoint的一个点,如果成功则返回true。

DelPart (Shape, iPart)
+

Shape中删除一个部分,如果成功则返回true。

GetPartCount (Shape)
+

返回Shape中部分的数量。

GetPointCount (Shape [, iPart])
+

返回Shape中点的数量。

GetPointXY (Shape [, iPoint [, iPart = 1]])
+

Shape或指定点的坐标中返回所有点的坐标:x1,y1,x2,y2,...。

CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...])
+

Shape对象复制到目标Shapes,并进行相对平移(dx,dy),返回新的Shape对象。

MoveShapeTo (dx, dy, Shape1 [, Shape2, ...])
+

Shape对象平移到其相对位置(dx,dy)。

GetCenterXY (Shapes)
+

返回Shapes的中心坐标(x,y)。

GetCenterXY (Shapes, index1 [, index2, ...])
+

返回在Shapes中由索引指定的Shape对象的中心坐标(x1,y1,x2,y2,...)。

GetCenterXY (Shape1 [, Shape2, ...])
+

返回Shape对象的中心坐标(x1,y1,x2,y2,...)。

GetDistance (x1, y1, x2, y2 [, x3, y3, ...])
+

返回每两个坐标(x,y)对之间的总距离。

GetShapeLen (Shape1 [, Shape2, ...])
+

返回Shape对象的长度。

GetShapeArea (Shape1 [, Shape2, ...])
+

返回Shape对象的面积。

GetShapeType (Shape|Shapes)
+

返回ShapesShape对象的类型("Point","Line"或"Polygon")。

GetExtent (Shapes)
+

返回Shapes的范围坐标(Lx,By,Rx,Ty)。

GetExtent (Shapes, index)
+

返回Shapes中索引为index的Shape的范围坐标(Lx,By,Rx,Ty)。

GetExtent (Shape)
+

返回Shape的范围坐标(Lx,By,Rx,Ty)。

GetIntersection (ShapeA, ShapeB)
+

返回两个Shapes的交集的ShapePointLinePolygon)对象。

GetValue (Shape, "field_name")
+

返回Shape的指定字段的值。

SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...])
+

Shape的不同字段设置值。

SetCoorSys ("Earth"|"Non-Earth")
+

设置坐标系统。如果使用"Earth",距离、长度和面积将根据地球椭球坐标系统计算。默认情况下使用"Non-Earth",即笛卡尔坐标系统。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.4_grids.html b/docs/4.4_grids.html index fc03bf11..e1893ea8 100644 --- a/docs/4.4_grids.html +++ b/docs/4.4_grids.html @@ -22,26 +22,26 @@ document.documentElement.classList.toggle('dark', true); } - 4.4 栅格图形 | MicroCity笔记 + 4.4 栅格图形 | MicroCity笔记 - + -

4.4 栅格图形

Grids in MicroCity have simple structure (3.3) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be found in the "grid_samples" folder of the Project Tab in iconScriptEditor.

Cellular Data Manipulation

CreateGrid ("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]])
-

Returns a Grid object.

GetCellSize (Grid)
-

Returns the Cellsize value of a Grid.

GetGridMaxXY (Grid)
-

Returns XMax, YMax of a Grid.

ConvertToGridXY (Grid, x1, y1 [, x2, y2, ...])
-

Converts real coordinates to coordinates in a Grid. Returns X1, Y1, X2, Y2, ... .

ShapeToGrid (Grid, Shape, value)
-

Rasterizes a Shape in a Grid. The cell values will be set according to the covering area and the inputed value.

ShapeToGrid (Grid, Shapes, "field_name")
-

Rasterizes all Shape objects in a Shapes. The cell values will be set according to the covering area and the values of Shapes field.

GetValue (Grid, X1, Y1 [, X2, Y2, ...])
-

Returns cells' (specified by Grid coordinates) values: value1, value2, ... .

SetValue (Grid, value, X1, Y1 [, X2, Y2, ...])
-

Sets values for cells specified by Grid coordinates.

GetCenterXY (Grid)
-

Returns the center real coordinate (x, y) of a Grid.

GetCenterXY (Grid, X1, Y1 [, X2, Y2, ...])
-

Returns the real coordinates of cells' centers: x1, y1, x2, y2, ... .

GetExtent (Grid)
-

Returns the leftbottom and righttop corner of a Grid's extent: Lx, By, Rx, Ty.

GetExtent (Grid, X, Y)
-

Returns the leftbottom and righttop corner of a cell's extent: Lx, By, Rx, Ty.

GetFractalDim (Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0])
-

Calculates fractal dimension of the specified area in a Grid. Returns dimension, RSQ of linear regression, and the number of boxes in every fold.

Last Updated:
Contributors: huuhghhgyg
- +

4.4 栅格图形

在MicroCity中,栅格图形具有简单的结构(3.3),但是如果在其上应用算法,可以高效利用时间和空间。本章的示例代码可以在项目选项卡的"grid_samples"文件夹中找到,该选项卡位于iconScriptEditor中。

栅格数据操作

CreateGrid("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]])
+

返回一个Grid对象。

GetCellSize(Grid)
+

返回Grid的Cellsize值。

GetGridMaxXY(Grid)
+

返回Grid的XMax和YMax值。

ConvertToGridXY(Grid, x1, y1 [, x2, y2, ...])
+

将实际坐标转换为Grid中的坐标。返回X1,Y1,X2,Y2,...。

ShapeToGrid(Grid, Shape, value)
+

Grid中将Shape栅格化。栅格单元值将根据覆盖面积和输入的值设置。

ShapeToGrid(Grid, Shapes, "field_name")
+

Shapes中栅格化所有的Shape对象。栅格单元值将根据覆盖面积和Shapes字段的值设置。

GetValue(Grid, X1, Y1 [, X2, Y2, ...])
+

返回指定Grid坐标的单元格值:value1,value2,...。

SetValue(Grid, value, X1, Y1 [, X2, Y2, ...])
+

设置指定Grid坐标单元的值。

GetCenterXY(Grid)
+

返回Grid的中心实际坐标(x,y)。

GetCenterXY(Grid, X1, Y1 [, X2, Y2, ...])
+

返回单元格中心的实际坐标:x1,y1,x2,y2,...。

GetExtent(Grid)
+

返回Grid范围的左下角和右上角坐标:Lx,By,Rx,Ty。

GetExtent(Grid, X, Y)
+

返回单元格范围的左下角和右上角坐标:Lx,By,Rx,Ty。

GetFractalDim(Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0])
+

计算Grid中指定区域的分形维度。返回维度,线性回归的RSQ值以及每个折叠中的盒子数。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.5_3d_scenes.html b/docs/4.5_3d_scenes.html index 7b44ebac..5014e3e3 100644 --- a/docs/4.5_3d_scenes.html +++ b/docs/4.5_3d_scenes.html @@ -22,41 +22,41 @@ document.documentElement.classList.toggle('dark', true); } - 4.5 3D场景 | MicroCity笔记 + 4.5 3D场景 | MicroCity笔记 - + -

4.5 3D场景

Scenes and inside 3D objects (3.4) can be scripted. Sample codes for this chapter can be found in the "3d_samples" folder of the Project Tab in iconScriptEditor.

3D Scene and Object Manipulation

CreateScene ("Title" [, RotSpeed=1] [, TransSpeed=1])
-

Creates a new 3d scene and returns the object.

AddZipTo3DPath (Scene, "filename.zip")
-

Adds a zip file to the search directory and returns true if succeed. It is useful for collecting a large amount of files.

LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg")
-

Loads six image files as the skybox of a 3d scene.

LoadObject (Scene, "filename.3ds" [,shadow = false [, AnimationSpeed]])
-

Loads a 3d object from a file and returns the object.

AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255])
-

Adds a light object and returns the object.

Add3DLabel(Scene, "label" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]])
-

Adds a 3D label at (0,0,0) and returns the object.

Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0])
-

Adds a 3D line object frome (x1, y1, z1) to (x2, y2, z2) and retruns the object.

Add3DRect (Scene, length, width [, r = 180, g = 180, b = 180])
-

Adds a 3D rectangular object from (-length/2,0,-width/2) to (length/2,0,width/2) and returns the object.

Add3DBox (Scene, length, width, height [, r = 180, g = 180, b = 180 [, bShowEdge = true]])
-

Adds a 3D box object from (-length/2,-height/2,-width/2) to (length/2,height/2,width/2) and returns the object.

AddSphere (Scene, radius [, polycount = 16 [, r = 180, g = 180, b = 180]])
-

Adds a sphere at (0,0,0) and returns the object. If the radius parameter is less than 0, returns an invisible object.

GetTexture (Object)
-

Returns the texture files of a object: "filename1", "filename2", ... .

LoadTexture (Scene, Object, "filename1" [, "filename2", ...])
-

Loads texture files to an object.

SetPosition (Object, x, y, z [, absolute = false])
-

Sets the position of an object relative to its parent (or the absolute position to the scene).

GetPosition (Object [, absolute = false])
-

Gets the position of an object relative to its parent (or the absolute position to the scene).

SetRotation (Object, rx, ry, rz [, absolute = false])
-

Sets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene).

GetRotation (Object [, absolute = false])
-

Gets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene).

SetScale (Object, sx, sy, sz)
-

Sets the scale of an object.

GetScale (Object)
-

Gets the scale of an object.

SetParent (Object, Parent)
-

Attaches an object to another object as a child.

GetParent (Object)
-

Gets the parent of an object.

SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]])
-

Sets the ID, position, rotation and scale of an object.

DelObject (Object)
-

Deletes an object.

SetCamera (Scene, x, y, z [,Tx, Ty, Tz])
-

Sets the position and target of the scene camera.

GetCamera (Scene)
-

Gets the camera object of a 3d scene and its position and targt.

GetSelections (Scene)
-

Returns selected objects from a 3d scene.

GetObjectID (Object1 [, Object2, ...])
-

Returns "id"s of objects.

SetObjectID (Object, "id")
-

Sets the id of an object.

GetObject (Scene, "id")
-

Finds an object by its id.

Last Updated:
Contributors: huuhghhgyg
- +

4.5 3D场景

场景3D物体3.4)可以进行脚本编写。本章节的示例代码可以在项目标签中的"3d_samples"文件夹中的图标ScriptEditor中找到。

3D场景和物体操作

CreateScene ("标题" [, RotSpeed=1] [, TransSpeed=1])
+

创建一个新的3D场景并返回物体。

AddZipTo3DPath (Scene, "文件名.zip")
+

将一个zip文件添加到搜索目录中,并在成功时返回true。这对于收集大量文件很有用。

LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg")
+

将六个图像文件加载为3D场景的天空盒。

LoadObject (Scene, "文件名.3ds" [,shadow = false [, AnimationSpeed]])
+

从文件中加载一个3D物体,并返回该物体。

AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255])
+

添加一个光源物体,并返回该物体。

Add3DLabel(Scene, "标签" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]])
+

在坐标(0,0,0)处添加一个3D标签,并返回该物体。

Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0])
+

从点(x1, y1, z1)到点(x2, y2, z2)添加一个3D线物体,并返回该物体。

Add3DRect (Scene, 长度, 宽度 [, r = 180, g = 180, b = 180])
+

从(-长度/2,0,-宽度/2)到(长度/2,0,宽度/2)添加一个3D矩形物体,并返回该物体。

Add3DBox (Scene, 长度, 宽度, 高度 [, r = 180, g = 180, b = 180 [, bShowEdge = true]])
+

从(-长度/2,-高度/2,-宽度/2)到(长度/2,高度/2,宽度/2)添加一个3D盒子物体,并返回该物体。

AddSphere (Scene, 半径 [, polycount = 16 [, r = 180, g = 180, b = 180]])
+

在坐标(0,0,0)处添加一个球体,并返回该物体。如果半径参数小于0,则返回一个不可见的物体。

GetTexture (Object)
+

返回一个物体的纹理文件:"文件名1","文件名2"等等。

LoadTexture (Scene, Object, "文件名1" [, "文件名2", ...])
+

加载纹理文件到一个物体中。

SetPosition (Object, x, y, z [, absolute = false])
+

设置一个物体相对于其父物体的位置(或者绝对位置到场景)。

GetPosition (Object [, absolute = false])
+

获取一个物体相对于其父物体的位置(或者该物体在场景中的绝对位置)。

SetRotation (Object, rx, ry, rz [, absolute = false])
+

设置一个物体相对于其父物体的旋转角度(左手坐标系),以度为单位(或者该物体在场景中的绝对旋转角度)。

GetRotation (Object [, absolute = false])
+

获取一个物体相对于其父物体的旋转角度(左手坐标系),以度为单位(或者该物体在场景中的绝对旋转角度)。

SetScale (Object, sx, sy, sz)
+

设置一个物体的缩放比例。

GetScale (Object)
+

获取一个物体的缩放比例。

SetParent (Object, Parent)
+

将一个物体作为子物体附加到另一个物体上。

GetParent (Object)
+

获取一个物体的父物体。

SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]])
+

设置一个物体的id、位置、旋转和缩放。

DelObject (Object)
+

删除一个物体。

SetCamera (Scene, x, y, z [,Tx, Ty, Tz])
+

设置场景相机的位置和目标。

GetCamera (Scene)
+

获取一个3D场景的相机物体以及其位置和目标。

GetSelections (Scene)
+

从一个3D场景中返回选中的物体。

GetObjectID (Object1 [, Object2, ...])
+

返回物体的"id"。

SetObjectID (Object, "id")
+

设置一个物体的id。

GetObject (Scene, "id")
+

根据id查找一个物体。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.6_networks.html b/docs/4.6_networks.html index ba8243b0..032c6e04 100644 --- a/docs/4.6_networks.html +++ b/docs/4.6_networks.html @@ -22,33 +22,33 @@ document.documentElement.classList.toggle('dark', true); } - 4.6 网络 | MicroCity笔记 + 4.6 网络 | MicroCity笔记 - + -

4.6 网络

GIS vector data (3.2) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sample codes for this chapter can be found in the "network_samples" folder of the Project Tab in iconScriptEditor.

Network Manipulation

CreateNetwork ()
-

Creates an empty network and returns the object.

CreateNetwork (UnTopoLines)
-

Creates a network from an untopologized "line" Shapes and returns three objects: Network, Nodes (Shapes) and Links (Shapes).

CreateNetwork (Nodes, Links)
-

Creates a Network object from topologized Nodes and Links Shapes. Returns the Network object.

InitNetwork (Network, Nodes, Links)
-

Initiates a Network from a Nodes and a Links Shapes. Returns true if succeed.

AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]])
-

Adds a new link or update an existing link in the Network. Returns linkID, oID, dID, true/false for adding and true/false for updating.

AddLink (Network, Shapes|Table, index1 [, index2, ...])
-

Adds or updates links from the recordset of a Shapes or Table. Returns boolean values.

DelLink (Network, linkID)
-

Deletes a link from a Network. Returns a boolean value.

GetNearNodeID (Network, x, y [, radius=nil])
-

Gets the nearest Network nodes from a coordinate. Returns node ids.

GetNodeXY (Network, nodeID1 [, nodeID2, ...])
-

Returns the coordinates of nodes in a Network: x1, y1, x2, y2, ... .

Algorithms

GenSTPTree (Network, startID [, endID])
-

Generates a Shortest Path Spanning Tree from a node. Returns a boolean value.

GetSTPPath (Network, endID, "NodeID"|"LinkID")
-

After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link id sequence: id1, id2 ,... .

GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp")
-

After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shapes index sequence.

GetSTPPath (Network, endID, "NodeShp"|"LinkShp")
-

After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shape object sequence.

GetSTPLen (Network, endID)
-

After calling GenSTPTree call this function. Returns a Shortest Path Distance to a end node.

GetSTPLen (Network, startID, endID)
-

Gets a Shortest Path from a start node to an end node in a Network. Returns the distance.

GetSTPLen (Network, x1, y1, x2, y2)
-

Gets a Shortest Path from a start coordinate to an end coordinate in a Network. Returns the distance.

SetTrip (Network, oID, dID, amount)
-

Sets an amount of a trip from an origin to an destination.

SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]])
-

After calling SetTrip call this function. Performs the User Equilibium Traffic Assignment and returns a boolean value.

GetFlow (Network, linkID)
-

Returns the traffic flow of a specified link.

SetFlow (Network, linkID, flow)
-

Set the traffic flow of a specified link and return a boolean value.

Last Updated:
Contributors: huuhghhgyg
- +

4.6 网络

在MicroCity中,GIS矢量数据(参见3.2)可以进行拓扑操作,并应用最短路径算法用户均衡交通分配算法。本章的示例代码可以在项目选项卡的"network_samples"文件夹中找到,具体请参考iconScriptEditor

网络操作

CreateNetwork ()
+

创建一个空网络对象并返回。

CreateNetwork (UnTopoLines)
+

从未进行拓扑操作的“线”形状创建网络,并返回三个对象:网络、节点(形状)和链接(形状)。

CreateNetwork (Nodes, Links)
+

从进行了拓扑操作的节点和链接形状创建网络对象。返回网络对象。

InitNetwork (Network, Nodes, Links)
+

从节点和链接形状初始化网络。如果成功返回true。

AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]])
+

向网络中添加新的链接或更新现有链接。返回linkID、oID、dID、添加结果(true/false)和更新结果(true/false)。

AddLink (Network, Shapes|Table, index1 [, index2, ...])
+

从形状记录集或表中添加或更新链接。返回布尔值。

DelLink (Network, linkID)
+

从网络中删除链接。返回布尔值。

GetNearNodeID (Network, x, y [, radius=nil])
+

获取坐标最近的网络节点。返回节点ID。

GetNodeXY (Network, nodeID1 [, nodeID2, ...])
+

返回网络中节点的坐标:x1、y1、x2、y2,等等。

算法

GenSTPTree (Network, startID [, endID])
+

从一个节点生成最短路径生成树。返回布尔值。

GetSTPPath (Network, endID, "NodeID"|"LinkID")
+

在调用GenSTPTree之后调用该函数。返回由节点ID或链接ID序列表示的最短路径:id1、id2,等等。

GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp")
+

在调用GenSTPTree之后调用该函数。返回由节点或链接形状索引序列表示的最短路径。

GetSTPPath (Network, endID, "NodeShp"|"LinkShp")
+

在调用GenSTPTree之后调用该函数。返回由节点或链接形状对象序列表示的最短路径。

GetSTPLen (Network, endID)
+

在调用GenSTPTree之后调用该函数。返回到达目标节点的最短路径距离。

GetSTPLen (Network, startID, endID)
+

在网络中从起点节点到终点节点获取最短路径。返回距离。

GetSTPLen (Network, x1, y1, x2, y2)
+

在网络中从起点坐标到终点坐标获取最短路径。返回距离。

SetTrip (Network, oID, dID, amount)
+

设置从出发地到目的地的旅行量。

SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]])
+

在调用SetTrip之后调用该函数。执行用户均衡交通分配,并返回布尔值。

GetFlow (Network, linkID)
+

返回指定链接的交通流量。

SetFlow (Network, linkID, flow)
+

设置指定链接的交通流量,并返回布尔值。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.7_des_simulations.html b/docs/4.7_des_simulations.html index 3f976d7b..490f0145 100644 --- a/docs/4.7_des_simulations.html +++ b/docs/4.7_des_simulations.html @@ -22,29 +22,29 @@ document.documentElement.classList.toggle('dark', true); } - 4.7 离散事件模拟 | MicroCity笔记 + 4.7 离散事件仿真 | MicroCity笔记 - + -

4.7 离散事件模拟

MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, which is very useful for dynamic system analysis. Sample codes for this chapter can be found in the "simulation_samples" folder of the Project Tab in iconScriptEditor.

Random Number Generation

CreateRandEng (seed, "uniform_01")
-

Creates a binary distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "uniform_real" [, min = 0, max = 1])
-

Creates a uniform distributed real random generation engine from a seed and returns the object.

CreateRandEng (seed, "uniform_int" [, min = 0, max = 1])
-

Creates an uniform integer random generation engine from a seed and returns the object.

CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2])
-

Creates a triangle distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "bernoulli" [, p = 0])
-

Creates a bernoulli distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1])
-

Creates a cauchy distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "exponential" [, lambda = 1])
-

Creates a exponential distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "geometric" [, p = 0])
-

Creates a geometric distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "normal" [, mean = 0, sigma = 1])
-

Creates a normal distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1])
-

Creates a lognormal distributed random generation engine from a seed and returns the object.

GetNextRandom (Engine)
-

Gets a random number from a random generation engine.

Simulation Control

CreateEvent (time, Funcion [, arg1, arg2, ...])
-

Creates a future event from a Lua Function or a Lua Coroutine. Returns a Coroutine object.

ExecAllEvents ()
-

Calls this at last. It will execute all events as Lua Coroutines.

Delay ([relativeTime = 0])
-

Calls this function in a Lua Coroutine will let it first yield then resume it after the specified relative time. If the parameter relativeTime is not set, the current Coroutine will yield and won' be resumed automatically.

Resume ([time, ] Coroutine [, arg1, arg2, ...])
-

Resumes a yielded coroutine immediately or at a specified time.

GetSimTime ()
-

Returns the current simulation time.

Last Updated:
Contributors: huuhghhgyg
- +

4.7 离散事件仿真

MicroCity有一个内置的模拟时间计数和事件调度机制。它提供了几个嵌入的Lua函数来方便创建离散事件仿真,这对于动态系统分析非常有用。本章的示例代码可以在项目选项卡的“simulation_samples”文件夹中的iconScriptEditor找到。

随机数生成

CreateRandEng (seed, "uniform_01")
+

使用种子创建一个二进制分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "uniform_real" [, min = 0, max = 1])
+

使用种子创建一个服从均匀分布的实数随机数生成引擎,并返回该对象。

CreateRandEng (seed, "uniform_int" [, min = 0, max = 1])
+

使用种子创建一个服从均匀分布的整数随机数生成引擎,并返回该对象。

CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2])
+

使用种子创建一个服从三角分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "bernoulli" [, p = 0])
+

使用种子创建一个服从伯努利分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1])
+

使用种子创建一个服从柯西分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "exponential" [, lambda = 1])
+

使用种子创建一个服从指数分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "geometric" [, p = 0])
+

使用种子创建一个服从几何分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "normal" [, mean = 0, sigma = 1])
+

使用种子创建一个服从正态分布的随机数生成引擎,并返回该对象。

CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1])
+

使用种子创建一个服从对数正态分布的随机数生成引擎,并返回该对象。

GetNextRandom (Engine)
+

从随机数生成引擎中获取一个随机数。

模拟控制

CreateEvent (time, Funcion [, arg1, arg2, ...])
+

Lua FunctionLua Coroutine创建一个将来的事件,并返回一个Coroutine对象。

ExecAllEvents ()
+

最后调用这个函数。它会将所有事件作为Lua Coroutines执行。

Delay ([relativeTime = 0])
+

Lua Coroutine中调用这个函数,让它先暂停一段指定的相对时间,然后再恢复执行。如果没有设置参数relativeTime,当前的Coroutine将暂停而不会自动恢复。

Resume ([time, ] Coroutine [, arg1, arg2, ...])
+

立即或在指定的时间恢复一个已暂停的协程。

GetSimTime ()
+

返回当前的模拟时间。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/4.8_mixed_integer_programming.html b/docs/4.8_mixed_integer_programming.html index 4b9d680a..edc5a343 100644 --- a/docs/4.8_mixed_integer_programming.html +++ b/docs/4.8_mixed_integer_programming.html @@ -22,27 +22,27 @@ document.documentElement.classList.toggle('dark', true); } - 4.8 混合整数线性规划 | MicroCity笔记 + 4.8 混合整数线性规划 | MicroCity笔记 - + -

4.8 混合整数线性规划

MicroCity employs the lpsolveopen in new window to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build and solve models. Sample codes for this chapter can be found in the "optimization_samples" folder of the Project Tab in iconScriptEditor.

Model Creation and Execution

CreateLP ([rows = 0 , columns = 0])
-

Creates a Mixed Integer Linear Programming model and returns the LPModel object.

SetObjFunction (LPModel, rowTable, "MAX"|"MIN")
-

Sets the objective function of a LPModel with a Lua Table which stores coefficients of the decision variables.

AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue)
-

Adds a constraint to a LPModel with a Lua Table which stores coefficients of the decision variables.

SetInteger (LPModel, index)
-

Sets a decision variable specified by the index as an integer variable.

SetBinary (LPModel, index)
-

Sets a decision variable of a LPModel specified by the index as a binary variable.

SetUnbounded (LPModel, index)
-

Sets a decision variable of a LPModel to be unbounded(+/- infinity).

SolveLP (LPModel [, timeoutSec = 60])
-

Solves a LPModel and returns 0 as success, -1 as invalid LP model, -2 as nomemory, 1 as suboptimal, 2 as infeasible, 3 as unbounded, 4 as degenerate, 5 as a numerical failure encountered, 6 as the user abort, 7 as a timeout error, 9 as the model could be solved by presolve, 10 as the B&B routine failed, 11 as the B&B was stopped because of a break-at-first, 12 as a feasible B&B solution was found, 13 as no feasible B&B solution found.

GetObjective (LPModel)
-

Returns the objective function value of a LPModel.

GetVariable (LPModel, index)
-

Returns the value of a decision variable specified by the index.

GetVariables (LPModel)
-

Returns all values of the decision variables of a LPModel.

GetDual (LPModel, index)
-

Returns the dual value of a decision variable specified by the index.

GetDuals (LPModel)
-

Returns all dual values of the decision variables of a LPModel.

ReadLP("fileName.mps")
-

Reads a LPModel from a file (*.lp, *.mps) and returns the LPModel if succeed.

WriteLP (LPModel, "fileName.mps")
-

Writes a LPModel to a file (*.lp, *.mps) and returns true if succeed.

Last Updated:
Contributors: huuhghhgyg
- +

4.8 混合整数线性规划

MicroCity使用lpsolveopen in new window来解决混合整数线性规划问题。开发人员可以使用嵌入的Lua函数来构建和求解模型。本章的示例代码可以在项目选项卡中的"optimization_samples"文件夹中找到,图标为图标ScriptEditor.

模型创建和执行

CreateLP ([rows = 0 , columns = 0])
+

创建一个混合整数线性规划模型并返回LPModel对象。

SetObjFunction (LPModel, rowTable, "MAX"|"MIN")
+

使用存储决策变量系数的Lua Table设置LPModel的目标函数。

AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue)
+

使用存储决策变量系数的Lua TableLPModel添加约束。

SetInteger (LPModel, index)
+

将由索引index指定的决策变量设置为整数变量。

SetBinary (LPModel, index)
+

将由索引index指定的LPModel的决策变量设置为二进制变量。

SetUnbounded (LPModel, index)
+

将由索引index指定的LPModel的决策变量设置为无界(正/负无穷大)。

SolveLP (LPModel [, timeoutSec = 60])
+

求解LPModel并返回0表示成功,-1表示无效LP模型,-2表示内存不足,1表示次优,2表示不可行,3表示无界,4表示退化,5表示遇到数值错误,6表示用户中止,7表示超时错误,9表示模型可由预处理解决,10表示B&B例程失败,11表示B&B因中断而停止,12表示找到可行的B&B解决方案,13表示没有可行的B&B解决方案。

GetObjective (LPModel)
+

返回LPModel的目标函数值。

GetVariable (LPModel, index)
+

返回由索引index指定的决策变量的值。

GetVariables (LPModel)
+

返回LPModel的所有决策变量的值。

GetDual (LPModel, index)
+

返回由索引index指定的决策变量的对偶值。

GetDuals (LPModel)
+

返回LPModel的所有决策变量的对偶值。

ReadLP("fileName.mps")
+

从文件(*.lp, *.mps)中读取LPModel,并在成功时返回LPModel

WriteLP (LPModel, "fileName.mps")
+

LPModel写入文件(*.lp, *.mps),并在成功时返回true。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/docs/imgs/index.html b/docs/imgs/index.html deleted file mode 100644 index ad0d155b..00000000 --- a/docs/imgs/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - MicroCity笔记 - - - - - - - - - diff --git a/docs/index.html b/docs/index.html index aa18bb2e..4cac1218 100644 --- a/docs/index.html +++ b/docs/index.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - MicroCity文档 | MicroCity笔记 + MicroCity Desktop 文档 | MicroCity笔记 - + -

MicroCity文档

目录

声明:本网站文档部分内容来自microcity.github.ioopen in new window,版权归原作者所有。

Last Updated:
Contributors: huuhghhgyg
- +

MicroCity Desktop 文档

目录

声明:本网站文档中的部分内容来源于MicroCity Desktopopen in new window,版权归原作者所有。

这篇文章使用ChatGPT翻译自其他语言,如果有问题请在反馈open in new window页面提交反馈。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/en/docs/1.1_what_microcity_can_do.html b/en/docs/1.1_what_microcity_can_do.html new file mode 100644 index 00000000..da2a8620 --- /dev/null +++ b/en/docs/1.1_what_microcity_can_do.html @@ -0,0 +1,34 @@ + + + + + + + + + 1.1 What MicroCity can Do | MicroCity Notes + + + + + +

1.1 What MicroCity can Do

MicroCity is designed to be a handy spatial planning tool, which is portable, compact and fast.

A Modeling Framework

Based on GIS, Networks and Mixed Integer Programming libraries, MicroCity can be used as a modeling framework to solve transporation problems, such as City Logistics and Shipping Planning:

city_logistic   

shipping_planning

A Simulation Platform

Based on 3D CGI and Discrete Event Simulation Engine, MicroCity can be used as a simulation platform to evaluate logistic scenarios, such as Automated Warehouses and Container Terminals:

warehouse_simulation

terminal_simulation

Customized by Scriptable Modules

MicroCity can extend its functionality with modules which can be inherited from SAGAopen in new window or scripted and debugged in Script Editor:
modules    shot

Currently, MicroCity is mainly used in teaching and research. It can be freely distributed.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/2.1_showing_a_world_map.html b/en/docs/2.1_showing_a_world_map.html new file mode 100644 index 00000000..25aaa3fe --- /dev/null +++ b/en/docs/2.1_showing_a_world_map.html @@ -0,0 +1,34 @@ + + + + + + + + + 2.1 Showing a World Map | MicroCity Notes + + + + + +

2.1 Showing a World Map

This tutorial will guide you in manipulating and visualizing GIS data in MicroCity.

Loading Data and Creating a Map

Download the countries.shpopen in new window (ArcGIS shapefile) and the countries.dbfopen in new window (dBase file) in a same folder. Open icon_microcityMicroCity and load button_load or drag the countries.shp into MicroCity and select Data Tab in Workspace panel. Double click Data->Shapes->Polygon->01. countries in Workspace panel. Screenshot

Visualizing Coutries' Properties

Right click icon 01. countries in the Workspace panel. Click Attributes->Table->Show in the popup menu. In the Settings Panel, find the Colors->Type option and select Graduated Color. In its sub-option Attribute, select POP_EST which is population property of countries. In the Setting Panel, find the Chart option and click the ... button. In the popup dialog, select pie in Chart Type option and select GDP_MD_EST in Attribute (Size) option and select EXPORT and IMPORT checkboxs in Fields option and click Okay button. Screenshot

Editing Shapes

Select buttonAction button at toolbar. Left click some country and right click it and select Edit Selected Shape in the popup menu. Then the shape will be in editing mode. You can change its polygon points and finish your editing by right click and select Edit Selected Shape again.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/2.2_searching_for_countries.html b/en/docs/2.2_searching_for_countries.html new file mode 100644 index 00000000..8ad287ff --- /dev/null +++ b/en/docs/2.2_searching_for_countries.html @@ -0,0 +1,52 @@ + + + + + + + + + 2.2 Searching for Countries | MicroCity Notes + + + + + +

2.2 Searching for Countries

This tutorial will guide you in coding with MicroCity Script to manipulate GIS data. You have to complete 2.1 to proceed.

GIS Data Structure

In MicroCity, GIS data consists of three types of Shapes: Point, Polyline and Polygon, each of which can be visualized as a Map Layer. In a layer, a Shape object consists of one or more Parts, and every Part consists of one or more Points. A Shape object is also associated to a record in the Attributes Table. You can also edit the shape or its attributes (see 3.2). structure If you want perform a complex editing or handle a batch of shapes, you can use MicroCity Script, in which many built-in functions can be used.

Making a Query

Suppose we want to find countries, each of which has a population of more than 100 million and is entirely in the northern hemisphere. So we need to check every point's coordinate in each shape and the population attribute of the shape. Open ScriptEditor icon_script_editor and type following codes:

local Countries = Open("countries.shp")                 --Try to open the shapes layer
+for i = 1, GetRecCount(Countries) do                    --Loop all the shape objects in the layer
+    local country = GetShape(Countries, i)              --Get the shape object of a country
+    local north = true                                  --Assume the country is in the northern hemisphere
+    for j = 1, GetPartCount(country) do                 --Loop all of the parts in the shape
+        for k = 1, GetPointCount(country, j) do         --Loop all of the points in the shape part
+            local x, y = GetPointXY(country, k, j)      --Get coordinate of the point j
+            if y < 0 then                               --If the latitude is less than 0
+                north = false                           --The north assumption is false
+            end
+        end
+    end
+    local pop = GetValue(country, "POP_EST")            --Get the population property
+    local name = GetValue(country, "NAME")              --Get the country name
+    if pop > 100000000 and north  then                  --Check the two conditions
+        Print(name, ": ", pop/100000000)                --Print out the result
+    end
+end
+

Running the Script

Save the script to query.mcs and open it with MicroCity or drag it to MicroCity. Then you will find a query item appears in Modules Tab in Workspace panel. Double click the sub-item main. If a dialog pops up, select 01. countries and click Okay. The results will be shown in Messages panel. results

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.1_ui_overview.html b/en/docs/3.1_ui_overview.html new file mode 100644 index 00000000..d68fa107 --- /dev/null +++ b/en/docs/3.1_ui_overview.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.1 UI Overview | MicroCity Notes + + + + + +

3.1 UI Overview

MicroCity provides a concise graphic windowed interface to facilitate the manipulation of data and modules.

The Main Window and Components

Screenshot

Supported Files

MicroCity can open ArcGIS shapefile (*.shp), Grids file (*.sgrd), dBase file (*.dbf), Tabular text file (*.csv, *.txt), Point clouds (*.spc), Image file (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) and MicroCity 3D Scene (*.m3d). These data files are maintained in the Data Tab of the Workspace Panel. Module libraries (*.dll, *.mcs) are maintained and executed through the Modules Tab of the Workspace Panel.

Project Management

The information of opened data files, module libraries, settings and sub-windows can be saved or opened in a MicroCity Project (*.mprj) through the menu File->Project. The mprj file does not contain any file's data. For easy maintenance, files in a project should be put into the same folder or sub-folders of the mprj file.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.2_vector_shapes.html b/en/docs/3.2_vector_shapes.html new file mode 100644 index 00000000..84aef8ea --- /dev/null +++ b/en/docs/3.2_vector_shapes.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.2 Vector Shapes | MicroCity Notes + + + + + +

3.2 Vector Shapes

MicroCity can open, create and edit ArcGIS shapefiles (*.shp) which are called Shapes and maintained in the Data Tab of the Workspace Panel. By using modules (see 3.7) other vector file formats, such like Scalable Vector Graphics (*.svg) and AutoCAD Drawing Exchange Format (*.dxf), can also be imported or exported.

Opening, Creating, Saving and Closing Shapes

Users can click buttonLoad button or File->Shapes->Load menu item to open an ArcGIS shapefile (*.shp) as a Shapes. Creating a new Shapes can be done from menu File->Shapes->New and the pop-up dialog as shown below. Users can choose one shapes type from icon_shapes_pointPoint, icon_shapes_lineLine and icon_shapes_polygonPolygon. The relationship between a ArcGIS shapefile (*.shp) and a same named dBase file (*.dbf) is also shown.

new shapes    shape_files

Saving a Shapes can be done from the right click context menu Save or Save As. You can also close a Shapes from the menu and get a prompt dialog to save it.

shapes menu    close and save

Showing and Editing Shapes

Double click a Shapes from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle buttonAction botton and right click a Shape in a Shapes layer and choose Edit Selected Shape then go to the Editing Mode. In this mode users can add/delete parts and add/delete points in a shape (for data structure of a shape see 2.2). The associated attributes table (*.dbf) of a Shapes can be accessed through right-clicking context menu Attributes->Table->Show (see the tutorial 2.1).

edit shape    edit point

Display Settings and Data Visualization

Users can change Shapes outline, fill, labels and other display settins from the Settings Panel. Some options can connect attribute data and give visualization functionalities (for example 2.1).

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.3_raster_grids.html b/en/docs/3.3_raster_grids.html new file mode 100644 index 00000000..bc9dba25 --- /dev/null +++ b/en/docs/3.3_raster_grids.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.3 Raster Grids | MicroCity Notes + + + + + +

3.3 Raster Grids

MicroCity can open, create and edit SAGA Grid (*.sgrd) which is called Grid and maintained in the Data Tab of the Workspace Panel. Image files (*.bmp, *.gif, *.jpg, *.png, *.tif, *.pcx) can be opened as Grid as well. By using modules (see 3.7) other raster file formats, such like ESRI Arc/Info Grid (*.adf) and Surfer Grid (*.grd), can also be imported or exported.

Opening, Creating, Saving and Closing Grids

Users can click buttonLoad button or File->Grid->Load menu item to open a Grid. Creating new Grid can be done from menu File->Grid->New and the pop-up dialog:

new grid    grid_structure The above right figure is the data structure and definitions of a Grid. A Grid starts from its bottom left corner which has coordinate (xMin, yMin), contains NX*NY Square Cells. Each cell has its own Integer Coordinate (X, Y), in the range of (0, 0) to (XMax, YMax).

Saving Grid can be done from the right click context menu Save or Save As. You can also close a Grid from the menu and get a prompt dialog to save it.

grid menu    close and save

Showing and Editing Grids

Double click a Grid from the Data Tab will give you a map view (for maps and layers see 3.6). Toggle Action botton button and select a range of cells in a Grid. Then the value of these cells can be edited in the Attributes Tab of the Settings Panel.

grid selection    grid_attributes

Display Settings and 3D View

Users can show cell values, change color and set transparency of a Grid by using Settings Panel. Using button button can creat a 3D surface of a Grid in which cell values are translated to elevation (see 3.6).

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.4_3d_scenes.html b/en/docs/3.4_3d_scenes.html new file mode 100644 index 00000000..3f5c0340 --- /dev/null +++ b/en/docs/3.4_3d_scenes.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.4 3D Scenes | MicroCity Notes + + + + + +

3.4 3D Scenes

MicroCity 3D Scene (*.m3d) is a data file format to store 3D scenes' information. Popular 3D file formats including 3D Studio Max (*.3ds), Wavefront OBJ (*.obj) and Stereolithography (*.stl) can be loaded as objects in a scene (see below) but not be stored in the .m3d file.

Opening, Creating, Saving and Closing 3D Scenes

Users can click Load button button or File->Scene->Load menu item to open a Scene. Creating new Scene can be done from menu File->Scene->New and fill the pop-up dialog as shown below. After pressing Okay button an item will appear in the Data Tab of the Workspace Panel. Then Scene can be saved or closed through right-click menu:

new scene    scene_menu

Showing and Editing 3D Scenes

Double click a Scene from the Data tab will give you a scene view. Left-mouse-dragging in a scene veiw will rotate the camera and right-mouse-dragging will translate the camera. Double-left-clicking a scene view can select objects and Double-right-clicking a scene view can popup a context menu (shown below). One can add objects, load objects and set objects, etc.. Note that the Rotation in the coordinate system should obey Left-hand rule. The illustration of the coordinate system and an example of the rotation around y-axis is shown below:

object_menu    scene_coordinate

The coordinate used in the position and rotation of an object is relative to its parent object. By default, the parent of a new object is null.

Display Settings

Users can change the background color, reference grid or other display options of a Scene by using Settings Panel.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.5_tables.html b/en/docs/3.5_tables.html new file mode 100644 index 00000000..7c4bb32e --- /dev/null +++ b/en/docs/3.5_tables.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.5 Tables | MicroCity Notes + + + + + +

3.5 Tables

Tabular files including dBase files (*.dbf), Text file (*.txt) and Comma Separated Values (*.csv) can be opened as Table and saved with MicroCity.

Opening, Creating, Saving and Closing Tables

Users can click Load button button or File->Table->Load menu item to open a tabular file. Creating a new Table can be done from menu File->Table->New and the pop-up dialog as shown below. Saving a Table can be done from the right click context menu Save or Save As.

new table    table_menu

Showing and Editing Tables

Double click a Table from the Data Tab will give you a table view. Altering a table's stucture can be done by right click the table's head. If you click "Add Field" then, a dialog which guide you (as shown below). If you want insert a record to the table, you can right click the left numbers of the table and select a context menu item.

table_view_menu    add_field

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.6_maps_and_layers.html b/en/docs/3.6_maps_and_layers.html new file mode 100644 index 00000000..03d16a87 --- /dev/null +++ b/en/docs/3.6_maps_and_layers.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.6 Maps and Layers | MicroCity Notes + + + + + +

3.6 Maps and Layers

In MicroCity, Shapes and Grids can be showed in Maps. Each map may contains multiple layers and each layer is corresponding to a Shapes or a Grid.

Opening, Creating, Saving, Printing and Closing Maps

Because Maps are based on Shapes and Grids, they can not be saved or opened independently, but can be saved or opened along with a MicroCity Project (*.mprj). Creating a Map is by double clicking a Shapes or Grid from the Data Tab of the Workspace Panel. A Map window contains four coordinate bars which can be used to locate objects (see below). A Map can also be printed or closed from the context menu of the Maps Tab of the Workspace Panel.

map_coordinates   map_menu

Adding, Moving, Hiding and Closing Layers in a Map

A Map can have multiple Layers, each of them represents a data item. One can add a Layer to a Map by double clicking a Shapes or a Grid from the Data Tab. A lower layer can be obscured by upper layers. One can move a layer by dragging, hide a layer by double clicking and close a layer through the menu (as shown below).

add_layer    layer_menu

Controlling Map Views

When a data item or a layer is selected, this layer is called the active layer. One can toggle the Action button b_action to select and edit an object in the active layer. By toggling the Zoom b_zoom or Pan b_pan botton, the map can zoomed in, zoomed out or panned. If one lose in a map, he can use the Zoom to Full Extent b_zfull button to get a full view of the map. Other zoom controlling buttons b_zlastb_znextb_zactiveb_zsel can be used to facilitate the map browsing.

The Synchronise b_sync button can be used if you want compare difference between two or more maps. The Ruler b_ruler button can be used to meassure distances. Note that, by default, the unit of the distances measured is kilometer under the coordinate system of Earth. One can change the coordinate system to Non-Earth from the Settings Panel of the Map, and get Cartesian distance without unit.

One can create a 3D surface map by clicking 3D b_3d button, which need a appropriately sized Grid (see 3.3).

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/3.7_modules.html b/en/docs/3.7_modules.html new file mode 100644 index 00000000..638b6f8f --- /dev/null +++ b/en/docs/3.7_modules.html @@ -0,0 +1,34 @@ + + + + + + + + + 3.7 Modules | MicroCity Notes + + + + + +

3.7 Modules

The functionality of MicroCity can be extended by modules, one type of which is SAGA Moduleopen in new window (*.dll). SAGA Modules contains many useful libraries for Shapes and Grids. Another type of Module is MicroCity Script (*.mcs), which can be edited and debugged with icon_script_editorScriptEditor (see 4.1).

Loading, Closing and Executing Modules

Modules can be loaded to MicroCity by clicking Load button button or Modules->Load Module Library menu item. The Modules Tab of the Workspace Panel will display the loaded Librariesicon_module_lib (each of which corresponding to a file) and their inside Modules icon_module. One can close or reload a Module Library from the context menu. Executing a moule has many ways: double clicking it, clicking the Execute button from the Settings Panel, or click the Execute context menu item. One can also Debug a MicroCity Script module by clicking the Debug context menu item, that needs the ScriptEditor running in the background. MicroCity can also capture runtime errors and pause the execution of modules.

module_file_menu    module_menu

Accelerating, Stopping the Execution of a Module

MicroCity Script module is created with Luaopen in new window language which is very fast. In some cases, if you want much more faster execution speed, you can click the icon_module_lib Module Libraries in the Modules Tab of the Workspace Panel and switch the Script Running Mode in the Settings Panel from the Safe Mode to the Fast Mode. Then MicroCity will use LuaJITopen in new window to execute modules.

If a module is being executed, one can stop it by click the Execute button in the corresponding Settings. In Safe Mode the execution can be immediately stopped, but in Fast Mode the stopping is depend on the GetReady() function called in the script (see 4.2.

module_libraries_settings    module_settings

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.1_si_overview.html b/en/docs/4.1_si_overview.html new file mode 100644 index 00000000..231aa0a4 --- /dev/null +++ b/en/docs/4.1_si_overview.html @@ -0,0 +1,35 @@ + + + + + + + + + 4.1 SI Overview | MicroCity Notes + + + + + +

4.1 SI Overview

MicroCity uses Modules (see 3.7) to extend its functionalities. One type of the modules is MicroCity Script (*.mcs) which can be edited and debugged in the iconScriptEditor.

The Script Editor

scritp_editor

Coding and Debugging MicroCity Scripts

ScriptEditor is based on ZeroBraneopen in new window. One can find detailed information there. For debugging, you should keep iconScript Editor being opened. Then right click the module from iconMicroCity and choose Debug item in the context menu (see 3.7). The execution can be indicated in the Code View of ScriptEditor. You can control the execution and watch variables with Debug Buttons.

The Lua Language and Embedded Functions

MicroCity uses Lua 5.1open in new window as its script language. One can find the reference manual there. MicroCity embeds many useful funtions in Lua, which can not only control user interfaces, manipulate data, but also can solve mathematical models and sun simulations. You should read following chapters for more information.

Conventions in this reference:
There are four major data types in Lua can be passed though embedded functions as parameters, namely Number, Boolean, String and Object. The type Object includes builtin Lua objects, such as Table, Function adn Thread..., as well as MicroCity objects, such as Shapes, Grid, Table and Scene.... To clarify the parameter type in embedded functions, we use capitalization, quotation mark and semantic information to avoid ambiguities in function descriptions. A lowercase word of a paramter means a Number. Sometimes, to present an integer parameter, a letter 'i' followed by a word is used, like iField. Starting with the letter 'b' and followed by a word means a Boolean, like bShow. A quoted word means a String. A capitalized word means an Object or a keyword. Following is an example of a embedded function description.

AddParameter (Module, ParentNode, "Value",  "id" [, default = 0])
+

In this case, the Module parameter should be a Module object. The ParentNode parameter should be a Node object, but it act as a parent Node. The "Value" parameter is a string, but it represent the builtin type Value in MicroCity, so this string can not be changed. The "id" parameter should be a user specified string. The default parameter is a number. The contents in a pair of '[' and ']' are optional. The character '|' among parameters means "or".

Encoding formats:
MicroCity uses ANSI encoding format to read and write data, such as shp, txt, csv and dbf. ScriptEditor and the embedded funtions use UTF-8 encoding format to read and write data, such as txt or csv.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.2_ui_control.html b/en/docs/4.2_ui_control.html new file mode 100644 index 00000000..ad3a6bf4 --- /dev/null +++ b/en/docs/4.2_ui_control.html @@ -0,0 +1,63 @@ + + + + + + + + + 4.2 UI Control | MicroCity Notes + + + + + +

4.2 UI Control

Microcity Script can be used to control some features appearing in user interfaces, which include moduels, data objects, messages and so on. There are some sample codes can be found in the "user_interface" folder of the Project Tab in iconScriptEditor.

Basic User Interfaces

Print ("hello" [,...])
+

Prints values in the Messages Panel.

Note ("hello" [,...])
+

Notifies users and pauses the execution.

SetProcessText ("processing")
+

Sets a text at the bottom left corner of MicroCity.

SetProgress (position, range)
+

Sets the progress bar of position/range that locates at the bottom right conner of MicroCity.

Sleep (milliseconds)
+

Pauses the execution for milliseconds.

GetReady ()
+

MicroCity shares the same thread with the lua engine. Heavy calculations in lua will block the MicroCity interface. Use this function inside can let the MicroCity interface respond to user operations. Returns false if user cancel the current execution.

GetClickXY ()
+

Returns x,y where a user clicked at a Map View.

GetDragExtent ()
+

Returns bottom-left and top-right corner coordinate: Lx, By, Rx, Ty, which a user used mouse to drag a rectangle in a Map View.

Data Objects

PATH
+

Internal global variable that holds a string of current working directory, such as "c:\microcity".

Open (".\\shapes.shp" [, ".\\grid.sgrd" [, ".\\table.dbf" [, ".\\scene.m3d" , ...]]])
+

Opens and returns Shapes, Table, Grid and Scene object from current working directory or opened data.

Close (Shapes|Grid|Table|Scene|Network|RndEngine|LPModel)
+

Closes an opened or created Shapes, Table, Grid, Scene, Network, RndEngine or LPModel object.

Update (Shapes|Grid|Table [, bShow = ture])
+

Update current changes of Shapes, Grid or Table object in MicroCity. The bShow indicates whether to create a view of the object. Returns false if user cancel the current execution.

CreateMap ("name", Shapes1|Grid1 [, Shapes2|Grid2, ...])
+

Creates a Map View to show objects which can be arranged in layers by their order in the parameters.

Modules and Parameters

AddModule ("Function" [, "name"]) 
+

This function can add a lua function as a module to current module library. The module's default name is the function's name. Returns a Module object.

AddParameter (Module, ParentNode, "Node",   "id")
+AddParameter (Module, ParentNode, "Value",  "id" [, default = 0])
+AddParameter (Module, ParentNode, "Range",  "id" [, low = 0 [,  high = 1]])
+AddParameter (Module, ParentNode, "Check",  "id" [, default = 0])
+AddParameter (Module, ParentNode, "String", "id" [, "string" = "")
+AddParameter (Module, ParentNode, "Choice", "id" [, "choice1|choice2|" [, choice = 1]])
+AddParameter (Module, ParentNode, "File",   "id" [, "c:\\default.txt" = ""])
+AddParameter (Module, ParentNode, "Color",  "id" [, "color" = "255 255 255")
+AddParameter (Module, ParentNode, "Shapes", "id")
+AddParameter (Module, ParentNode, "Grid",   "id")
+AddParameter (Module, ParentNode, "Scene",  "id")
+AddParameter (Module, ParentNode, "Table",  "id")
+AddParameter (Module, ParentNode, "Field",  "id")
+

These functions can add a parameter to a module's settings panel. Returns corresponding values or an object. The ParentNode can be set to the first return of a AddParameter function. If "Field" is set at the third place, the parent_node can be set to a Table or Shapes object to get its attributes table's head.

GetParameter (Shapes|Table|Grid|Scene|Module, "id")
+

Returns the parameter specified by "id" from the object's settings panel.

SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
+

Sets the parameter specified by "id" in the object's settings panel. Returns true if succeed. Note that the choice parameter should start from 1. A parameter's "id" can be found in the parameter's helper text shown as below.

shot

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.3_shapes_and_tables.html b/en/docs/4.3_shapes_and_tables.html new file mode 100644 index 00000000..00b01bb7 --- /dev/null +++ b/en/docs/4.3_shapes_and_tables.html @@ -0,0 +1,73 @@ + + + + + + + + + 4.3 Shapes and Tables | MicroCity Notes + + + + + +

4.3 Shapes and Tables

Users can manipulate Shapes and Tables with MicroCity Script. For detailed data structure of Shapes, you can refer to previous chapter 2.2 and 3.2. Because Shapes can be treated as Tables with extra field with geographic data, some of embeded functions for tabular data manipulation can be used both in Shapes and Tables. Sample codes for this chapter can be found in the "shapes_samples" folder of the Project Tab in iconScriptEditor.

Tabular Data Manipulation

CreateShapes ("name", "Point|Line|Polygon")
+

Returns a Shapes object.

CreateTable ("Name")
+

Returns a Table object.

GetFieldCount (Shapes|Table)
+

Returns the number of fields in a Shapes or Table

GetField (Shapes|Table, iField)
+

Inputs the index (starts from 1) of a field and returns the field name and type ("Int", "Float", "Double" or "String).

AddField (Shapes|Table, "field1", "Int|Float|Double|String" [, "field2", "Int|Float|Double|String", ...])
+

Adds fields to a *Table or Shapes and returns booleans (true or false) by order.

DelField (Shapes|Table, iField)
+

Returns true if successfully delete a field.

GetRecCount (Shapes|Table)
+

Returns the total number of records in a Shapes or Table.

AddRecord (Shapes|Table)
+

Adds a record to a Shapes or Table and returns the index.

GetValue (Shapes|Table, "field_name", index1 [, index2, ...])
+

Retrieve values from a specified field and indexes of a Shapes or Table. Returns multiple values by the order of indexes.

SetValue (Shapes|Table, value, "field_name", index1 [, index2, ...])
+

Sets values for a specified field and indexes of a Shapes or Table.

Geographic Data Manipulation

GetSelections (Shapes)
+

Returns selected shape objects from a Shapes.

GetShape (Shapes, index1 [, index2, ...])
+

Returns Shape objects from a Shapes by the order of indexes.

AddShape (Shapes, Shape)
+

Adds a Shape object to a Shapes and returns its index.

AddShape (Shapes [, x1, y1, x2, y2, ...])
+

Adds a Shape object to a Shapes which defined as points. Returns the Shape object and index.

DelShape (Shape|Shapes)
+

Deletes a Shape or Shapes object and returns ture if successful.

AddPoint (Shape, x, y [, iPart = 1])
+

Adds a point to a Shape and returns ture if successful.

InsPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
+

Inserts a point to a Shape and returns ture if successful.

SetPoint (Shape, x, y [, iPoint = 1 [, iPart = 1]])
+

Sets a point coordinates in a Shape and returns ture if successful.

DelPoint (Shape, iPoint [, iPart=1])
+

Deletes a point at position iPoint from a Shape and returns ture if successful..

DelPart (Shape, iPart)
+

Deletes a part from a Shape and returns ture if successful.

GetPartCount (Shape)
+

Returns the number of parts in a Shape.

GetPointCount (Shape [, iPart])
+

Returns the number of points in a Shape.

GetPointXY (Shape [, iPoint [, iPart = 1]])
+

Returns all points' coordinates: x1, y1, x2, y2, ... from a Shape or a specified point's coordinate.

CopyShapeTo (TargetShapes, dx, dy, Shape1 [, Shape2, ...])
+

Copys Shape objects to a target Shapes with relative translation (dx, dy) and returns new Shape objects.

MoveShapeTo (dx, dy, Shape1 [, Shape2, ...])
+

Translates Shape objects to its relative position (dx, dy).

GetCenterXY (Shapes)
+

Returns the center coordinate (x, y) of a Shapes.

GetCenterXY (Shapes, index1 [, index2, ...])
+

Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects specified by indexes in a Shapes.

GetCenterXY (Shape1 [, Shape2, ...])
+

Returns the center coordinates (x1, y1, x2, y2, ...) of Shape objects.

GetDistance (x1, y1, x2, y2 [, x3, y3, ...])
+

Returns the total distance between every two pairs of coordinates (x, y).

GetShapeLen (Shape1 [, Shape2, ...])
+

Returns lengths of Shape objects.

GetShapeArea (Shape1 [, Shape2, ...])
+

Returns areas of Shape objects.

GetShapeType (Shape|Shapes)
+

Returns the type ("Point", "Line" or "Polygon") of the a Shapes or Shape object.

GetExtent (Shapes)
+

Returns the extent coordinates (Lx, By, Rx, Ty) of a Shapes's extent.

GetExtent (Shapes, index)
+

Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape indexed in a Shapes.

GetExtent (Shape)
+

Returns the extent coordinates (Lx, By, Rx, Ty) of a Shape.

GetIntersection (ShapeA, ShapeB)
+

Returns a Shape (Point, Line or Polygon) object of the intersection of two Shapes.

GetValue (Shape, "field_name")
+

Returns the value of specified field of a Shape.

SetValue (Shape, value1, "field_name1" [, value2, "field_name2", ...])
+

Sets values in different fiedds for a Shape.

SetCoorSys ("Earth"|"Non-Earth")
+

Sets coordinate system. If using "Earth", distances, lenths and areas are calculated according to the earth ellipsoid coordinate system. By default the "Non-Earth" is used, which is cartesian coordinate system.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.4_grids.html b/en/docs/4.4_grids.html new file mode 100644 index 00000000..6123959b --- /dev/null +++ b/en/docs/4.4_grids.html @@ -0,0 +1,47 @@ + + + + + + + + + 4.4 Grids | MicroCity Notes + + + + + +

4.4 Grids

Grids in MicroCity have simple structure (3.3) but efficient time and space utilization if applying algorithms on them. Sample codes for this chapter can be found in the "grid_samples" folder of the Project Tab in iconScriptEditor.

Cellular Data Manipulation

CreateGrid ("name", "Int|Float|Double", XMax, YMax [, CellSize = 1 [, xMin = 0 [, yMin = 0] [, init = 0]]]])
+

Returns a Grid object.

GetCellSize (Grid)
+

Returns the Cellsize value of a Grid.

GetGridMaxXY (Grid)
+

Returns XMax, YMax of a Grid.

ConvertToGridXY (Grid, x1, y1 [, x2, y2, ...])
+

Converts real coordinates to coordinates in a Grid. Returns X1, Y1, X2, Y2, ... .

ShapeToGrid (Grid, Shape, value)
+

Rasterizes a Shape in a Grid. The cell values will be set according to the covering area and the inputed value.

ShapeToGrid (Grid, Shapes, "field_name")
+

Rasterizes all Shape objects in a Shapes. The cell values will be set according to the covering area and the values of Shapes field.

GetValue (Grid, X1, Y1 [, X2, Y2, ...])
+

Returns cells' (specified by Grid coordinates) values: value1, value2, ... .

SetValue (Grid, value, X1, Y1 [, X2, Y2, ...])
+

Sets values for cells specified by Grid coordinates.

GetCenterXY (Grid)
+

Returns the center real coordinate (x, y) of a Grid.

GetCenterXY (Grid, X1, Y1 [, X2, Y2, ...])
+

Returns the real coordinates of cells' centers: x1, y1, x2, y2, ... .

GetExtent (Grid)
+

Returns the leftbottom and righttop corner of a Grid's extent: Lx, By, Rx, Ty.

GetExtent (Grid, X, Y)
+

Returns the leftbottom and righttop corner of a cell's extent: Lx, By, Rx, Ty.

GetFractalDim (Grid, X1, Y1, X2, Y2, fold [, MultiFractalQ = 0])
+

Calculates fractal dimension of the specified area in a Grid. Returns dimension, RSQ of linear regression, and the number of boxes in every fold.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.5_3d_scenes.html b/en/docs/4.5_3d_scenes.html new file mode 100644 index 00000000..6d3a42f8 --- /dev/null +++ b/en/docs/4.5_3d_scenes.html @@ -0,0 +1,62 @@ + + + + + + + + + 4.5 3D Scenes | MicroCity Notes + + + + + +

4.5 3D Scenes

Scenes and inside 3D objects (3.4) can be scripted. Sample codes for this chapter can be found in the "3d_samples" folder of the Project Tab in iconScriptEditor.

3D Scene and Object Manipulation

CreateScene ("Title" [, RotSpeed=1] [, TransSpeed=1])
+

Creates a new 3d scene and returns the object.

AddZipTo3DPath (Scene, "filename.zip")
+

Adds a zip file to the search directory and returns true if succeed. It is useful for collecting a large amount of files.

LoadSkybox (Scene, "top.jpg" ,"bottom.jpg" ,"left.jpg" ,"right.jpg" ,"front.jpg" ,"back.jpg")
+

Loads six image files as the skybox of a 3d scene.

LoadObject (Scene, "filename.3ds" [,shadow = false [, AnimationSpeed]])
+

Loads a 3d object from a file and returns the object.

AddLight (Scene, x, y, z, Radius [, r = 255, g = 255, b = 255])
+

Adds a light object and returns the object.

Add3DLabel(Scene, "label" [, width=10, height=10 [, r = 180, g = 180, b = 180 [, "font.xml"]]])
+

Adds a 3D label at (0,0,0) and returns the object.

Add3DLine (Scene, x1, y1, z1, x2, y2, z2 [, r = 0, g = 0, b = 0])
+

Adds a 3D line object frome (x1, y1, z1) to (x2, y2, z2) and retruns the object.

Add3DRect (Scene, length, width [, r = 180, g = 180, b = 180])
+

Adds a 3D rectangular object from (-length/2,0,-width/2) to (length/2,0,width/2) and returns the object.

Add3DBox (Scene, length, width, height [, r = 180, g = 180, b = 180 [, bShowEdge = true]])
+

Adds a 3D box object from (-length/2,-height/2,-width/2) to (length/2,height/2,width/2) and returns the object.

AddSphere (Scene, radius [, polycount = 16 [, r = 180, g = 180, b = 180]])
+

Adds a sphere at (0,0,0) and returns the object. If the radius parameter is less than 0, returns an invisible object.

GetTexture (Object)
+

Returns the texture files of a object: "filename1", "filename2", ... .

LoadTexture (Scene, Object, "filename1" [, "filename2", ...])
+

Loads texture files to an object.

SetPosition (Object, x, y, z [, absolute = false])
+

Sets the position of an object relative to its parent (or the absolute position to the scene).

GetPosition (Object [, absolute = false])
+

Gets the position of an object relative to its parent (or the absolute position to the scene).

SetRotation (Object, rx, ry, rz [, absolute = false])
+

Sets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene).

GetRotation (Object [, absolute = false])
+

Gets the rotation (left hand rule) of an object in degrees relative to its parent (or the absolute rotation to the scene).

SetScale (Object, sx, sy, sz)
+

Sets the scale of an object.

GetScale (Object)
+

Gets the scale of an object.

SetParent (Object, Parent)
+

Attaches an object to another object as a child.

GetParent (Object)
+

Gets the parent of an object.

SetObject (Object "id" [,x, y, z, [,rx, ry, rz [,sx, sy, sz]]])
+

Sets the ID, position, rotation and scale of an object.

DelObject (Object)
+

Deletes an object.

SetCamera (Scene, x, y, z [,Tx, Ty, Tz])
+

Sets the position and target of the scene camera.

GetCamera (Scene)
+

Gets the camera object of a 3d scene and its position and targt.

GetSelections (Scene)
+

Returns selected objects from a 3d scene.

GetObjectID (Object1 [, Object2, ...])
+

Returns "id"s of objects.

SetObjectID (Object, "id")
+

Sets the id of an object.

GetObject (Scene, "id")
+

Finds an object by its id.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.6_networks.html b/en/docs/4.6_networks.html new file mode 100644 index 00000000..3787e258 --- /dev/null +++ b/en/docs/4.6_networks.html @@ -0,0 +1,54 @@ + + + + + + + + + 4.6 Networks | MicroCity Notes + + + + + +

4.6 Networks

GIS vector data (3.2) in MicroCity can be topologized to Networks and applied the Shortest Path Algorithm and User Equilibrium Traffic Assignment Algorithm. Sample codes for this chapter can be found in the "network_samples" folder of the Project Tab in iconScriptEditor.

Network Manipulation

CreateNetwork ()
+

Creates an empty network and returns the object.

CreateNetwork (UnTopoLines)
+

Creates a network from an untopologized "line" Shapes and returns three objects: Network, Nodes (Shapes) and Links (Shapes).

CreateNetwork (Nodes, Links)
+

Creates a Network object from topologized Nodes and Links Shapes. Returns the Network object.

InitNetwork (Network, Nodes, Links)
+

Initiates a Network from a Nodes and a Links Shapes. Returns true if succeed.

AddLink (Network, linkID|-1, oID|-1, dID|-1, impedance [, direction = 1 [, capacity = 1E+38]])
+

Adds a new link or update an existing link in the Network. Returns linkID, oID, dID, true/false for adding and true/false for updating.

AddLink (Network, Shapes|Table, index1 [, index2, ...])
+

Adds or updates links from the recordset of a Shapes or Table. Returns boolean values.

DelLink (Network, linkID)
+

Deletes a link from a Network. Returns a boolean value.

GetNearNodeID (Network, x, y [, radius=nil])
+

Gets the nearest Network nodes from a coordinate. Returns node ids.

GetNodeXY (Network, nodeID1 [, nodeID2, ...])
+

Returns the coordinates of nodes in a Network: x1, y1, x2, y2, ... .

Algorithms

GenSTPTree (Network, startID [, endID])
+

Generates a Shortest Path Spanning Tree from a node. Returns a boolean value.

GetSTPPath (Network, endID, "NodeID"|"LinkID")
+

After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link id sequence: id1, id2 ,... .

GetSTPPath (Network, endID, "iNodeShp"|"iLinkShp")
+

After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shapes index sequence.

GetSTPPath (Network, endID, "NodeShp"|"LinkShp")
+

After calling GenSTPTree calls this function. Returns a Shortest Path indicated by a node or link Shape object sequence.

GetSTPLen (Network, endID)
+

After calling GenSTPTree call this function. Returns a Shortest Path Distance to a end node.

GetSTPLen (Network, startID, endID)
+

Gets a Shortest Path from a start node to an end node in a Network. Returns the distance.

GetSTPLen (Network, x1, y1, x2, y2)
+

Gets a Shortest Path from a start coordinate to an end coordinate in a Network. Returns the distance.

SetTrip (Network, oID, dID, amount)
+

Sets an amount of a trip from an origin to an destination.

SolveUE (Network [, rootTol = 1E-2 [, equlBrm = 1E-5 [, maxIter = 10000]]])
+

After calling SetTrip call this function. Performs the User Equilibium Traffic Assignment and returns a boolean value.

GetFlow (Network, linkID)
+

Returns the traffic flow of a specified link.

SetFlow (Network, linkID, flow)
+

Set the traffic flow of a specified link and return a boolean value.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.7_des_simulations.html b/en/docs/4.7_des_simulations.html new file mode 100644 index 00000000..e8462260 --- /dev/null +++ b/en/docs/4.7_des_simulations.html @@ -0,0 +1,50 @@ + + + + + + + + + 4.7 Discrete Event Simulations | MicroCity Notes + + + + + +

4.7 Discrete Event Simulations

MicroCity has a inside simulation time counting and event scheduling mechanism. It provides several embedded Lua functions to facilitate creating Discrete Event Simulations, which is very useful for dynamic system analysis. Sample codes for this chapter can be found in the "simulation_samples" folder of the Project Tab in iconScriptEditor.

Random Number Generation

CreateRandEng (seed, "uniform_01")
+

Creates a binary distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "uniform_real" [, min = 0, max = 1])
+

Creates a uniform distributed real random generation engine from a seed and returns the object.

CreateRandEng (seed, "uniform_int" [, min = 0, max = 1])
+

Creates an uniform integer random generation engine from a seed and returns the object.

CreateRandEng (seed, "triangle" [, a = 0, b = 1, c = 2])
+

Creates a triangle distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "bernoulli" [, p = 0])
+

Creates a bernoulli distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "cauchy" [, median = 0, sigma = 1])
+

Creates a cauchy distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "exponential" [, lambda = 1])
+

Creates a exponential distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "geometric" [, p = 0])
+

Creates a geometric distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "normal" [, mean = 0, sigma = 1])
+

Creates a normal distributed random generation engine from a seed and returns the object.

CreateRandEng (seed, "lognormal" [, mean = 0, sigma = 1])
+

Creates a lognormal distributed random generation engine from a seed and returns the object.

GetNextRandom (Engine)
+

Gets a random number from a random generation engine.

Simulation Control

CreateEvent (time, Funcion [, arg1, arg2, ...])
+

Creates a future event from a Lua Function or a Lua Coroutine. Returns a Coroutine object.

ExecAllEvents ()
+

Calls this at last. It will execute all events as Lua Coroutines.

Delay ([relativeTime = 0])
+

Calls this function in a Lua Coroutine will let it first yield then resume it after the specified relative time. If the parameter relativeTime is not set, the current Coroutine will yield and won' be resumed automatically.

Resume ([time, ] Coroutine [, arg1, arg2, ...])
+

Resumes a yielded coroutine immediately or at a specified time.

GetSimTime ()
+

Returns the current simulation time.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.7_des_simulations_zh.html b/en/docs/4.7_des_simulations_zh.html new file mode 100644 index 00000000..71e176d7 --- /dev/null +++ b/en/docs/4.7_des_simulations_zh.html @@ -0,0 +1,50 @@ + + + + + + + + + 4.7 离散事件模拟 | MicroCity Notes + + + + + +

4.7 离散事件模拟

MicroCity具有内部模拟时间计数和事件调度机制。它提供了几个嵌入式Lua函数,以便更容易地创建离散事件模拟,这对于动态系统分析非常有用。本章的示例代码可以在 图标ScriptEditorProject 选项卡的"simulation_samples"文件夹中找到。

随机数生成

CreateRandEng(seed, "uniform_01")
+

从种子创建一个二进制分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "uniform_real" [, min = 0, max = 1])
+

从种子创建一个均匀分布的实数随机生成引擎,并返回该对象。

CreateRandEng(seed, "uniform_int" [, min = 0, max = 1])
+

从种子创建一个均匀分布的整数随机生成引擎,并返回该对象。

CreateRandEng(seed, "triangle" [, a = 0, b = 1, c = 2])
+

从种子创建一个三角形分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "bernoulli" [, p = 0])
+

从种子创建一个伯努利分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "cauchy" [, median = 0, sigma = 1])
+

从种子创建一个柯西分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "exponential" [, lambda = 1])
+

从种子创建一个指数分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "geometric" [, p = 0])
+

从种子创建一个几何分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "normal" [, mean = 0, sigma = 1])
+

从种子创建一个正态分布的随机生成引擎,并返回该对象。

CreateRandEng(seed, "lognormal" [, mean = 0, sigma = 1])
+

从种子创建一个对数正态分布的随机生成引擎,并返回该对象。

GetNextRandom(Engine)
+

从随机生成引擎获取一个随机数。

模拟控制

CreateEvent(time, Function [, arg1, arg2, ...])
+

Lua函数Lua协程创建一个未来事件。返回一个协程对象。

ExecAllEvents()
+

最后调用此函数。它将执行所有事件作为Lua协程

Delay([relativeTime = 0])
+

Lua协程中调用此函数将使其首先暂停,然后在指定的相对时间后恢复。如果未设置relativeTime参数,则当前协程将暂停,并且不会自动恢复。

Resume([time, ] Coroutine [, arg1, arg2, ...])
+

立即或在指定时间恢复一个已暂停的协程。

GetSimTime()
+

返回当前模拟时间。

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/4.8_mixed_integer_programming.html b/en/docs/4.8_mixed_integer_programming.html new file mode 100644 index 00000000..d9936825 --- /dev/null +++ b/en/docs/4.8_mixed_integer_programming.html @@ -0,0 +1,48 @@ + + + + + + + + + 4.8 Mixed Integer Programming | MicroCity Notes + + + + + +

4.8 Mixed Integer Programming

MicroCity employs the lpsolveopen in new window to takle Mixed Integer Linear Programming problems. Developers can use embedded Lua functions to build and solve models. Sample codes for this chapter can be found in the "optimization_samples" folder of the Project Tab in iconScriptEditor.

Model Creation and Execution

CreateLP ([rows = 0 , columns = 0])
+

Creates a Mixed Integer Linear Programming model and returns the LPModel object.

SetObjFunction (LPModel, rowTable, "MAX"|"MIN")
+

Sets the objective function of a LPModel with a Lua Table which stores coefficients of the decision variables.

AddConstraint (LPModel, rowTable, "<="|">="|"==", rhsValue)
+

Adds a constraint to a LPModel with a Lua Table which stores coefficients of the decision variables.

SetInteger (LPModel, index)
+

Sets a decision variable specified by the index as an integer variable.

SetBinary (LPModel, index)
+

Sets a decision variable of a LPModel specified by the index as a binary variable.

SetUnbounded (LPModel, index)
+

Sets a decision variable of a LPModel to be unbounded(+/- infinity).

SolveLP (LPModel [, timeoutSec = 60])
+

Solves a LPModel and returns 0 as success, -1 as invalid LP model, -2 as nomemory, 1 as suboptimal, 2 as infeasible, 3 as unbounded, 4 as degenerate, 5 as a numerical failure encountered, 6 as the user abort, 7 as a timeout error, 9 as the model could be solved by presolve, 10 as the B&B routine failed, 11 as the B&B was stopped because of a break-at-first, 12 as a feasible B&B solution was found, 13 as no feasible B&B solution found.

GetObjective (LPModel)
+

Returns the objective function value of a LPModel.

GetVariable (LPModel, index)
+

Returns the value of a decision variable specified by the index.

GetVariables (LPModel)
+

Returns all values of the decision variables of a LPModel.

GetDual (LPModel, index)
+

Returns the dual value of a decision variable specified by the index.

GetDuals (LPModel)
+

Returns all dual values of the decision variables of a LPModel.

ReadLP("fileName.mps")
+

Reads a LPModel from a file (*.lp, *.mps) and returns the LPModel if succeed.

WriteLP (LPModel, "fileName.mps")
+

Writes a LPModel to a file (*.lp, *.mps) and returns true if succeed.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/docs/index.html b/en/docs/index.html new file mode 100644 index 00000000..32eefd4b --- /dev/null +++ b/en/docs/index.html @@ -0,0 +1,34 @@ + + + + + + + + + MicroCity Desktop Documents | MicroCity Notes + + + + + +
Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/index.html b/en/index.html new file mode 100644 index 00000000..df9e2a67 --- /dev/null +++ b/en/index.html @@ -0,0 +1,35 @@ + + + + + + + + + Home Page | MicroCity Notes + + + + + +

MicroCity Notes

Record the learning process of MicroCity and provide quick reference

Desktop docs Learning notes

Doc and Search 🔍

The desktop documentation is adapted from MicroCity's project docs with slight modifications. Quickly search and navigate content using the website's search functionality.

Learning Notes 📔

In addition to docs, find summaries of pitfalls in using and learning MicroCity Web/Desktop. These notes aim to help you avoid as many pitfalls as possible.

Stylish and Smooth ✨

VuePress powers this standalone site for a seamless reading and documentation reference. Install it as a Progressive Web App (PWA) for anytime access, irrespective of network constraints.

Getting Started with MicroCity Web

  1. Open MicroCity Webopen in new window, and the example code for rotating blocks will load by default.

  2. Click the Play button to run the code.

  3. The program will run, and you will see the blocks rotating in the right-hand view.

If you want to learn more about how to use MicroCity Web and its advanced features, you can refer to the Learning Notes provided on this site.

Getting Started with MicroCity Desktop

GitHub release (latest by date) GitHub release (by tag)

  1. Go to the MicroCity documentation repository to download the Latest Version of MicroCityopen in new window.

  2. Open the iconScriptEditor and type:

Print("hello, world!")
+
  1. Save the script as test.mcs and drag it into iconMicroCity.

  2. In the main interface of the program, go to the Modules tab on the left side, open icontest, and double-click on iconmain to execute the script you just wrote.

  3. The information about the execution of the script will be displayed in the Messages panel at the bottom of the program interface.

For more information on how to use MicroCity, you can refer to the documentation found on this site, which is a mirror of the documentation provided on GitHub: MicroCity Documentation. You can also refer to the documentation of MicroCtiy on GitHub at MicroCityopen in new window.

MicroCityNotes Repository

GitHub last commit GitHub Workflow Status Netlify Statusopen in new window

If users in China have difficulty accessing GitHub, they can also visit the Synchronized Siteopen in new window hosted on Netlify.

If you find any issues with the documentation or notes, please feel free to submit a Pull Requestopen in new window or provide Issuesopen in new window to help make it better😋.

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

+ + + diff --git a/notes/3d-objects-en.html b/en/notes/3d-objects.html similarity index 50% rename from notes/3d-objects-en.html rename to en/notes/3d-objects.html index 732dfcd3..164a2621 100644 --- a/notes/3d-objects-en.html +++ b/en/notes/3d-objects.html @@ -1,5 +1,5 @@ - + @@ -22,14 +22,14 @@ document.documentElement.classList.toggle('dark', true); } - 3D Objects | MicroCity笔记 + 3D Objects | MicroCity Notes - + -

3D Objects

This section will introduce the objects and their control functions in a 3D scene.

Adding Objects

To add objects to the scene, use the following function:

local obj = scene.addobj([type], {key1 = value1, key2 = value2, ...})
-

Optional Object Properties

Objects added to the scene typically support setting some of the following properties:

Object PropertyMeaning
colorThe color of the object. The format of the color can support built-in colors, hexadecimal, and RGB. Same as the background color of the scene
opacityOpacity
hcolorThe color when the object is selected
sizeThe size of the object. The default value is 1
lengthThe length of the object, commonly used for box
widthThe width of the object, commonly used for box
heightThe height of the object, commonly used for box
radiusThe size of the object's rounded corners
segmentsThe number of segments, usually used to set the precision of the sphere drawn
selectableWhether the object can be selected
nameThe name of the object
textThe text value of the object
fontThe font of the text
verticesThe set of points that make up the corresponding object

The following are the types of objects that can be added to the scene:

Object Types

List of Object Types

For the sake of brevity, the key properties of the optional objects shown in the example below only display the relevant attributes of the object. Other common properties can be added by referring to the Optional Object Properties.

label

label is a text label. The text of the label can be set in the text attribute.

local obj = scene.addobj('label', {text = "Hello World!"})
+    

3D Objects

This section will introduce the objects and their control functions in a 3D scene.

Adding Objects

To add objects to the scene, use the following function:

local obj = scene.addobj([type], {key1 = value1, key2 = value2, ...})
+

Optional Object Properties

Objects added to the scene typically support setting some of the following properties:

Object PropertyMeaning
colorThe color of the object. The format of the color can support built-in colors, hexadecimal, and RGB. Same as the background color of the scene
opacityOpacity
hcolorThe color when the object is selected
sizeThe size of the object. The default value is 1
lengthThe length of the object, commonly used for box
widthThe width of the object, commonly used for box
heightThe height of the object, commonly used for box
radiusThe size of the object's rounded corners
segmentsThe number of segments, usually used to set the precision of the sphere drawn
selectableWhether the object can be selected
nameThe name of the object
textThe text value of the object
fontThe font of the text
verticesThe set of points that make up the corresponding object

The following are the types of objects that can be added to the scene:

Object Types

List of Object Types

For the sake of brevity, the key properties of the optional objects shown in the example below only display the relevant attributes of the object. Other common properties can be added by referring to the Optional Object Properties.

label

label is a text label. The text of the label can be set in the text attribute.

local obj = scene.addobj('label', {text = "Hello World!"})
 

points

points is a collection of points. You can create a single point or multiple points. Each point has three-dimensional coordinates to determine its position in three-dimensional space. The number of points is determined by the vertices attribute.

Here is an example of creating a points object:

-- create a point at position (5,5,5)
 scene.addobj("points", {vertices = {5,5,5}, size = 5})
 
@@ -64,7 +64,7 @@
 

getparent()

Gets the parent object of obj.

local num = obj:getparent()
 

setparent()

Sets the parent object of obj to obj0.

obj:setparent(obj0)
 

delete()

Delete obj.

obj:delete()
-
Last Updated:
Contributors: huuhghhgyg
- +
Last Updated:
Contributors: huuhghhgyg
+ diff --git a/en/notes/3d-scene.html b/en/notes/3d-scene.html new file mode 100644 index 00000000..73cc0581 --- /dev/null +++ b/en/notes/3d-scene.html @@ -0,0 +1,39 @@ + + + + + + + + + 3D Scene | MicroCity Notes + + + + + +

3D Scene

This section introduces 3D scenes and their settings.

MicroCityWeb 3D Scene Coordinate System

The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate system, and the specific direction of each coordinate axis is shown in the following figure.

Coordinate system in MicroCityWeb

Coordinate system in MicroCityWeb

Note that the three-dimensional coordinate axes x, y, and z here are manually drawn to show the coordinate system in MicroCityWeb and do not directly exist in the three-dimensional scene.

Setting up a Scene

Setting up a scene requires the use of the setenv function, with the specific usage as follows:

local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true})
+

It can be simplified as follows:

local s = scene.setenv({key1 = value1, key2 = value2, ...})
+

The variable s holds the returned environment object. The optional parameters of the function will be described in detail below.

Optional Parameters of a Scene

Parameter List

grid: Background grid of the scene

Optional values

ValueMeaning
"none"default, no grid
"plane"flat grid
"sphere"spherical grid

bgcolor: Background color of the scene

Optional value types:

Value TypeExample
Built-in colors"black", "white", "gray", etc.
Hexadecimal colors"#ffffff", "#fff", "#000000", "#000", etc.
Colors represented by RGB"rgb(255, 255, 255)", "rgb(0, 0, 0)", etc.

Example:

scene.setenv({bgcolor='gray'}) -- Sets the background color to the built-in color "gray"
+scene.setenv({bgcolor='#eee'}) -- Sets the background color to the hexadecimal color "#eee"
+scene.setenv({bgcolor='rgb(255, 255, 255)'}) -- Sets the background color to white
+

camtype: Camera angle of view

Optional values:

ValueMeaning
"ortho"Orthographic. Equivalent to a projection onto the x and y plane. User's view is in two-dimensional space.
"persp"Perspective (default). User's view is in three-dimensional space.

clear: Whether to clear the scene

When the value is set to true, the scene is cleared.

The setenv function does not clear the original scene by default, unless the value of the clear parameter is manually set to true.

rotspeed & transpeed

ValueMeaning
rotspeedSets the speed of rotating a 3D object with the mouse.
transpeedSets the speed of translating a 3D object with the mouse.

These two parameters usually do not need to be set specially, and the default values can be used.

Others

Regarding high-frequency setting scenarios

2023/03/21: It has been found that setting the scene too frequently can cause excessive memory usage and browser crashes. Therefore, it is recommended to avoid calling the scene.setenv() function in a loop as much as possible.

If it is necessary to do so, make sure that the frequency of calls is relatively low. This allows the browser to have enough time for garbage collection, otherwise it may cause the browser to crash.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/cy-simulation.html b/en/notes/cy-simulation.html new file mode 100644 index 00000000..3febe50b --- /dev/null +++ b/en/notes/cy-simulation.html @@ -0,0 +1,34 @@ + + + + + + + + + Port AGV Service Process 3D Simulation Approach | MicroCity Notes + + + + + +

Port AGV Service Process 3D Simulation Approach

This train of thought is for reference only.

Banner

Simulating the process of a container terminal is a complex task that involves many factors and entities. This article mainly introduces the approach to simulate the process of AGV receiving services from the yard crane to accepting services from the quay crane using MicroCityWeb.

Implementing Yard Crane Handling of Containers

Problem 1 Screenshot

Overall Approach

Implementing the handling of containers by the yard crane is the first step in simulating the yard. I plan to use an object-oriented approach for this part, abstracting the yard crane and the yard as objects.

Overall Structure

The specific idea is to treat the yard as a data model that stores various data, such as container entities, coordinates of containers in corresponding positions (rows, columns, heights), etc. The yard crane is treated as an operator responsible for the yard crane's 3D animation and management of data in the yard object.

The benefit of doing this is to decouple the yard crane from the yard, making it easier to expand in the future. In addition, if the object's properties are well considered, multiple objects can be easily created in the same scene to simulate multiple yard cranes operating in the yard.

Events and Tasks

I plan to create task sequences for the main entity objects that require movement in the overall process. This allows for parallel operations of multiple yard cranes in the same scene, with each yard crane performing its own tasks without interfering with each other. In addition, a central control program is needed to control the execution of tasks at each time node and the 3D animation of the yard crane.

Business Process

In this simulation, the main focus of the business process is the movement of containers. Therefore, the most important aspect is the transfer of ownership of containers. The process flow of container ownership transfer is shown in the following diagram:

Container Object Process Flow

Container Object Process Flow

Object Structure

The following are the structures of the main objects involved in this simulation.

Structure of Yard Crane Object

Structure of Yard Object

Implementation Approach

Yard Size

For the yard object, since its main function is to store container objects and related data (such as coordinates of corresponding positions), we need to determine the size of the yard. Therefore, determining the size of the yard is a necessary step. When creating the yard object, we need to determine the size of the yard, including the number of rows, columns, and height. This facilitates subsequent operations.

My approach is to first determine the area occupied by the yard and the number of container layers. Based on the relevant data, we can calculate the maximum number of rows and columns that can be used to place containers.

  • Regarding the area occupied by the yard, it can be determined by inputting the coordinates of two points when creating the object. Based on the diagonal formed by connecting the two points, we can determine the area occupied by the yard.
  • As for the number of container layers, it can be determined by inputting a number when creating the object. Based on these two inputs, we can determine the size of the yard.

Yard Layout Calculation

Events and Tasks

Since the yard crane is the main object that needs to be moved in this simulation, we only need to operate the yard crane during each loop of task execution.

Therefore, I plan to treat the task sequence of the yard crane as a queue. During each loop of task execution, we take out the first task from the object's task sequence and execute it. After execution, we check if the task completion condition is met. If so, we delete the task and move on to the next one. This ensures that the yard crane objects execute tasks in order during each loop of task execution.

The method for executing tasks is executeTask(dt), where the object executes tasks based on the duration dt. The executeTask(dt) function contains the logic for processing tasks, including task type determination, task execution, and task deletion.

If there are multiple yard cranes in the scene, simply add these objects to the list of objects executing tasks. During each loop of task execution, the main control program will iterate through this list of objects and execute tasks for each object.

Tips

Note that although the task execution appears to be simultaneous in terms of time, it actually depends on the sequence position of the objects.

One example is: suppose two objects need to occupy position A at the same time. According to the order of the task sequence, the object that is executed first will occupy position A, while the object that is executed later will fail to occupy it, even though they are both trying to occupy position A at the same moment. Therefore, it is not strictly simultaneous execution here, but sequential execution according to the task sequence at the same time.

Business Process

  1. The yard crane first obtains the coordinates of the corresponding position (row, column, height) of the container from the yard and moves the spreader to the designated position in the yard to grab the container. The ownership of the container is transferred from the yard (cy.containers) to the yard crane spreader (rmg.attached) (by removing the table reference, setting the value to nil).
  2. The yard crane moves the container to the aisle and releases it there. In the same way, the ownership of the container is transferred from the yard crane spreader (rmg.attached) to the aisle (rmg.stash), indicating that the container can be picked up.
  3. If there is a vehicle that takes away the container, the ownership of the container can be further transferred from the aisle of the yard crane (rmg.stash) to the vehicle.

Results

Yard Crane Simulation

Implementation of the Whole Process from AGV Arrival to Service

Problem Description

Problem 2 Description

Implement the three-dimensional representation of the process above using event scheduling method.

What's New

The implementation of the previous simulation serves as the foundation for this simulation. Compared to the previous simulation, the most significant improvement in this simulation is:

  • Using the object-oriented programming paradigm to create objects of four types: yard crane, yard (data model), AGV, quay crane, and ship (data model), and implement the movement methods for the objects and their components.

If you are not familiar with object-oriented programming, you can refer to General Knowledge - Object-Oriented Programming.

  • Continuing with the idea of event-driven simulation, the overall control process is implemented to control multiple objects simultaneously at the same time (primarily achieved through the object's executeTask(dt) and maxStep() functions). In the object-oriented programming paradigm, executeTask(dt) and maxStep() can be seen as interfaces. The main program controls the objects by implementing these two interfaces. (Although Lua seems to lack this concept.)
  • Using task sequences to implement the flow of each object, achieving mutual waiting between the yard crane and AGV, and between the AGV and quay crane, and coordinating tasks between different objects.
  • Attempting to extend the flow from the yard to the AGV, and then to the quay crane and ship, implementing two-level queuing and waiting.

Object Design

Due to the large number of attributes and functions, the design of objects is presented in the form of a mind map.

Tips

This section takes up a lot of space. You can also directly jump to the next section Overall Layout.

Yard

The yard remains as the data model. Yard

Yard Crane

Yard Crane

AGV

AGV

Quay Crane

The code and structures involving the quay crane are derived mainly from the yard, so they will not be described in detail later. Quay Crane

Ship

The ship object also serves as a data model, designed similarly to the yard.

Ship

Overall Layout

Overall Layout

Overall Process

Overall Process Diagram

Container Flow Process

Compared to the previous simulation, this simulation goes further in terms of the process. It adds the flow of AGV arrival and queuing, as well as the service of the quay crane and container loading onto the ship.

Process Analysis

With the introduction of AGVs, the flow between the yard crane, quay crane, and AGV has becomes more complex. First, the arrival of AGVs is random, which may cause queuing. Second, the arrival of AGVs triggers the flows of the yard crane and AGV, which in turn trigger the flow of the quay crane. Therefore, the flow of this simulation is a multi-level flow that needs to consider the coordination between multiple objects.

Especially in the process between AGV and RMG, there is a mutual waiting between AGV and RMG. When the AGV arrives, it needs to notify the RMG to extract the cargo. In the process of extraction by the RMG:

  • The RMG needs to wait for the AGV to arrive at the designated position before it can move the cargo onto the AGV.
  • The AGV needs to wait for the RMG to grab the container and place it on the AGV before transferring the ownership of the container from the RMG to the AGV.

Therefore, the process between the AGV and the RMG is a mutually waiting process. The specific process can be referred to in the diagram below.

Process Diagram of Mutual Waiting between AGV and RMG

The process of the quay crane is similar to that of the RMG, which is also a mutually waiting process. The main points are:

  • When the AGV arrives at the designated position, the quay crane may be serving other AGVs, so the AGV has to wait.
  • When the AGV just enters the service area of the quay crane, it notifies the quay crane to reach the designated position. If the quay crane arrives at the designated position first, it has to wait.

Implementation Method

Implementation of Queuing Process

For AGV queuing, I chose to use cellular automaton as the data model of parking spaces. The length of each parking space is:

Length of Parking Space=Length of 1 Container in the data model+Gap between containers \text{Length of Parking Space} = \text{Length of 1 Container in the data model} + \text{Gap between containers}

Since the length of the AGV is slightly longer than that of 1 container, it needs to occupy the length of 2 parking spaces. When executing a task, the AGV checks if the space ahead is blocked, and if not, it moves forward. If the space ahead is the target bay, it moves forward and waits for the RMG operation, then continues to move forward in terms of cells until it leaves. The queuing principles for the RMG and quay crane are also the same.

AGV Queuing Diagram

Diagram of AGV Cellular Automaton Queuing Model

Implementation of Event Scheduling Method

In the previous simulation, I used a variable step size to advance the time for simulation. In this simulation, I used the event scheduling method to accurately advance the events to their occurrence time for execution.

You may have noticed that in the Object Design section, executeTask() and maxstep() are marked as (interface). This is because to calculate the accurate advancement time, I need to implement executeTask() and maxstep() methods in each object. The executeTask() method is used to execute the task, and the maxstep() method is used to calculate the time remaining for the current task to be completed and obtain the maximum advancement time based on that, and then compare it with the interval time dt obtained from the system execution to get the maximum advancement time.

I believe that the following diagram from the course can effectively represent how the event scheduling method is used for simulation and scene refreshing. The first row refers to the business process of simulation, and the Refresh part in the second row refers to refreshing the scene.

Event Scheduling Diagram

Results

Note

The following parts contain animated GIFs, and the images have a large file size. Since this site is hosted on GitHub Pages, if you don't have a special network environment, the animated GIFs may load slowly or even fail to load.

Tips

If you encounter moiré patterns in the animated GIFs while directly viewing them, you can try opening them to enlarge the view and see if there is any improvement.

RMG running process RMG Running Process 1

RMG Running Process 2

Quay crane running process Quay Crane Running Process

Overall running process Overall Running Process 1

Overall Running Process 2

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/debug.html b/en/notes/debug.html new file mode 100644 index 00000000..57453189 --- /dev/null +++ b/en/notes/debug.html @@ -0,0 +1,50 @@ + + + + + + + + + Debugging | MicroCity Notes + + + + + +

Debugging

This page introduces the functions and shortcuts related to debugging in MicroCity Web.

Clearing Output

Right-clicking on the output area allows you to enter commands. Entering print() clears the content of the output area.

Debugger Shortcuts

During the process of debugging a program, especially at breakpoints, you can use F9 (Step Over), F10 (Step Into), and F11 (Step Out) to control the program execution.

  • F9 Step Over: Skips the current line and executes the next line.
  • F10 Step Into: Enters the current line. If the current line is a function call, it enters the function body.
  • F11 Step Out: Exits the current function and executes the next line after the function call.

Debug Commands

Watching Variables

Use the debug.watch() command in the console to monitor variables.

For example, if you want to monitor the value of variable a during debugging, you can use the debug.watch('a') command.

Right-clicking on the output area allows you to enter commands.

Stack Trace

The debug.traceback() function can print the current stack trace information.

function myFunction()
+    -- Some code logic
+    print(debug.traceback("Stack trace"))
+    -- Other code logic
+end
+
+function anotherFunction()
+    myFunction()
+end
+
+anotherFunction()
+

Output:

Stack trace
+stack traceback:
+[string "function myFunction() ..."]:3: in function 'myFunction'
+[string "function myFunction() ..."]:8: in function 'anotherFunction'
+[string "function myFunction() ..."]:11: in main chunk
+

Running Status

  • debug.debug() enters Debug mode. It is often used to enter Debug mode during program execution. If you want to start in Debug mode, you can right-click the top ▶️ button. See User Interface Introduction - Running Status for details.
  • debug.pause() pauses program execution. The Run button ▶️ at the top will light up, and the Pause button ⏸️ will turn off.

Other Debug Commands

Most of Lua's Debug functions are applicable to MicroCity Web. For reference, please see:

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/event-scheduling.html b/en/notes/event-scheduling.html new file mode 100644 index 00000000..bdcf35d4 --- /dev/null +++ b/en/notes/event-scheduling.html @@ -0,0 +1,95 @@ + + + + + + + + + Discrete Event Simulation and Program Control | MicroCity Notes + + + + + +

Discrete Event Simulation and Program Control

Coroutines

MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling.

coroutine.queue

Adds a function or coroutine to the coroutine queue for execution after a specified relative time.

coroutine.queue(rt, f|co [, argument list...])
+

Parameters

ParameterDescription
rtRelative time from the current queue. It should be greater than or equal to 0. In other words, it specifies the time after which the input function or coroutine will be executed.
f/coFunction or coroutine. If it's a function, you only need to input the function name.

coroutine.qtime

Retrieves the current time of the queue.

local time = coroutine.qtime()
+

Example

Here are two examples provided:

Adding Coroutines to the Queue

This example demonstrates how to add coroutines to the queue and display the current queue time within the function.

function Show()
+    print("Current time:", coroutine.qtime())
+end
+
+function ShowShort()
+    print("Current time (short):", coroutine.qtime())
+end
+
+coroutine.queue(10, Show)
+coroutine.queue(20, Show)
+coroutine.queue(15, ShowShort)
+coroutine.queue(5, Show)
+
+-- Result:
+-- Current time: 5.0
+-- Current time: 10.0
+-- Current time (short): 15.0
+-- Current time: 20.0
+

Vehicle Movement

This example demonstrates how to use coroutines to refresh the scene based on real-world time.

scene.setenv({grid='plane'}) -- Set the scene background grid
+
+-- Vehicle
+local car = scene.addobj('/res/2axle.glb')
+car.speed = 1 -- Car speed
+
+-- Initial time
+local t = os.clock()
+local dt = 0
+
+-- Refresh time state t and dt (based on CPU intervals to synchronize with real-world time)
+function refreshtime()
+    dt = os.clock() - t
+    t = os.clock()
+end
+
+-- Coroutine updates the scene
+function update()
+    if not scene.render() then return end -- Render the scene and check if the program is terminated
+    coroutine.queue(dt, update) -- Add the next update based on CPU step time
+    carmove() -- Move the vehicle
+    refreshtime() -- Calculate the current dt
+end
+
+-- Vehicle movement
+function carmove()
+    print("Car moves at", t)
+    local x, y, z = car:getpos()
+    car:setpos(x, y, z + dt * car.speed)
+end
+
+-- Initial update (add the first update)
+-- Since subsequent updates are added within the function, the updates will loop automatically
+coroutine.queue(dt, update)
+

Random Numbers

Creating a Random Seed

local seed = math.randomseed(x [, dist])
+

Parameters

ParameterDescription
xRandom seed. Different input values will produce different random numbers. To get different values each time, consider setting the random seed x to the current time.
distRandom distribution (optional). If not set, the default is a uniform distribution. If this parameter is set, you can also specify mu and sigma as parameters for the corresponding distribution.

The dist parameter can be set to one of three distributions:

  • 'normal': Normal distribution
  • 'exponential': Exponential distribution
  • 'poisson': Poisson distribution

In addition, you can set parameters for these distributions, where the mu key represents the mean and the sigma key represents the standard deviation.

Example

-- Create a random seed with a Poisson distribution
+local seed = math.randomseed(os.time(), {distribution = "poisson", mu = "3"}) -- Poisson distribution with a mean of 3
+
+-- Output a random number
+print(seed:random())
+

Program Control

Program control, in this context, mainly refers to controlling the execution of a program using the buttons in the user interface, including pause, resume, and stop.

This mainly refers to the first three buttons in the command bar.

In MicroCityWeb, program control refers to the pause, resume, and stop of the 3D interface rendering implemented through the scene object. The specific function is as follows:

local state = scene.render()
+

Here, the return value of scene.render() is stored in the state variable. The state variable can be either true or false, representing the running or terminated state of the program (button 3 in the command bar).

Pausing the rendering of 3D objects is also achieved by calling scene.render(). If the refresh of 3D objects is implemented by continuously calling the scene.render() function and the refresh interval is not controlled by os.sleep(), it is possible to pause the rendering of the 3D interface at a certain state. This is because if os.sleep() is used to control the speed of 3D object movement and the pause button is clicked while the program is in the os.sleep() process, the program may not respond immediately, resulting in the pause button becoming ineffective. Therefore, it is recommended not to use os.sleep() for controlling the speed of 3D object movement, but to use other parameters to control the duration of advancement in order to control the speed of 3D object movement.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/index.html b/en/notes/index.html new file mode 100644 index 00000000..4c1fc92d --- /dev/null +++ b/en/notes/index.html @@ -0,0 +1,34 @@ + + + + + + + + + Notes | MicroCity Notes + + + + + +

Notes

General Knowledge

MicroCity (Desktop Version)

MicroCityWeb

Ideas

The notes referenced in this page directory apply to the corresponding versions of MicroCity. Special thanks to Sun Zhuo (MicroCity author)open in new window for the guidance and assistance during the writing and organizing process.

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/lp.html b/en/notes/lp.html new file mode 100644 index 00000000..b332a281 --- /dev/null +++ b/en/notes/lp.html @@ -0,0 +1,178 @@ + + + + + + + + + Model Solving | MicroCity Notes + + + + + +

Model Solving

In MicroCity, mathematical models can be solved. In this article, we will introduce the common process of solving mathematical models in MicroCity and provide some tips to help you better build models.

The detailed usage of all functions in the planning model can be found in the document 4.8 Mixed Integer Linear Programming.

Tips

The content on this page is based on MicroCity Desktop version. If you are looking for a solution for mixed integer programming in MicroCity Web version, please refer to the corresponding Mixed Integer Programming section in the MicroCity Web notes.

Creating Model Objects

Create a planning model object and store it in the variable lp.

local lp = CreateLP()
+

The mathematical model object created in the official documentation is stored in the variable LPModel, which has the same function as lp in this article.

Writing Mathematical Models

At this point, the object of the mathematical model has been created and stored in the variable lp, and further operations can be performed on it. A mathematical model generally consists of two parts:

Next, let's introduce how to create the objective function.

Creating the Objective Function

In MicroCity, SetObjectFunction() is used to set the objective function of the model object. It allows you to choose whether to optimize for maximum or minimum. The specific usage is as follows:

Maximum
SetObjFunction(lp, coeff, "max") -- Optimize for maximum
+

"min" and "max" are case-insensitive, so "MIN" and "MAX" can also be used.

Parameter Description and Example

ParameterDescription
lpMathematical model object. Input the mathematical model into the function to set the objective function.
coeffObjective function coefficients, which is a table type variable. Used to determine the coefficients of the objective function in the model.
"min" or "max"Determine whether to optimize for the maximum or the minimum of the objective function.

coeff is a coefficient list for the objective function, which is a table type variable. Suppose you want to minimize the function 4x1+12x2+18x34x_1+12x_2+18x_3, the procedure to add the objective function is as follows:

-- Suppose you have already created the model object and stored it in the variable lp
+
+-- 4*x1 + 12*x2 + 18*x3
+local coeff = {4, 12, 18}
+
+-- Set the objective function: minimize
+SetObjFunction(lp, coeff, "min")
+

Adding Constraint Equations

In MicroCity, the function for adding model constraints is AddConstraint(), used as follows:

-- Use symbols to express
+AddConstraint(lp, cons, "<=", b)
+
+-- Alternatively, you can use abbreviations
+AddConstraint(lp, cons, "le", b)
+

Parameter Description

ParameterDescription
lpMathematical model object. Input the mathematical model into the function to add constraints to it.
consConstraint equation coefficients. Similar to cons in setting the objective function, it is also a table type variable used to determine the coefficients of each variable in the constraint equation.
"<=" or ">=" or "==", or their corresponding alphabetic expressionsDetermines the relationship between the constraint equation and the right-hand side.
bA number representing the right-hand side of the constraint equation. It can be a variable or a constant.

Example

The objective function 4x1+12x2+18x34x_1+12x_2+18x_3 has been set above. Suppose you want to add two constraint equations for this function:

{x1+3x332x2+2x35 \left\{\begin{matrix} x_1+3x_3\ge3 \\ 2x_2+2x_3\ge5 \end{matrix}\right.

Add corresponding constraint equations:

-- Add constraint: x1+3*x3≥3
+cons = { 1, 0, 3 }
+AddConstraint(lp, cons, ">=", 3)
+
+-- Add constraint: 2*x2+2*x3≥5
+cons = { 0, 2, 2 }
+AddConstraint(lp, cons, ">=", 5)
+

It is not difficult to notice that the number of coefficients is consistent with the number of variables in the objective function. Therefore, before programming the solution, you need to first determine the total number of variables and arrange the positions of each variable.

Set Variable Types

MicroCity's mathematical programming supports integer programming. If no SetUnbounded() is set for the variables, the default value range for the variables is non-negative real numbers (≥0). The following describes in detail how to set variable types.

You can set the integer variable or 0-1 variable for the i-th variable in the model. If the variable is not set to these types, the default variable is non-negative real number.

Integer Variables
SetInteger(lp, i) -- Integer variable
+

To allow the value of the i-th variable to be negative (by default, it cannot be negative):

SetUnbounded(lp, i)
+

Model Solving and Output

Model Solving

Since both the objective function and the constraint equations have been added, solving the model is simple, just one step:

SolveLP(lp)
+

After executing this statement, the mathematical model stored in the variable lp is solved.

Output

After solving the problem, it still needs to be output to understand the result of the solution. The following are commonly used functions for outputting the solution result.

Obtain the objective function value:

GetObjective(lp)
+

Obtain the value of the i-th variable:

GetVariable(lp, i)
+

SolveLP

The SolveLP() function also has output after the solution is obtained, the meaning of the output code is as follows:

Output CodeMeaning
0Success
-1Invalid LP Model
-2Out of Memory
1Suboptimal
2Infeasible
3Unbounded
4Degenerate
5Numerical Error
6User Termination
7Timeout Error

For the meaning of other return values, please refer to the documentation 4.8 Mixed Integer Linear Programming for the SolveLP() function.

Model Solution Example

Here is a simple example of modeling and solving for reference. (Actually it just strings together the previous content)

Example:

minf=4x1+12x2+18x3s.t.{x1+3x332x2+2x35x1,x2,x3N minf=4x_1+12x_2+18x_3\\ s.t.\left\{\begin{matrix} x_1+3x_3\ge3 \\ 2x_2+2x_3\ge5 \\ x_1,x_2,x_3\in N \end{matrix}\right.

N represents the set of natural numbers (non-negative integers)

Script:

-- Create linear programming object
+local lp = CreateLP()
+
+local n = 3 -- Set the number of objective functions
+
+-- Objective function: 4*x1 + 12*x2 + 18*x3
+-- Set the coefficients of the objective function, and the objective function is minimized
+local coeff = { 4, 12, 18 }
+SetObjFunction(lp, coeff, "min")
+
+-- Add constraint 1: x1 + 3*x3 ≥ 3
+cons = { 1, 0, 3 }
+AddConstraint(lp, cons, ">=", 3)
+
+-- Add constraint 2: 2*x2 + 2*x3 ≥ 5
+cons = { 0, 2, 2 }
+AddConstraint(lp, cons, ">=", 5)
+
+-- Since SetUnbounded() is not set,
+-- by default, all variables are non-negative,
+-- so there is no need to add constraints for non-negative variables.
+
+-- Set all variables to integers
+for i = 1, n do
+    SetInteger(lp, i)
+end
+
+-- Solve the model
+SolveLP(lp)
+
+-- Output the objective function value
+print("Objective function value:", GetObjective(lp))
+
+-- Output the values of each variable
+for i = 1, n do
+    print("x", i, "=", GetVariable(lp, i))
+end
+

Output:

Objective function value: 42
+x1=0
+x2=2
+x3=1
+

Some Techniques for Modeling

Linearization

Sometimes we encounter modeling problems with multiple subscripts, such as the decision variable xijx_{ij}, which needs to be linearized.

Let's assume that the shape of the decision variable itself is 3 rows and 4 columns, that is:

Column 1Column 2Column 3Column 4
x11x_{11}x12x_{12}x13x_{13}x14x_{14}
x21x_{21}x22x_{22}x23x_{23}x24x_{24}
x31x_{31}x32x_{32}x33x_{33}x34x_{34}

Assuming that the objective function is to sum up these decision variables, which is F=i=13j=14xijF=\sum_{i=1}^3\sum_{j=1}^4x_{ij}, if we want to input it into the objective function, we can linearize it as x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}.

Since there are only two dimensions, we can use two for loops to achieve this:

local cons = {}
+for i = 1, 3 do -- the first dimension
+    for j = 1, 4 do -- the second dimension
+        cons[4 * (i - 1) + j] = 1 -- fill in the coefficients
+        -- the idea of 4 * (i - 1) + j is similar to carrying
+    end
+end
+
+-- result:
+-- cons has a length of 12, and all values are 1
+

Example: Assignment Model

Let's take a look at the specific usage and convenience of multidimensional linearization using an actual example.

Four people, A, B, C, and D, are assigned to deliver four types of goods, A, B, C, and D, with the corresponding delivery times shown in the table. If each person delivers only one type of goods, who should be assigned to deliver which type of goods to minimize the total time?

Person\GoodsABCD
A149415
B117910
C132105
D1791513

Let's assume that the numbers corresponding to goods A, B, C, D are 1, 2, 3, 4 respectively, and xij=1x_{ij}=1 represents person i delivering goods j, and xij=0x_{ij}=0 represents person i not delivering goods j.

The mathematical model of the above problem can be represented as

minZ=i=14j=14cijxijs.t.{j=14xij=1,i=1,2,...,4i=14xij=1,j=1,2,...,4xij=0,1 minZ=\sum_{i=1}^4\sum_{j=1}^4c_{ij}x_{ij}\\ s.t.\left\{\begin{matrix} \sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\ \sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\ x_{ij}=0,1 \end{matrix}\right.

Solution code:

-- efficiency matrix
+local cost = {
+    { 14, 9, 4, 15 },
+    { 11, 7, 9, 10 },
+    { 13, 2, 10, 5 },
+    { 17, 9, 15, 13 }
+}
+
+local lp = CreateLP()
+
+-- create the objective function
+local coeff = {}
+for i = 1, 4 do
+    for j = 1, 4 do
+        -- it is easy to convert a two-dimensional array to a one-dimensional array here
+        coeff[4 * (i - 1) + j] = cost[i][j]
+    end
+end
+
+SetObjFunction(lp, coeff, "min")
+
+-- add constraints
+for k = 1, 4 do -- control the value of the i dimension
+    local cons = {}
+    for i = 1, 4 do
+        for j = 1, 4 do
+            if i == k then -- sum up j, check i
+                cons[4 * (i - 1) + j] = 1
+            else
+                cons[4 * (i - 1) + j] = 0
+            end
+        end
+    end
+    AddConstraint(lp, cons, "==", 1)
+end
+

for k = 1, 4 do -- Control the value of the jth dimension local cons = {} for i = 1, 4 do for j = 1, 4 do if j == k then -- Sum i and check j cons[4 * (i - 1) + j] = 1 else cons[4 * (i - 1) + j] = 0 end end end AddConstraint(lp, cons, "==", 1) end

-- Solve the model SolveLP(lp)

-- Output the objective function value print("Objective function value:", GetObjective(lp))

-- Output the decision variables for i = 1, 4 do -- First dimension for j = 1, 4 do -- Second dimension local x = GetVariable(lp, 4 * (i - 1) + j) if x ~= 0 then print("x[", i, "][", j, "]=", x) end end end


+Output
+

Objective function value: 29 x[1][3]=1 x[2][1]=1 x[3][4]=1 x[4][2]=1

| Result      | Person | Item |
+| ----------  | :---: | :------: |
+| $x_{13}=1$  |   A   |    C     |
+| $x_{21}=1$  |   B   |    A     |
+| $x_{34}=1$  |   C   |    D     |
+| $x_{42}=1$  |   D   |    B     |
+
+### Handling Intermediate Variables
+Sometimes there may be intermediate variables in the model that need to have corresponding positions in the matrix in order to be solved, but these intermediate variables do not participate in the calculation of the objective function value. **You can set the coefficients of these intermediate variables to 0 at their corresponding positions.**
+
+Let $x_1, x_2, x_3, x_4$ be the decision variables and $y_1, y_2$ be the intermediate variables. The objective function is:
+$$
+z = \sum_{i=1}^4 x_i
+$$
+Then the coefficients of the objective function can be set as:
+```lua
+local fcons = {1, 1, 1, 1, 0, 0}
+

After that, you can proceed with the general process 😎

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/lua.html b/en/notes/lua.html new file mode 100644 index 00000000..451254b1 --- /dev/null +++ b/en/notes/lua.html @@ -0,0 +1,242 @@ + + + + + + + + + Quick Start with Lua Language | MicroCity Notes + + + + + +

Quick Start with Lua Language

Since MicroCity uses the Lua scripting language, it is necessary to familiarize yourself with the basic usage of Lua before starting to write scripts with MicroCity. This article introduces the commonly used syntax for writing Lua scripts in MicroCity, which can help you quickly understand the overall approach to writing MicroCity scripts based on concepts from other programming languages.

Variable and Function Definition

Lua automatically recognizes variable types, so there is no need to define variable types before variable names. You can assign values directly.

a = 1.5
+b = "string"
+c = {} -- c is a table, explained below
+

Function definition

function add(a, b)
+    return a + b
+end
+

Above is a simple definition of the add() function, which aims to add the two input variables and return the result.

Variables can be global or local, and functions are the same. Here is how to define local variables and functions.

-- Define a local function
+local function show(msg)
+    print(msg)
+end
+
+-- Define a local variable
+local a = 1
+

If there is a conflict between locally defined content (function or variable) and globally defined content, the locally defined content takes precedence. When such a conflict exists, the content you are operating on is the local content.

If there is no explicit need to manipulate global variables, it is recommended to define variables as local variables as much as possible. This practice may reduce the occurrence of bugs and is a safer approach.

Condition

It's all about if, and there are several specific forms of implementation:

  1. Normal form
if condition then
+    print("condition==true")
+end
+
  1. Form with else
if condition then
+    print("condition==true")
+else
+    print("condition==false")
+end
+
  1. Form with elseif
if number > 0 then
+    print("number>0")
+elseif number < 0 then
+    print("number<0")
+else
+    print("number==0")
+end
+

In Lua, the equality operator is ==, and the inequality operator is ~=. You can apply these operators to conditional expressions. Here is a simple example:

print(1==1) -- true
+print(1~=1) -- false
+

Loop

Here are two most commonly used loops: for and while.

for

The simplest form

-- Output numbers from 1 to 10, a total of 10 numbers
+for i = 1,10 do
+    print(i)
+end
+

If you are familiar with C or C-like languages, the corresponding form of the above code is as follows:

for(int i=1; i<=10; i++){
+    printf("%d\n",i);
+}
+

Taking step size into consideration

-- Output numbers from 10 to 1, a total of 10 numbers with a step size of -1
+for i = 10,1,-1 do
+    print(i)
+end
+

When the step size is negative, it is important to note that the starting and ending numbers should be in reverse order.

Generic loop You can directly traverse all elements in a table. i is the index of the table element, starting from 1; v is the value of the table element.

a = {4,7,9}
+for i,v in ipairs(a) do
+    print("index=",i,"\tvalue=",v)
+end
+

ipairs is used for arrays (guessing i stands for integer), and pairs is used for objects. Since arrays are also objects, pairs can be used for arrays as well.

while

There is only one commonly used method for while.

local condition = true
+while condition do
+    print("while==true")
+    condition = false
+end
+

Similar to C-like languages. As long as condition is true, while will continue to run. When condition is set to false, the while loop will end.

Loop Operators

Just like in other languages, the break keyword is used to exit a loop. In Lua, there is no continue, only break. However, the continue functionality can be achieved by using the if + break structure.

Lua's Small Feature: Tables

Although Lua refers to its arrays as tables, I think this data structure is more similar to Python sets or JSON, as it can store anything without any structural constraints.

collection = {{"a", 1, 2}, "abc", {2, 3}}
+

To find the length of an array, simply prepend # before the array name.

list = {1, 2, 3, 4, 5}
+for i=1,#list do
+    print(list[i])
+end
+

In Lua, array (table) indices start from 1, unlike C-like languages where they start from 0. Taking the previously defined collection as an example:

-- collection = {{"a", 1, 2}, "abc", {2, 3}}
+print(collection[1][1]) -- a
+print(collection[2]) -- abc
+print(collection[3][2]) -- 3
+

Indexing

Lua table indexing is very flexible and can be done with numbers, strings, or even other types of data.

Here are some simple examples:

local list = {}
+
+-- Indexing with numbers
+list[1] = "a"
+
+-- Indexing with strings
+list["b"] = 2
+list.message = "hello world" -- Equivalent to list["message"] = "hello world"
+
+print(list[1]) -- a
+print(list["b"]) -- 2
+print(list.message) -- hello world
+

Adding Elements

Adding to a specific position

table.insert(table, pos, value) -- Inserts an element at a specific position (pos)
+

Or

table.insert(table, value) -- Appends an element at the end
+

Example

list = {1, 2, 3, 4, 5}
+table.insert(list, 6)
+-- {1, 2, 3, 4, 5, 6}
+

Removing Elements

table.remove(table, pos) -- Removes an element at a specific position
+

Example

list = {1, 2, 3, 4, 5}
+table.remove(list, 2)
+-- {1, 3, 4, 5}
+

Sorting a Table

Default Sorting Method

You can use a function to sort a list, and the simplest usage is as follows:

table.sort(list) -- Sorts the list in ascending order
+

Here is an example:

-- Function: Print List
+function PrintList(list)
+    -- Output the list
+    local listStr = ""
+    for i = 1, #list do
+        listStr = listStr .. list[i] .. " "
+    end
+    print(listStr)
+end
+
+local list = { 3, 7, 2, 5, 4 } -- Original list
+
+PrintList(list) -- Output the original list
+table.sort(list) -- Sort the list
+PrintList(list) -- Output the sorted list
+
+-- Result:
+-- 3 7 2 5 4 (Original list)
+-- 2 3 4 5 7 (Sorted list)
+

Custom Sorting Method

The table.sort function can also use a custom sorting rule, but this rule needs to be written in a function.

table.sort(list, function(a, b))
+

The function(a, b) is the custom sorting rule, which requires returning a boolean value (true or false) in the end. a and b are any two items in the list, and if the function returns true, then a comes before b, otherwise b comes before a.

Below are two examples for reference.

Example 1: Changing the code above to output in descending order
-- The PrintList() function is omitted here, with the same code as above
+
+local list = { 3, 7, 2, 5, 4 } -- Original list
+
+PrintList(list) -- Output the original list
+table.sort(list, function(a, b) -- Sort the list
+    return a > b -- Sort in descending order, if a > b, then a comes before b
+end)
+PrintList(list) -- Output the sorted list
+
+-- Output:
+-- 3 7 2 5 4 (Original list)
+-- 7 5 4 3 2 (Sorted list)
+
Example 2: Sorting in a two-dimensional array
-- Function: Print the list
+function PrintList(list)
+    -- Output the list
+    local listStr = ""
+    for i = 1, #list do
+        listStr = listStr .. "\n" .. list[i][1] .. ", " .. list[i][2]
+    end
+    print(listStr)
+end
+
+ -- Original list
+local list = { { 3, 5 }, { 7, 6 }, { 2, 2 }, { 5, 1 }, { 4, 3 } }
+
+PrintList(list) -- Output the original list
+
+-- Sort in descending order based on the first dimension of each item in the list
+table.sort(list, function(a, b)
+    return a[1] > b[1]
+end)
+PrintList(list) -- Output the sorted list
+
+-- Sort in descending order based on the second dimension of each item in the list
+table.sort(list, function(a, b)
+    return a[2] > b[2] 
+end)
+PrintList(list) -- Output the sorted list
+
+-- Output:
+-- Original list:
+-- 3, 5
+-- 7, 6
+-- 2, 2
+-- 5, 1
+-- 4, 3
+
+-- Sorted based on the first dimension:
+-- 7, 6
+-- 5, 1
+-- 4, 3
+-- 3, 5
+-- 2, 2
+
+-- Sorted based on the second dimension:
+-- 7, 6
+-- 3, 5
+-- 4, 3
+-- 2, 2
+-- 5, 1
+

Reference of table

When there is no deep copy of a table, and it is directly copied, the newly obtained list2 is equivalent to a reference to the original list1, known as shallow copy. When you modify the elements in list2 obtained from shallow copy, the elements in list1 will also change because the two tables are referenced.

The above example code also follows this principle. Below is a new example to highlight this characteristic.

Example: Shallow Copy

function PrintList(list)
+    -- Output the list
+    local listStr = ""
+    for i = 1, #list do
+        listStr = listStr .. list[i] .. " "
+    end
+    print(listStr)
+end
+
+list1 = { 1, 2, 3, 4, 5 }
+PrintList(list1)
+-- 1 2 3 4 5
+
+list2 = list1
+PrintList(list2)
+-- 1 2 3 4 5
+
+-- Modify the second element in list2
+list2[2] = 10
+PrintList(list2)
+-- 1 10 3 4 5
+
+PrintList(list1)
+-- 1 10 3 4 5
+

Example: Deep Copy

And what if you want to create a completely new list list2? Then you need to copy each element in the table one by one, also known as deep copy.

-- PrintList function code remains the same as above
+
+list1 = { 1, 2, 3, 4, 5 }
+PrintList(list1)
+-- 1 2 3 4 5
+
+list2 = {} -- Create a new empty list
+
+-- Copy elements from list1 to list2
+for index, value in pairs(list1) do
+    table.insert(list2, value)
+end
+PrintList(list2)
+-- 1 2 3 4 5
+
+-- Modify the 2nd element of list2
+list2[2] = 10
+PrintList(list2)
+-- 1 10 3 4 5
+
+PrintList(list1)
+-- 1 2 3 4 5 (no changes occurred)
+

In this example, modifying the elements in the deep copy list2 does not affect the original list1.

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/notes/mip-en.html b/en/notes/mip.html similarity index 80% rename from notes/mip-en.html rename to en/notes/mip.html index 5336cffc..c97cbac5 100644 --- a/notes/mip-en.html +++ b/en/notes/mip.html @@ -1,5 +1,5 @@ - + @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - Mixed integer programming | MicroCity笔记 + Mixed integer programming | MicroCity Notes - + -

Mixed integer programming

Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web.

Translate info

This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.

Creating a Mixed-Integer Programming Model

Creating an integer programming model object.

local mip = math.newmip() -- Assign the created model object to mip
+    

Mixed integer programming

Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web.

Translate info

This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.

Creating a Mixed-Integer Programming Model

Creating an integer programming model object.

local mip = math.newmip() -- Assign the created model object to mip
 

Setting the Objective Function

In MicroCity Web, the first line of the model is the objective function, added using the mip:addrow() function.

You can choose to maximize or minimize the objective function. The usage is as follows:

Maximize
mip:addrow(coeff, 'max') -- Maximize the objective function
 

Parameter Description and Examples

ParameterPurpose
mipMathematical model object. Sets the objective function for the model
coeffCoefficients of the objective function, a table variable. Determines the coefficients of the objective function in the model.
"min" or "max"Determines whether to minimize or maximize the objective function.

coeff is a list of coefficients for the objective function, a table variable. Suppose you want to minimize the function

4x1+12x2+18x3 4x_1+12x_2+18x_3

the approach to adding the objective function is as follows:

-- Assuming you have already created the model object and stored it in the variable mip
@@ -156,7 +156,7 @@
 

Online Execution

Check this exampleopen in new window in MicroCityWeb

ResultPersonItem
x13=1x_{13}=1AC
x21=1x_{21}=1BA
x34=1x_{34}=1CD
x42=1x_{42}=1DB

Handling Intermediate Variables

Sometimes, there are intermediate variables in a model that must have corresponding positions in the matrix to be solved, and these intermediate variables do not participate in the calculation of the objective function value. The coefficients of the intermediate variables at their corresponding positions can be set to 0.

Suppose x1,x2,x3,x4x_1, x_2, x_3, x_4 are decision variables, and y1,y2y_1, y_2 are intermediate variables. The objective function is:

z=i=14xi z=\sum_{i=1}^4x_i

The coefficients of the objective function can be set as follows:

local fcons = {1, 1, 1, 1, 0, 0}
 -- The first 4 elements correspond to decision variables,
 -- and the last 2 elements correspond to intermediate variables
-

Afterward, you can proceed with the general process 😎

Last Updated:
Contributors: huuhghhgyg
- +

Afterward, you can proceed with the general process 😎

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/en/notes/network.html b/en/notes/network.html new file mode 100644 index 00000000..be80225d --- /dev/null +++ b/en/notes/network.html @@ -0,0 +1,103 @@ + + + + + + + + + Operating Networks | MicroCity Notes + + + + + +

Operating Networks

Network Topology

Network topology, in simple terms, refers to a network with nodes and connections between them. If we think of connections as roads, then you need to solve the following problems:

  1. Is this road one-way or two-way?
  2. Where does the road start? Where does it end?

In general, each road in a network diagram is considered to be one-way. If a two-way road is needed, you simply need to add a road in the opposite direction. Like this: Two-way road This way, each road has a direction. It is common to use the symbol O for the starting point and the symbol D for the destination point. Using O and D, the direction of each road can be clearly described.

For the example in the above diagram, the road at the top has O=1, D=2, so the direction is described as from 1 to 2; the road at the bottom has O=2, D=1, so the direction is described as from 2 to 1.

Building Network Topology using Functions

MicroCity can handle networks, and the specific usage of all functions can be found in the reference document: 4.6 Networks

Here are some simple methods for creating network objects in MicroCity:

local network = CreateNetwork() 
+

Create an empty network object and return it. network is the returned empty network object.

After creating the object, you can use functions like AddLink and DelLink to create connections in the network object. See the reference document for specific usage.

local network, nodes, links = CreateNetwork(Lines)
+

Here, Lines is a vector graphic object of type Line. In this usage, the CreateNetwork() function in MicroCity can directly add starting points and endpoints to the road connections and automatically label the O and D points in the returned links object.

In other words, you only need to provide the network connections, and the remaining work of topology can be automatically completed by the function. I believe this may be the most commonly used method for creating network diagrams and conducting topology.

Simple Example of Network Topology

-- Open the connection layer
+Shapes = Open("Shapes.shp")
+
+-- Create network topology
+network, network_nodes, network_links = CreateNetwork(Shapes)
+
+-- Create a layer to store the topologized network nodes
+Nodes = CreateShapes("Nodes", "point")
+-- Copy the network nodes obtained from topoization to the layer
+AddField(Nodes, "ID", "int")
+for i = 1, GetRecCount(network_nodes) do
+	CopyShapeTo(Nodes, 0, 0, GetShape(network_nodes, i))
+end
+
+-- Create a layer to store the topologized network connections
+Links = CreateShapes("Links", "line")
+-- Copy the original attribute fields from the network connections to the layer
+for i = 1, GetFieldCount(Shapes) do
+	AddField(Links, GetField(Shapes, i))
+end
+-- Add attribute fields for the connections, and corresponding data will be added later using functions
+AddField(Links, "ID", "int")
+AddField(Links, "O", "int")
+AddField(Links, "D", "int")
+AddField(Links, "IMPEDANCE", "double")
+AddField(Links, "DIRECTION", "int")
+AddField(Links, "CAPACITY", "double")
+-- Copy the network lines obtained from topoization to the layer (including corresponding data)
+for i = 1, GetRecCount(network_links) do
+	CopyShapeTo(Links, 0, 0, GetShape(network_links, i))
+end
+
+-- Update the layers
+Update(Nodes)
+Update(Links)
+

The example is modified from the built-in editor of MicroCity.

Although the network connection was established at the beginning, it is possible that during the topology process, the nodes on the connection may overlap, causing the continuous connection to be divided into multiple segments. Therefore, the resulting Links layer may be different from the input layer. The topology nodes Nodes obtained from the topology process correspond to the resulting links Links, so it is recommended to use the topological processing result of the Links layer as the connection between network nodes.

Pitfall: Creating Network Objects

If you need to create a network again using the CreateNetwork(Nodes, Links) function, you need to retain the attributes added during the topological process, otherwise there will be errors in network initialization:

AddField(Links, "ID", "int")
+AddField(Links, "O", "int")
+AddField(Links, "D", "int")
+AddField(Links, "IMPEDANCE", "double") -- impedance
+AddField(Links, "DIRECTION", "int") -- direction
+AddField(Links, "CAPACITY", "double") -- capacity
+

If you are only doing a one-time topology of the network and will not use the topologically processed network to create a network object again, you still need to create the above attributes first. The topologically processed data is not filled in according to the attribute names, but according to their positions.

If only O and D attributes are created, the ID data will be filled in the O attribute, and the O data will be filled in the D attribute. If only the ID, O, and D attributes are created in the order mentioned above, the data will be filled correctly due to the data order being filled based on their positions.

CopyShapeTo Function

The CopyShapeTo() function is used in the topological process to copy a Shape object to the corresponding position in the Shapes layer and perform position transformation in the Shapes layer based on the input dx and dy. Here, dx and dy represent the displacements in the x and y directions (referred to as deltax and deltay).

CopyShapeTo(TargetShapes, dx, dy, Shape1 [, Shape2, ...])
+

Based on the usage of the function, it also supports copying to multiple layers and then performing the transformation. If you only want to copy the shape to the corresponding position of the corresponding layer without transformation, you can set dx and dy to 0, like this:

CopyShapeTo(TargetShapes, 0, 0, Shape1 [, Shape2, ...])
+

For the specific usage of the CopyShapeTo() function, please refer to 4.3 Vector Graphics and Tables

Using the Network Topology Algorithm

After performing the network topology, you can use the built-in functions to solve many problems, such as generating a minimum spanning tree, finding the shortest path, or calculating the shortest distance. This article will take the calculation of the shortest path and its length as an example to explain the process and pitfalls of calculating the shortest path.

Calculating the Shortest Path and Its Length

To calculate the shortest path, it is necessary to determine which two points in the network the shortest path is between. Here, startID and endID represent the starting point and the endpoint, respectively. Let's assume that you have already created a network object and stored it in a variable named Network. If you don't know how to create a network graph, you can refer to the Network Topology process described above.

Creating a Minimum Spanning Tree

Step 1: First, create a minimum spanning tree with startID as the starting point. Theoretically, after creating a minimum spanning tree with the starting point, you can obtain the shortest distance from the starting point to any point on the network. You can use the GenSTPTree() function to create a minimum spanning tree.

GenSTPTree(Network, startID [, endID])
+

The endID here is not necessary, but if it is available, you can provide it to the function. In other words, you have two ways to accomplish this:

GenSTPTree(Network, startID) -- Method 1
+GenSTPTree(Network, startID, endID) -- Method 2 (recommended)
+

It is generally believed that the more complete the information provided, the better the execution effect. Since you already know endID before calculating the shortest path, it is recommended to provide it to the function.

The usage of this function with brackets has been explained here, and this notation will be used directly in the following text.

Step 2, obtain the information corresponding to the shortest path. As mentioned earlier, the shortest route between two points can only be determined after the starting point and the destination point are determined. Since the minimum spanning tree was created using the starting point startID earlier, now we only need to provide the destination point endID in order to obtain the shortest path and its length. The following explains the methods to obtain the shortest path length and the shortest path using the Network object.

Obtaining the Shortest Path Length

MicroCity's documentation provides three ways to obtain the shortest path.

The first method is used when the shortest path spanning tree has already been calculated and the information for the starting point has been inputted. Therefore, now only the information for the destination point needs to be provided (even if it has been provided already). The function requires a network object Network and the endpoint endID is used as follows:

local len = GetSTPLen(Network, endID)
+

The second method calculates the shortest path length between two points on the network by providing the starting point startID and the destination point endID. This usage does not require generating the shortest path spanning tree before calculating the shortest path and can be used directly. The Network parameter represents the network object and is used as follows:

local len = GetSTPLen(Network, startID, endID)
+

The third method calculates the shortest path length between two points on the network by providing the xy coordinates of the starting and destination points. This usage also does not require generating the shortest path spanning tree before calculating the shortest path and can be used directly. The coordinates of the starting point are set as x1 and y1, the coordinates of the destination point are set as x2 and y2, and the Network parameter represents the network object and is used as follows:

local len = GetSTPLen(Network, x1, y1, x2, y2)
+

Obtaining the Shortest Path

MicroCity's documentation provides three pieces of information that can be obtained, namely:

  1. The sequence of point or line IDs
  2. The sequence of point or line indices
  3. The sequence of point or line shapes.

For detailed usage of the functions, please refer to 4.6 Networks - Algorithms. Here, only the second method, which returns the sequence of point or line indices, will be used as an example.

To return the sequence of points:

GetSTPPath (Network, endID, "iNodeShp")
+

To return the sequence of lines:

GetSTPPath (Network, endID, "iLinkShp")
+

This way, the sequence of point or line indices can be obtained.


Pitfall: Sequences

In Getting Started with Lua, we introduced sets in Lua, which provide rich features to assist in code writing. However, we have not heard of sequences. A sequence is something like this:

local x, y = GetCenterXY(Shapes) -- using this function temporarily
+

Here, x and y form a sequence. Here's another scenario:

GetDistance (x1, y1, x2, y2 [, x3, y3, ...]) -- using another function here temporarily
+

In this case, the more points that are inputted, the more return values there will be. If four points are inputted, it can be handled like this:

-- Normal case
+d1, d2, d3, d4 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4)
+
+-- Only the first two return values can be kept
+d1, d2 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4)
+
+-- Of course, only one return value can be kept as well
+d1 = GetDistance(x1, y1, x2, y2, x3, y3, x4, y4)
+

The number of input parameters and output parameters in the above function are related. If n points are inputted as parameters, n distances will be returned. However, for the network topology, when returning the shortest path, the returned values are always parameter sequences, and I don't know how many parameters the function will give me; and when there are too many output parameters, it is also not feasible to manually create many variables to store these parameters.

-- Wrong approach:
+local indexList = GetSTPPath(Network, endID, "iLinkShp")
+-- The GetSTPPath() function does not return a table
+-- The indexList obtained here is only the index of the first Link, which is a numerical value.
+

Since the left side of the equal sign cannot be changed, let's make changes on the right side. Do you remember how to define a simplest table?

local list = {1, 2, 3, 4, 5}
+

The [to_be_replace[x]] on the right side can actually be seen as a sequence. So, as long as you add parentheses to the return value of a function, you can pick them all up ( •̀ ω •́ )✧

local indexList = { GetSTPPath(Network, endID, "iLinkShp") }
+

The indexList obtained using the above method is a variable of table type. Then, you can start performing various operations on the collection 😋

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/oop.html b/en/notes/oop.html new file mode 100644 index 00000000..b72b8c77 --- /dev/null +++ b/en/notes/oop.html @@ -0,0 +1,101 @@ + + + + + + + + + Object-Oriented Programming | MicroCity Notes + + + + + +

Object-Oriented Programming

Object-Oriented Programming (OOP) is a programming paradigm that abstracts real-world entities into objects in the program world. Objects communicate with each other through message passing, forming the functionality of a program.

Yard Objects

According to online sources, OOP has three main characteristics: encapsulation, inheritance, and polymorphism. However, in this simulation, encapsulation is the most frequently used, while the opportunities for inheritance and polymorphism are rare. Additionally, I haven't implemented object message passing in MicroCity yet. If I do, I will update this article accordingly. Therefore, the following mainly introduces how to use encapsulation in Lua code for MicroCity.

Tips

The code examples in this article are applicable to MicroCityWeb and may not necessarily work for the desktop version of MicroCity. Furthermore, this article is based on personal insights and does not guarantee absolute correctness in terms of concepts.

Basic Concepts of Object-Oriented Programming

Classes and Objects

In simple terms, a class is a template for objects, and an object is an instance of a class.

A class is a fundamental concept in object-oriented programming that represents a category of things. The concept of a class can be understood as a category of objects—such as AGVs, shelves, and gantry cranes. You can think of a class as a template for a category of things, and objects are specific instances created based on this template.

A good example is the mentioned shelf. A shelf is a class, and a specific shelf is an object. The shelf class contains various attributes, such as the shelf's location and the items it holds. Different shelf objects created from the shelf class belong to the shelf class, such as Shelf 1, Shelf 2, etc. Although their attributes may differ, they are all objects of the shelf class.

Class Attributes and Methods

In MicroCity simulation, based on my personal experience, classes usually have attributes but not necessarily methods. Continuing with the example of a shelf mentioned earlier, attributes are the characteristics of a class, such as the location of the shelf and the items on the shelf. Methods represent the behaviors of a class and are usually implemented with functions, such as an AGV lifting or placing a shelf, an AGV moving, or driving a shelf.

Advantages and Disadvantages of Using Object-Oriented Programming in Simulation

Advantages

In MicroCity, when dealing with scenarios involving the movement of multiple objects of the same type and playing animations of object movements (such as AGVs, shelves, and gantry cranes), a considerable amount of coordinate calculations and position settings are required. If each object needs to be implemented individually, the code for modifying the coordinate of each object will become very long, making it difficult to maintain. By using the object-oriented programming paradigm, data processing code can be encapsulated into individual objects, making the code more readable and maintainable.

Furthermore, if multiple objects of the same type need to be created in a scene, each object may have different parameters. By encapsulating using object-oriented methods, each object's parameters can be encapsulated within the objects themselves. When the simulation process or scale becomes more complex, the reusability of the code can be increased.

For simulations, the most important aspect is understanding the business process and business logic. Using object-oriented programming can make the simulation's business process and logic more clear, improve code readability, and increase maintainability. Furthermore, when it is necessary to modify the business logic of a class of objects, you only need to enter the class and make the modification. For example, modifying the scheduling algorithm for all gantry cranes in a port only needs to be done once because all gantry cranes share the same scheduling algorithm.

Based on personal experience, when using object-oriented methods to encapsulate objects, it is mostly intended to create a generic object and then create multiple objects of the same type in subsequent simulations automatically or manually, with different parameters for each object. This increases code reusability and improves code readability, providing convenience for future maintenance and modifications, and lays a foundation for large-scale simulations.

Disadvantages

If the simulation is small in scale and involves simple operations with a small codebase, it is not recommended to use object-oriented methods for code encapsulation. Using object-oriented methods will increase the number of lines of code, and may make the code appear more complex than the original problem. (Of course, there will be no consequences if you still choose to use it, except that it may look strange.) Specifically, you can refer to the provided code examples in the following sections and notice that most of the code is dedicated to describing classes and their business logic, while the code for the business process is simple and occupies a small proportion.

Implementation of Object-Oriented Programming in Lua

In Lua, the concept of object-oriented programming is typically implemented using tables. A table is a data structure in Lua that can represent arrays, dictionaries, objects, etc. In object-oriented programming, tables can be used to represent objects.

Example

Since the objects created in MicroCity are tables, we can encapsulate the object's attributes directly in a table and return that table when creating an object.

Here's an example:

-- The function will return an AGV object
+function AGV()
+    -- Create a 3D object of an AGV in MicroCity
+    local agv = scene.addobj('/res/agv.glb')
+
+    -- Set the properties of the object
+    agv.position = {0, 0, 0} -- Set the position of the object
+    agv.speed = 1 -- Set the speed of the object
+
+    function agv:move(dx, dy, dz)
+        agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- Modify the object's coordinates
+
+        agv:setpos(agv.position[1], agv.position[2], agv.position[3]) -- Set the object's position
+        scene.render() -- Render the scene (Not recommended to call here, just for demonstration purposes)
+    end
+
+    return agv -- Return the object
+end
+
+-- Object usage
+local obj = AGV() -- Create an object
+obj:move(1, 0, 0) -- Move the object 1 unit in the x direction
+

Or you can choose to encapsulate the object within a table and return that table after creating the object.

-- The function will return an AGV object
+function AGV()
+    -- Set the object's properties directly in the table to be returned
+    local agv = {
+        object = scene.addobj('/res/agv.glb'),
+        position = {0, 0, 0},
+        speed = 1
+    }
+
+    function agv:move(dx, dy, dz)
+        agv.position = {agv.position[1] + dx, agv.position[2] + dy, agv.position[3] + dz} -- Modify the object's coordinates
+
+        agv.object:setpos(agv.position[1], agv.position[2], agv.position[3]) -- Set the object's position
+        scene.render() -- Render the scene (Not recommended to call here, just for demonstration purposes)
+    end
+
+    return agv -- Return the object
+end
+
+-- Object usage
+local agv = AGV() -- Create an object
+agv:move(1, 0, 0) -- Move the object 1 unit in the x direction
+

There is also another method to create objects using setmetatable, this belongs to advanced usage, but I feel like it is not used very often. However, it seems like this method can be used to achieve class inheritance, if you are interested, you can search for it yourself. Here is the code implementation of the shelf class that I wrote for an earlier assignment as a reference. (Now I feel like this class is not written very well 😂, for example, x and y can be replaced with pos = {x, y}, and x_origin and y_origin can be replaced with origin = {x, y}).

-- Shelf
+Shelf = {
+    x = 1,
+    y = 1,
+    cargo = {"box"}, -- Items on the shelf
+    x_origin = 1, -- Shelf's original x coordinate
+    y_origin = 1 -- Shelf's original y coordinate
+}
+
+function Shelf:New(x, y)
+    local self = {}
+    setmetatable(self, {
+        __index = Shelf
+    })
+    self.__index = self
+
+    self.x = x
+    self.y = y
+    -- Set the original coordinates
+    self.x_origin = x
+    self.y_origin = y
+    return self
+end
+

Types of Classes

Here, I would like to summarize the main types of classes that I have created.

  1. 3D entity classes: These classes mainly control the movement of 3D entities, such as AGVs and cranes. Most of them have physical entities that need to be moved. Some even include sub-objects, such as crane objects that have hoists, ropes, and cranes as sub-objects.
  2. Data model classes: These classes represent various entities in a system, such as yards, shelves, and goods. For example, a yard class contains data about the yard's dimensions, the goods in the yard, and the containers in the yard.

It should be noted that I do not strictly categorize these types, as certain classes may possess the characteristics of multiple types. For instance, an AGV class also includes data about the AGV's position and speed, while a shelf class merely stores the shelf model. The movement of the shelf model is controlled by the AGV, and the more important function of the shelf class is to record the information of the goods on the shelf. Therefore, I consider these types as rough distinctions, and the specific implementation should be based on the actual business processes and requirements.

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/plots.html b/en/notes/plots.html new file mode 100644 index 00000000..1d45e44c --- /dev/null +++ b/en/notes/plots.html @@ -0,0 +1,291 @@ + + + + + + + + + Generic Drawing Code | MicroCity Notes + + + + + +

Generic Drawing Code

This section provides some pre-written drawing objects, which are convenient for direct use when visualizing data.

Info

All open source code on this page is licensed under the MIT license and can be used freely. However, please retain the copyright information when publicly distributing.

Histogram

A histogram is generally used to display the frequency or frequency distribution of various data values in a data set. It divides the data into several intervals (or "bins") according to a certain interval and then plots the frequency (or frequency) of each interval as a bar chart on the y-axis to reflect the distribution of the data.

Here is an example of a histogram drawn using the histogram object I wrapped.

Histogram Example

Importing the Histogram

First, import the histogram code. There are currently two options:

  1. Download the code file and import it (recommended): [Download the histogram code file](#Code file download) Histogram.lua and import it into MicroCityWeb. Then, reference the file to use it. The code reference is as follows:
require("Histogram") --Reference the histogram
+
  1. Copy the code: Copy the code from the Histogram.lua file directly into your code. The code is shown [below](#Histogram Code).

Creating a Histogram Object

Create a histogram object.

local plot = Histogram(list) -- list is the data set
+

You can also set the properties of the graph when creating the object.

local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end})
+

Setting the properties is not necessary and can be done as needed. In this case, only the range, scale, and fdisp properties are set.

Setting Histogram Properties

The above example provides a simple demonstration of setting histogram properties. According to the code, more properties can be set. See the table below for details:

PropertyFunctionExample
originSet the origin of the graph (bottom-left point)origin = {-50, -50}, set the origin of the graph at position (-50,-50)
sizeSet the length of the x and y axes of the graphsize = {100, 100}, set the length of the x and y axes of the graph to 100 each
scaleSet the graduations of the x and y axesscale = {3, 2}, set the graduations of the x and y axes of the graph to 3 and 2 respectively
axislabelSet the titles of the x and y axesaxislabel = {"x", "y"}, set the titles of the x and y axes of the graph to "x" and "y" respectively
rangeSet the display range of the x and y axesrange = {0, 10, 0, 20}, set the x-axis range of the graph to [0,10] and the y-axis range to [0,20]
filledSet whether to fill the bar chartfilled = false, set the bar chart to unfilled. The default style is filled
fdispThe display function for data labels, which defaults to the quantity. When setting the display function for data labels, it will also affect the display of y-axis tick marks.fdisp = function(v) return (v/n*100).."%" end, change the data labels to display in proportion (assuming n is the sample size)

Advanced Usage of Histograms

Dynamically refresh the data plot.

  1. Modify the data in the graph. Here, we use adding data to the graph as an example. Let's assume rnd is the data to be added. You can also directly modify the value of plot.data.
table.insert(plot.data, rnd)
+
  1. Refresh the graph.
plot:refresh()
+

Example

Basic Usage Example: Drawing a Poisson Distribution

require("Histogram") --Reference the histogram
+
+local seed = math.randomseed(1, {
+    distribution = "poisson",
+    mu = "3"
+})
+local list = {seed:random()}
+
+
+--Static drawing
+for i = #list, 400 do
+    table.insert(list, seed:random())
+end
+
+local histplot = Histogram(list, {
+    range = {0, 10, 0, 50},
+    scale = {1, 5}
+})
+scene.render()
+

Advanced Usage Example: Dynamically Refreshing Plot of the Poisson Distribution

This is an example of plotting the Poisson distribution and dynamically refreshing the data plot. It is assumed that the Histogram object has been imported and the scene is set for 2D display.

require("Histogram") -- Import the histogram
+
+local seed = math.randomseed(1, {
+    distribution = "poisson",
+    mu = "3"
+})
+local list = {seed:random()}
+
+local histplot = Histogram(list, {
+    range = {0, 10, 0, 50},
+    scale = {1, 8}
+})
+scene.render()
+
+-- Dynamic drawing
+local count = 1
+while count < 1000 do
+    local rnd = seed:random()
+    table.insert(histplot.data, rnd)
+
+    histplot:refresh()
+    count = count + 1
+    scene.render()
+end
+

Subplots

Subplots are a way to position and size multiple plots within a single interface. The name is borrowed from MATLAB.

Subplots

Importing Subplots

First, import the code for subplots. Like histograms, there are two options for importing:

  1. Download the code file and import (recommended): Download the subplot code file, import the Subplot.lua file in MicroCityWeb, and then use the code. Use the following code to import:
    require("Subplot") -- Import the subplot code
    +
  2. Copy the code: Copy the code from the Subplot.lua file directly into your code. In this case, there is no need to import the code. See the code below.

Creating Subplot Objects

When creating a subplot, you must specify the number of rows and columns. The number of rows and columns determines the number of subplots.

local subplot = Subplot(rows, cols)
+

You can also set additional properties to define the position and size of the subplots. Here is an example of setting the position and size of the subplots when creating them:

local subplot = Subplot(rows, cols, {span=10, diag={-80, -70, 80, 70}})
+

Setting Subplot Properties

Here, we will provide a detailed description of the properties of subplots. Setting these properties is optional and can be done as needed.

PropertyDescriptionExample
spanSets the spacing between subplotsspan=10, sets the spacing between subplots to 10 in all directions
diagSets the position and size of a subplot by specifying the coordinates of the two diagonal pointsdiag = {-80, -70, 80, 70}, sets the diagonal range of the subplot from coordinates (-80,-70) to (80,70)

Reading Subplot Values

After creating a subplot with properties, or modifying the properties and refreshing, you can read the values of the subplots, including the origin position and size of each subplot, using the following attributes.

Note

Here, it is assumed that the subplot object is stored in the subplot variable after creation.

AttributeMeaningExample
originptThe origin position of each subplot in the Subplot objectThe origin position of the subplot in the i-th row and j-th column can be obtained by subplot.originpt[i][j][1] and subplot.originpt[i][j][2]
psizeThe size of each subplot in the Subplot objectThe width and height of the subplot in the subplot can be obtained by subplot.psize[1] and subplot.psize[2].(assuming all subplots have the same size)

Example

This is an example of drawing the range of subplots. Assume that the Subplot object has been imported and the scene has been set to 2D display.

Here, the display range of each subplot in a 2x3 subplot is drawn as a rectangle. The range of each subplot is represented by four gray points, and the position of each subplot is represented by a blue rectangle.

require("Subplot") -- import the Subplot library
+
+local subplot = Subplot(2, 3, {span = 10})
+
+-- Draw the boundary points of the Subplot object
+local lb = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[2],0}})
+local lt = scene.addobj("points",{size = 10, vertices={subplot.diag[1],subplot.diag[4],0}})
+local rb = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[4],0}})
+local rt = scene.addobj("points",{size = 10, vertices={subplot.diag[3],subplot.diag[2],0}})
+
+-- Draw the range of each subplot
+for i = 1, subplot.row do
+    for j = 1, subplot.col do
+        scene.addobj("polyline", {size = 8, color = "blue",
+            vertices={
+                subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0,
+                subplot.originpt[i][j][1], subplot.originpt[i][j][2], 0,
+                subplot.originpt[i][j][1], subplot.originpt[i][j][2]+subplot.psize[2], 0,
+                subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2]+subplot.psize[2], 0,
+                subplot.originpt[i][j][1]+subplot.psize[1], subplot.originpt[i][j][2], 0,
+            }
+        })
+    end
+end
+scene.render()
+

Code

You can remove the scene.setenv code at the beginning depending on the combination of your code. The scene.render() in the code is used to refresh the image during dynamic drawing.

Code File Download

A list of code files can be found in ModelResource/libsopen in new window

NameLink
HistogramModelResource/libs/Histogram.luaopen in new window
SubplotModelResource/libs/Subplot.luaopen in new window

Histogram Code

Histogram

-- Initial scene settings
+local s = scene.setenv({camtype = "ortho"})
+
+-- Returns a histogram object
+function Histogram(data, ...)
+    local plot = {
+        -- Default value settings
+        origin = {-50, -50}, -- Coordinate origin coordinates
+        size = {100, 100}, -- Coordinate axis length
+        scale = {3, 2}, -- Coordinate axis scale values
+        range = {0, 10, 0, 20}, -- xy-axis range
+        axislabel = {"x", "y"},
+        filled = true, -- Whether to fill
+        fdisp = function(v) -- Data label display
+            return v
+        end,
+    }
+    -- Import parameters and fallback
+    if ... ~= nil then
+        for k, v in pairs(...) do
+            plot[k] = v
+        end
+    end
+    
+    local barShape = "polygon"
+    if plot.filled == false then barShape = "polyline" end
+
+    -- Initialization
+    plot.axes = {} -- Coordinate axes
+    plot.originlabel = {} -- The zero point may have dual coordinates
+    plot.bars = {} -- Data bars
+    plot.xvalue = {} -- x-axis tick values (excluding the minimum value)
+    plot.data = data
+
+    function plot:deldata() -- Delete data (private)
+        if #plot.bars == 0 then
+            return
+        end
+
+        for i = #plot.bars, 1, -1 do
+            -- print("plot.bar:",i)
+            plot.bars[i][2]:delete()
+            plot.bars[i][1]:delete()
+        end
+
+        plot.zero:delete()
+        for i = #plot.originlabel, 1, -1 do
+            plot.originlabel[i]:delete()
+        end
+
+        for i = #plot.axes, 1, -1 do
+            for j = #plot.axes[i], 1, -1 do
+                plot.axes[i][j][2]:delete()
+                plot.axes[i][j][1]:delete()
+            end
+        end
+    end
+
+    function plot:refresh() -- Called when drawing repeatedly (public)
+        plot:deldata()
+

-- Calculate coordinate scale parameters local xmax = math.max(math.max(table.unpack(plot.data)), plot.range[2]) local xmin = math.min(math.min(table.unpack(plot.data)), plot.range[1]) local valueRange = xmax - xmin plot.range[1], plot.range[2] = xmin, xmax

-- Statistical drawing values local barData = {} for i = 1, #data do -- Deep copy table.insert(barData, data[i]) end plot.barValue = {}

-- Draw zero point plot.zero = scene.addobj("points", { vertices = {plot.origin[1], plot.origin[2], 0}, size = 10 }) if plot.range[1] == plot.range[3] then -- Both are 0 plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1] - 4, plot.origin[2] - 4, 0) else plot.originlabel[1] = scene.addobj("label", { text = plot.range[1], size = 4 }) plot.originlabel[1]:setpos(plot.origin[1], plot.origin[2] - 4, 0) plot.originlabel[2] = scene.addobj("label", { text = plot.range[3], size = 4 }) plot.originlabel[2]:setpos(plot.origin[1] - 4, plot.origin[2], 0) end

-- X-axis Scale local xaxis = {} -- x-axis object, with elements as {point, label} for j = 1, (plot.range[2] - plot.range[1]) / plot.scale[1] do -- index of the scale local xpt = plot.origin[1] + j * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1] -- X-axis scale position local pt = scene.addobj("points", { vertices = {xpt, plot.origin[2], 0}, size = 5 }) -- scale point local label = scene.addobj("label", { text = string.format("%.1f", plot.range[1] + j * plot.scale[1]), size = 4 }) -- scale label table.insert(plot.xvalue, plot.range[1] + j * plot.scale[1]) -- current x-axis value label:setpos(xpt, plot.origin[2] - 4, 0) xaxis[j] = {pt, label} -- add object to x-axis collection end plot.axes[1] = xaxis

    for i = 1, #plot.axes[1] do -- based on x-axis score
+        local ub = plot.xvalue[i] -- current loop maximum value
+        -- print("Loop", i, "ub=", ub) -- for debugging
+
+        local value = 0
+        for j = #barData, 1, -1 do
+            if barData[j] <= ub then
+                value = value + 1
+                table.remove(barData, j)
+            end
+        end
+        plot.barValue[i] = value -- record value
+    end
+    local ymax = math.max(table.unpack(plot.barValue))
+    plot.range[4] = math.max(ymax, plot.range[4])
+
-- Y-axis scale
+local yaxis = {} -- y-axis objects, each element is {point, label}
+for i = 1, (plot.range[4] - plot.range[3]) / plot.scale[2] do -- index of each scale
+    local ypt = plot.origin[2] + i * plot.size[2] / (plot.range[4] - plot.range[3]) * plot.scale[2] -- Y-scale position
+    local pt = scene.addobj("points", {
+        vertices = {plot.origin[1], ypt, 0},
+        size = 5
+    }) -- scale point
+    local label = scene.addobj("label", {
+        text = plot.fdisp(plot.range[3] + i * plot.scale[2]),
+        size = 4
+    }) -- scale label
+    label:setpos(plot.origin[1] - 4, ypt, 0)
+    yaxis[i] = {pt, label}
+end
+plot.axes[2] = yaxis
+
+-- Draw data
+local xunit = plot.size[1] / (plot.range[2] - plot.range[1]) * #plot.axes[1] -- x-axis division value
+local yunit = plot.size[2] / (plot.range[4] - plot.range[3]) -- y-axis division value
+
+-- Draw histogram based on the values
+for i = 1, #plot.axes[1] do
+    -- Drawing
+    local xl = plot.origin[1] + (i - 1) * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1]
+    local xr = plot.origin[1] + i * plot.size[1] / (plot.range[2] - plot.range[1]) * plot.scale[1]
+    local yb, yt = plot.origin[2], plot.origin[2] + plot.barValue[i] * yunit
+    local bar = scene.addobj(barShape, {
+        vertices = {xl, yb, 0, xr, yb, 0, xr, yt, 0, xl, yt, 0, xl, yb, 0}
+    })
+    local label = scene.addobj("label", {
+        text = plot.fdisp(plot.barValue[i]),
+        size = 4
+    })
+    label:setpos((xl + xr) / 2, yt + 2, 0)
+    plot.bars[i] = {bar, label}
+end
+
function plot:draw() -- Draw initialization
+    -- Coordinate axis object
+    plot.coord = scene.addobj("polyline", {
+        vertices = {plot.origin[1] + plot.size[1], plot.origin[2], 0, plot.origin[1], plot.origin[2], 0,
+                    plot.origin[1], plot.origin[2] + plot.size[2], 0}
+    })
+    -- Coordinate axis title
+    if plot.axislabel~=nil then
+        plot.axislabel[1] = scene.addobj("label", {
+            text = plot.axislabel[1],
+            size = 4
+        })
+        plot.axislabel[1]:setpos(plot.origin[1] + plot.size[1], plot.origin[2] - 8, 0)
+        plot.axislabel[2] = scene.addobj("label", {
+            text = plot.axislabel[2],
+            size = 4,
+        })
+        plot.axislabel[2]:setpos(plot.origin[1]-4, plot.origin[2] + plot.size[2]+6, 0)
+        plot.axislabel[2]:setrot(0,0,1)
+    end
+end
+
+plot:draw()
+plot:refresh()
+scene.render()
+return plot
+end
+

Subplot code

Subplot

-- Attribute parameters
+-- local diag = {-80, -70, 80, 70} -- lbx,lby,rtx,rty
+-- local span = 10
+-- local row, col = 2, 2
+function Subplot(row, col, ...)
+    local subplot = {
+        span = 10,
+        diag = {-80, -70, 80, 70},
+        originpt = {}, -- Store coordinates of each row and column
+        psize = {} -- Subplot size
+    }
+    subplot.row, subplot.col = row, col
+
+```lua
+-- Import parameters and fallback
+if ... ~= nil then
+    for k, v in pairs(...) do
+        subplot[k] = v
+    end
+end
+
+function subplot:refresh()
+    -- Calculate parameters
+    subplot.psize = {
+        (subplot.diag[3]-subplot.diag[1] - (subplot.col-1)*subplot.span)/subplot.col,
+        (subplot.diag[4]-subplot.diag[2] - (subplot.row-1)*subplot.span)/subplot.row
+    }
+    local gwidth, gheight = subplot.psize[1]+subplot.span, subplot.psize[2]+subplot.span
+
+    -- Recalculate originpt
+    subplot.originpt = {}
+    for i = 1, subplot.row do
+        subplot.originpt[i]={}
+        for j = 1, subplot.col do
+            subplot.originpt[i][j] = {subplot.diag[1]+(j-1)*gwidth, subplot.diag[2]+(i-1)*gheight}
+        end
+    end
+end
+
+subplot:refresh()
+return subplot
+end
+

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/timelapse.html b/en/notes/timelapse.html new file mode 100644 index 00000000..4046dd51 --- /dev/null +++ b/en/notes/timelapse.html @@ -0,0 +1,70 @@ + + + + + + + + + Time Advancement Methods | MicroCity Notes + + + + + +

Time Advancement Methods

The time advancement method in simulation refers to how the simulation time is progressed during the simulation process.

Classification of Time Advancement Methods

There are three major categories of common simulation time advancement methods:

  • Event scheduling method: Event scheduling method is an event-based simulation method that sorts events in the simulation system and simulates them based on the order of their occurrence.
  • Fixed increment advancement method: The fixed increment advancement method refers to fixing a time increment during the simulation process. After setting the starting time, the simulation time is advanced based on the time increment.
  • Master clock advancement method: The master clock advancement method refers to controlling the entire simulation system during the simulation process using a master clock. It controls the simulation process by controlling the clock.

Example

Event Scheduling Method

The event scheduling method is an event-based simulation method that sorts events in the simulation system and simulates them based on the order of their occurrence. During the simulation process, the simulation system determines the next event to occur based on the current simulation time and the time of each event, and advances the simulation time to the time when the event occurs.

The event scheduling method consists of the following three main steps, which are also the main steps of the control program for the event scheduling method:

  • Time scanning: Determine the time when the next event will occur and advance the simulation clock to that moment.
  • Event identification: Correctly identify the event that is about to occur.
  • Event execution: Correctly execute the event that has occurred.

The basic principle flowchart of the event scheduling method is as follows:

For the specific implementation of the event scheduling method in MicroCityWeb, please refer to Discrete Event Simulation and Program Control - Coroutine.

Fixed Increment Advancement Method

The fixed increment advancement method refers to fixing a time increment during the simulation process and advancing the time simulation based on the increment from the starting time. Within each time step, if no event occurs, the simulation clock is advanced by one unit of time T; if there are multiple events within the step, these events are considered to occur at the end of the step.

Fixed Increment Advancement Method

Example

Code Flow Example

while scene.render() do
+    t = t + dt
+    if t % cycle ~= work_time then
+        d = d + v * dt
+        print("Time after departure:", t, "hours")
+    else
+        print("Time after departure:", t, "hours, resting")
+    end
+
+    car:setpos(CastToLine(d)) -- Linear trajectory
+
+    os.sleep(200)
+end
+

This is the main flow of the code and cannot be used directly.

Master Clock Advancement Method

The master clock advancement method refers to controlling the entire simulation system during the simulation process using a master clock. It controls the simulation process by controlling the clock. The master clock advancement method can be divided into two types: synchronous master clock and asynchronous master clock. Synchronous master clock means that all modules use the same master clock for advancement, while asynchronous master clock means that different modules use different master clocks for advancement.

The last part of the Automated Warehouse Simulation Approach mentions the improvement space and ultimately implements the master clock advancement method with synchronous master clock.

The implementation is done but the code is not included.

Changes from the Automated Warehouse Simulation to the Master Clock Advancement Method

Specifically, the following changes were made based on the original approach:

  • Most of the os.sleep() related to the event scheduling method were deleted. Due to the simplicity of the simulation process, the event scheduling method related to loading and unloading operations is retained to optimize resource utilization.
  • Set a global simulation clock and change the idea of the Agv:Move() function from "executing tasks and refreshing the scene at a fixed step size" to "monitoring changes in the simulation clock duration, executing tasks based on the duration changes, and refreshing the scene".
  • Added simulation speed adjustment.

From the above changes, it can be seen that the core of the simulation has shifted from event tasks to the simulation clock. In this, the part of scene refreshing is implemented using os.clock().

Example of Master Clock Advancement Method

Below is a simple example of the dominant clock driving method and the os.clock() function, modified from the built-in block rotation example in MicroCityWeb.

local obj = scene.addobj('box')
+
+-- Initial position
+local x = 1
+local y = 1
+local z = 0
+
+local rx, ry = 0.1, 0.1 -- Rotation speed in the x and y directions
+local simspeed = 10 -- Simulation speed
+
+local t = 0 -- Global simulation clock
+local t0 = os.clock() -- Record the start time of the simulation
+while scene.render() do
+    local dt = os.clock() - t0 -- Calculate the time difference since the last recorded time
+    t = t + dt -- Move the simulation clock forward by the corresponding time difference
+    
+    -- Set the current rotation position of the block
+	x = x + rx * dt * simspeed 
+	y = y + ry * dt * simspeed 
+	obj:setrot(x, y, z)
+	
+    t0 = os.clock() -- Record the simulation time
+end
+

Explanation:

  • When the simulation speed simspeed is 1, it means that the simulation clock is moving at the same speed as the real-world clock. simspeed can be considered as an acceleration factor.
  • dt represents the time difference between two recorded times, and the time step in the simulation is calculated as dt * simspeed.

    Info

    It should be noted that the value of the time increment dt is generally not the same in each loop cycle, and the specific value of dt generally depends on the computational power of the computer.

    Tips

    Sometimes there is not much time-consuming operation between two recorded times, and the calculated dt may be 0. Generally, there is a scene.render() between two time recordings, which usually ensures a non-zero time difference between the two samples.

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/tools.html b/en/notes/tools.html new file mode 100644 index 00000000..b83d929a --- /dev/null +++ b/en/notes/tools.html @@ -0,0 +1,34 @@ + + + + + + + + + Tools | MicroCity Notes + + + + + +

Tools

Possible tools that may come in handy:

🔨 Work In Progress...

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/versions.html b/en/notes/versions.html new file mode 100644 index 00000000..52c2b9b5 --- /dev/null +++ b/en/notes/versions.html @@ -0,0 +1,34 @@ + + + + + + + + + Versions of MicroCity | MicroCity Notes + + + + + +

Versions of MicroCity

MicroCity

GitHub release (latest by date) GitHub release (by tag)open in new window

When MicroCity software was initially launched, there was only a desktop version available, which could only run on Windows operating systems. Over time, the developer (@mixwindopen in new window) realized that this limitation prevented many potential users from using the software because they might be using other operating systems such as MacOS, Linux, and others.

MicroCityWeb

GitHub last commit (branch)

🎯Visit MicroCity Webopen in new window 📍(Offline version) Downloadopen in new window

To address this issue, the developer decided to develop MicroCityWeb, which is a version that can be directly run in a web browser. MicroCityWeb does not require any installation, just access its website using a modern browser such as Google Chrome or Microsoft Edge. Although running in a browser may cause some performance loss compared to the desktop version, it allows users to use the software on almost any operating system, such as Windows, MacOS, Linux for computers, and Android for mobile devices and tablets.

Although MicroCityWeb has been developed by the creators of MicroCity, you can still continue to use the previously developed desktop version of MicroCity. However, the desktop version will no longer receive updates for new features. All new features and improvements will be focused on the MicroCityWeb version. This decision aims to ensure that MicroCity can focus on one version and provide the best possible experience in that version. It also makes it easier to manage and maintain MicroCity, avoiding version control issues.

It should be noted that although the desktop version will no longer receive updates for new features, it can still be used. If users are already accustomed to using the desktop version, they can continue to do so. However, if users want to experience the latest features and improvements, they will need to switch to the MicroCityWeb version.

The MicroCityWeb version also provides an offline version packaged for browsers (see link above 🔗link).

Note

However, due to updates to the Chromium browser engine, certain outdated system versions may not be supported (such as Windows versions 8.1 and below, 32-bit Windows operating systems, etc.).

Compatibility

Due to the use of experimental JavaScript functions, MicroCityWeb may have compatibility issues running on the following browser engines:

  • Most browsers on iOS and iPadOS (due to Apple's requirement to use Safari's browser engine)
  • Firefox browser

Compatibility issues and some technical details encountered during testing on 29th September 2023

  • iOS and iPadOS:
    • Unable to open local files (due to the use of showOpenFilePicker() method)
  • Firefox:
    • Unable to open local files (due to the use of showOpenFilePicker() method)

Regarding the impact of the showOpenFilePicker() method, please refer to MDN Web Docs | showOpenFilePicker()open in new window.

Summary

The launch of MicroCityWeb version makes the software more user-friendly and popular, benefiting a wider range of users. At the same time, the MicroCity desktop version is still available, allowing users who are accustomed to this version to continue using it and facilitating their transition to the MicroCityWeb version.

At the time of writing this note, the MicroCityWeb is being used for the first time in a teaching environment and is able to function properly and provide certain simulation capabilities. The author's learning experience with MicroCity is as follows:

  • MicroCity (desktop version): Logistics information management
  • MicroCityWeb: Logistics system simulation

The content of this note is for reference only. If there are any discrepancies in the content due to time factors, you are also welcome to make corrections to the content of this note on Github through a Pull Request 🥳. Please check the Pull Requestopen in new window for further details.

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/visualization.html b/en/notes/visualization.html new file mode 100644 index 00000000..b7b2b6a1 --- /dev/null +++ b/en/notes/visualization.html @@ -0,0 +1,37 @@ + + + + + + + + + Visualization of Results | MicroCity Notes + + + + + +

Visualization of Results

This article introduces various methods for visualizing computational results. This includes changing the color of the content, changing the size of shapes, and changing the attribute labels displayed for elements.

Changing Shape Color

In the graphic properties box located at the bottom left corner of the program interface, the type of color displayed can be changed by modifying the Type attribute under the Colors section. There are 3 options available:

  • Unique Symbol: Specifies a specific color for all graphics in the same layer, which will not be discussed further here.
  • Lookup Table: Displays the corresponding color based on a numerical query from a table.
  • Graduated Color: Sets a gradient color based on the numerical values in the table.

Lookup Table - Changing Color Based on Table Values

By changing the Type attribute to Lookup Table, the color of the graphics can be modified based on the values in the table, achieving the effect of selecting specific graphics.

LookupTableProperties.png

In this example, the Attribute of Lookup Table is changed to SELECT in order to control the color of lines based on the values in the SELECT column of the table (as shown in the above image of attribute settings). When the value is 0, the color is displayed as black, and when the value is 1, the color is displayed as red. The values in the SELECT column of the table and the specific settings in the Lookup Table are shown in the following images.

TableSelect.pngLookupTableColor.png

The final effect achieved is shown below. SelectLinksColor.png

Graduated Color - Displaying Gradient Color Based on Values

By changing the Type attribute to Graduated Color, different colors can be displayed based on the varying numerical values in the table, achieving the effect of displaying a gradient color.

GraduatedColorProperties.png

In this example, a gradient color is displayed based on the population size of each country. It can be observed that China has a large population, hence the color displayed is red, while India also has a significant population, resulting in an orange color. Other regions have smaller populations, but differences can still be discerned through the colors.

GraduatedColorResult.png

The Colors attribute under Graduated Color can also be adjusted with other color schemes. The settings interface is shown in the following image, but each individual setting will not be listed here.

GraduatedColorSettings.png

If interested, the manual can be referred to for example 2.1 Showing a World Map to manually experiment with changing this attribute.

Changing the Display Size of Shapes and Labels

Selection of Reference System

There are 2 reference systems for displaying the size of content: one based on the map and one based on the screen. In this case, both the size of shapes and the display of labels are set to the same reference system.

When content is displayed based on the map, the size of the content will be synchronized and scaled according to the size of the map, as shown in the following images:

RelateToMapBig.png (Enlarging the content based on the map)

RelateToMapSmall.png (Shrinking the content based on the map)

When content is displayed based on the screen, the size of the content remains relatively consistent regardless of the map scaling, as shown in the following image:

RelateToScreenBig.png (Enlarging the content based on the screen)

Translate into English:

RelateToScreenSmall.png (Shrunk with the screen as the reference system)

Therefore, when drawing, the reference system should be selected according to the purpose of the drawing.

  • If you need to draw shapes with a specific size or label with a specific size on a map, such as drawing a circle with a radius of 10 km, you should use the map as the reference system.
  • If you only need labels and graphics to be displayed clearly at any size, you can choose the screen as the reference system.

Application examples of reference system

Draw dots in the picture, set the radius of the circle to be the same as the size of the circle, and set the center of the circle to be the center of each green dot. The size of the gray circle represents the coverage range of each green dot.

RangeDotRelateToMap.png

In the picture, the gray circle is drawn for each green dot with a radius of 16, representing the coverage range of each green dot. These gray circles are stored in a layer called Range.shp, and the layer type is Points.

Setting the reference system

The size reference system for graphics and labels can be set in the bottom left corner of the program interface. SizeProperties.png

The two positions marked in the picture can adjust the size reference system for graphics and the size reference system for labels respectively.

  • Setting the size reference system for graphics: Adjust the size reference system for graphics under the Size column in the Size relates to... section. Adjust the Default Size to adjust the size of the graphics relative to the coordinate system.
  • Setting the size reference system for labels: Adjust the size reference system for labels under the Labels column in the Size relates to... section. Adjust the Default Size to adjust the size of the labels relative to the coordinate system.

Changing the displayed labels

Manually changing the displayed labels

The size reference system for graphics and labels can be set in the bottom left corner of the program interface. The labels displayed in the picture above are ID. If you need to change it to other columns in the table, you can change the Attribute property under the Labels column to achieve it.

The position to be changed is shown in the picture. If you need to display the value in the corresponding MSG column in the table, you only need to change the Attribute property value under the Labels column to MSG.

LabelAttribProperties.png

However, every time the graphics are changed and the Update() function is executed, the label will be hidden. If the script to be executed contains the Update() function for this layer, there is no need to manually reconfigure the displayed labels after each script execution. The displayed labels can be automatically selected through the script.

Automatically changing the displayed labels

The value of an attribute can be changed using the SetParameter() function. Taking the Attribute property under the Labels column in the picture above as an example, you can see that its ID is LABEL_ATTRIB and its type is Choice in the bottom bar.

It should be noted that when the type is Choice, the parameter values are numbered starting from 1 and the numbering corresponds to the contents of the drop-down menu in order.

After clicking on this property, you can see that MSG is in the second position.

SetParameterProperties.png

Since the numbering in Lua usually starts from 1, the number for ID here corresponds to 1, and the number for MSG corresponds to 2. The object to be operated on is MSG, so the function needs to fill in the parameter value of type Choice as 2.

Now that all the required parameters have been obtained, the SetParameter() function can be used to change the displayed labels.

-- transports is the graphic layer
+SetParameter(transports, "LABEL_ATTRIB", 2)
+

The SetParameter() function needs to be executed after the Update() function, otherwise the effect will be overwritten by the Update() function.

Now let's take a closer look at the specific usage of the SetParameter() function:

SetParameter(Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
+
ParameterMeaning
Parameter1The input object, which can be Shapes, Table, Grid, Scene, or Module
Parameter2The id corresponding to the attribute. In the previous context, it is LABEL_ATTRIB
Parameter3If you need to change the attribute value, it only accepts three types: Number, String, and Object

The introduction of the SetParameter() function can be found in the 4.2 User Interface Control document, please refer to it.

Using Raster Grids

Raster grids can also be used for visualization, and I believe the most common application of raster grids is to draw heat maps. The generation of a heat map is mainly achieved by modifying the value of each cell on the raster grid. If you are not familiar with the specific structure of raster grids, you can refer to the 3.3 Raster Grids document. For controlling raster grids using scripts, you can refer to the 4.4 Grids document.

One scenario of using raster grids to draw heat maps is plotting price maps. When plotting a price map, we can iterate through each grid point on the raster grid, calculate the sum of distances from that grid point to each warehouse, and set the value of that grid point to this sum. This way, we can obtain a heat map. This method helps us visualize the distribution of prices and discover the trends and patterns of prices.

PlotPrice1.pngPlotPrice2.pngDL_Heatmap.png

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/warehouse-simulation.html b/en/notes/warehouse-simulation.html new file mode 100644 index 00000000..9d77e89d --- /dev/null +++ b/en/notes/warehouse-simulation.html @@ -0,0 +1,65 @@ + + + + + + + + + Ideas for Warehouse Automation Simulation | MicroCity Notes + + + + + +

Ideas for Warehouse Automation Simulation

The ideas in this article are for reference only and it is recommended to make appropriate improvements.

Specific Problem: Warehouse Simulation based on Cellular Automata

Problem1

In this problem, the locations of inbound and outbound can be changed, and the forklift is an AGV.

In other words, this is actually a cellular automata simulation of a mobile rack warehouse. The AGV can pass through the bottom of the rack, move to the bottom of the rack, lift the rack, and transport it to the inbound/outbound point.

Basic Assumptions

  • All items on the racks are the same.
  • Only one item is placed on each rack.

Therefore, outbound and inbound can be considered as completely opposite processes, so here we only need to discuss the outbound case in detail. It is assumed that there is already an item on the rack by default.

Overall Implementation Idea

  • Assign (x,y)(x, y) coordinates to each cell in the entire 3×33\times3 warehouse to facilitate subsequent movement operations.
  • With AGV as the core, operate the racks. When the AGV is in the lifted state and moves the rack, you only need to synchronize the coordinate position of the rack with the position of the AGV to achieve the effect of AGV moving the rack.

Business Process

Randomly generate the order list according to the required quantity, and the AGV moves the racks to the outbound point in order based on the order list.

Business Logic

When performing outbound, the AGV first finds the nearest rack and moves to the position of that rack, lifts the rack. For the rack (AGV), set the destination for movement and calculate the difference in Manhattan distance.

  • Before each movement, determine the direction of rack movement (xx or yy direction) by checking for obstacles.
  • If both directions are blocked, prioritize the yy direction (as specified) and recursively move away the obstacles in this direction to make space for the rack to move. If there is no space in the yy direction, then move in the xx direction.

Process Optimization: About the Old Method and the New Method

Both of these methods are viable, but the new method optimizes for specific scenarios by reducing the number of steps through obstacle prediction. See the problem in the figure below:

Old Method: No Obstacle Prediction (Inbound and outbound points are at position x=3,y=3x=3,y=3)

Effect of the old method

👉 After the AGV completes the outbound operation for the first rack and moves towards the second rack, it finds that the first rack blocks the way, so it goes back to move the first rack away, and then proceeds to do the outbound operation for the second rack.

New Method: Obstacle Prediction (Inbound and outbound points are at position x=3,y=3x=3,y=3)

Effect of the new method

👉 After the AGV completes the outbound operation for the first rack, it checks if other racks need to be moved before it can reach the inbound/outbound point. If necessary, it moves the obstructed racks and then proceeds to do the outbound operation for the next rack.

Info

In line with the principle of minimizing the occupation of the inbound/outbound points, when there is an empty space, the AGV will move the rack at the inbound/outbound point. Therefore, some seemingly redundant operations are not without comprehensive considerations.

Optimal layout schemes for different numbers of racks (animated graphics) The case with 8 racks has already been shown above. Here, we only show the cases with 5 and 7 racks from the table. For other cases, please refer to the appendix.

Collection and Analysis of Simulation Data

Maximum Inbound/Outbound Efficiency

The simulation results are shown in the figure below, representing the layout of racks with the best efficiency for the same number of racks.

  • Optimal rack layout: For the same number of racks, the layout with the minimum number of operations (ticks) to retrieve all items.

Explanation of the Layout Diagram

  • White: No rack is placed.
  • Light gray: Rack, but the AGV is initially positioned below this rack.
  • Gray: Rack.

Explanation of the Table

  • Rack Quantity: Number of racks in the layout diagram.
  • Old Ticks: Number of operations to retrieve items using the old method (no obstacle prediction).
  • New Ticks: Number of operations to retrieve items using the new method (with obstacle prediction). The new method will be explained later.
  • Highlighted in yellow: Scheme with the minimum number of operations (minimum ticks) in the same layout.

Optimal Layout

Maximum Space Utilization

If all positions are filled with racks, it will not be possible to access all racks. Therefore, the method with the highest space utilization is to place 8 racks.

Color Indications

  • Green: Rack with items.
  • Purple: Rack without items.
  • Light purple: Rack lifted by the AGV.
  • Dark purple: AGV below this rack, but the rack is not lifted.
  • Dark gray: Inbound/outbound points.

Sometimes, when the refresh rate is too fast, it may not be possible to see the rack being lifted by the AGV.

The entry and exit points are located at position x=2, y=3.

8 cargo shelves animation

Innovations

  • Additional consideration for different types of goods.
  • Each simulation generates demand based on the random arrangement of goods on the shelves.
  • Object-oriented programming. Using an object-oriented approach helps in abstracting the problem and improving the flow of the process. Good naming conventions make the program's logic and flow clear, ensuring that you won't forget everything after a night's sleep 😂

Different types of goods are represented by different colors. The meaning of AGV state colors, empty shelf colors, and entry/exit point colors remains the same.

  • Purple: Shelf without goods
  • Light purple: Shelf lifted by AGV
  • Dark purple: AGV is positioned beneath the shelf but hasn't lifted it
  • Dark gray: Entry/exit point

Example with 5 shelves:

Different types of goods - 5 shelves

Example with 8 shelves:

Different types of goods - 8 shelves

Simulation Enhancement: 3D Automated Warehouse Simulation

Problem2

In this part, the question has slightly changed. The requirement is to add a third dimension to the cellular automaton warehouse simulation and create a simulation of an automated warehouse. The specific requirement is shown in the image above.

Overall Approach

Adding the Third Dimension

Based on the core of the Cellular Automaton-based Warehouse Simulation, the part of the simulation that uses cellular automata will be rewritten as an internal data table to serve as an internal data model, monitoring and controlling the state of the entire simulation process.

Since the Cellular Automaton-based Warehouse Simulation uses an object-oriented approach to encapsulate objects, and object methods are extensively used in building the business logic and flow, only the object methods need to be rewritten (e.g., Agv:Move(dx, dy)) to achieve the transition from cellular automaton simulation to 3D automated warehouse simulation.

If the overall program structure is well-designed, applying "object-oriented" techniques will significantly improve maintainability and reduce the difficulty of migration.

The AGV and shelf models can be directly reused. For the goods, you only need to set the relative height list from the shelves to achieve automatic placement of goods at the specified height.

Tips

If you need to reuse existing models, or if you want to upload models to the repository maintained by the author of this document, please refer to the documentation on 3D Objects - External Models.

Significant Fluctuation in the Demand for Inbound and Outbound Goods

  • According to the requirements, there are basically only two scenarios: 3 shelves and 6 shelves.
  • Since the number of shelves is limited and the Cellular Automaton-based Warehouse Simulation has obtained the best layout for warehouse performance, the corresponding optimal layouts for the respective number of shelves can be directly reused. In this problem, only the placement of goods in fixed shelf layouts needs to be considered.
  • For the case of 3 shelves, the optimal layout is a symmetrical configuration in terms of height, with a distance of 1 from the entry/exit point. Therefore, only one scenario needs to be simulated, and the data collected from it.
  • For the case of 6 shelves, three scenarios were selected for multiple simulations to obtain the average, maximum, and minimum Ticks consumed by each scenario for inbound and outbound operations.

    Ticks represents the number of times the AGV moves and serves as a unit of operation time. Further improvements are mentioned in the following section: Areas for Enhancement.

  • Based on the above analysis, since there are limited scenarios, the best layout for goods can be determined by simulating the placement of goods at various positions, randomizing the types of demanded goods while keeping the total demand constant, and analyzing the obtained data.

Enhancements

During testing, it was found that the original strategy of moving shelves was not reasonable. Therefore, the shelf movement strategy was improved.

Old Strategy: Find the shelf closest to the AGV that contains the requested goods and move it to the entry/exit point.

Old Strategy

As seen in the animation, the AGV has moved the shelf containing the required goods (represented by blue blocks) to the entry/exit point. However, because the AGV moves the shelf adjacent to the one with the requested goods, it doesn't perform the outbound operation on the goods already at the entry/exit point.

New Strategy: Find the shelf closest to the entry/exit point that contains the requested goods and move it to the entry/exit point. By changing the strategy, the aforementioned issue has been resolved.

New Strategy

Innovation

Due to the large number of tests, the main process is written into a function for adaptive improvement, achieving automatic simulation tests for all cases and outputting data. The following figure is an example of running the automatic simulation test.

Automatic Test

Code for the automatic simulation test process, for reference only:

-- Batch test
+local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- Test demands (upper limit) sequence
+
+local output_string_list = {} -- List of test result strings
+for k, v in ipairs(cargo_ubs) do
+    local test_result = {} -- Test result sequence for this demand upper limit
+    cargo_ub = v -- Set the quantity upper limit
+    for j = 1, test_count do
+        scene.setenv({
+            grid = 'plane',
+            clear = true
+        }) -- Clear the scene
+
+        print("Test (", j, "/", test_count, "): Demand quantity is", cargo_ub)
+        local tick = ModelRun() -- Run the simulation model and return the test result
+        table.insert(test_result, tick) -- Insert the test result into the test result sequence
+    end
+
+    local output_string = ""
+    print("Test result sequence for demand quantity", cargo_ub, ":")
+    for i = 1, #test_result do -- Output the test result sequence to the list string
+        output_string = output_string .. test_result[i] .. "\t"
+    end
+    print(output_string)
+    table.insert(output_string_list, output_string)
+end
+
+-- Output the list of test results
+for i, str in ipairs(output_string_list) do
+    print("Test result sequence for demand quantity", cargo_ubs[i], ":", str)
+end
+

A bug was discovered during the automatic simulation test process, as described in the following text.

Shelf Layout Scheme

Shelf Layout Scheme

Color Legend

  • Light Blue: Inbound and outbound points
  • White: Empty space
  • Dark Blue, Red, Yellow: Colors corresponding to 3 types of goods

Assumptions

  • Each shelf contains 2 items of the same type
  • Random demand for goods, no preference for type
  • Only one item is taken out at a time

Simulation Results and Analysis

Simulate and test each quantity scenario in the layout scheme for each item 30 times, and calculate the maximum, minimum, and average values of the results for each scenario. The final conclusion is that in the case of 6 shelves, Layout Scheme 2 performs the best.

Scheme 3: 3 shelves

Scheme 3

Scheme 6

Trend in Average Ticks for Scheme 6 Trend in Average Ticks for Scheme 6

Optimal layout scheme for Scheme 6: Scheme 2 Optimal layout scheme for Scheme 6

Trend graph of "Demand Quantity - Shortest Average Service Time" for each sub-scheme should also be plotted. Taking Scheme 6-1 as an example, the x-axis represents the quantity of goods demanded, and the y-axis represents the shortest average service time (Ticks).

Scheme 6-1

Improvement Space

Since the specific execution time of the event is not given in the title, and the time unit is not specified, we only measure the number of operations on the shelves as the time cost. In other words, the time is calculated afterwards, and I think most of the students might have the same idea at this point. Although there is no problem with the final result, the idea can be changed to adapt to later studies.

The current approach is task-driven. Although it can obtain the correct result, it does not make use of simulation time. This approach does not have any issues when controlling only one entity. However, when dealing with multiple entities simultaneously, the current approach cannot handle the situation where multiple entities complete tasks at the same time, and can only achieve the situation where multiple entities complete tasks one after another. The specific process of the current approach is as follows:

Since the time advance method is used, the simulation world has its own time. For us, we can control the simulation speed by multiplying a multiplier on the simulation time, which is the simulation speed. In addition, this approach is more flexible in supporting multiple objects. The specific process is as follows:

This way, the simulation is changed to be time-centric, and the progress of all entities in the scene can be refreshed directly when refreshing the task execution progress. Since the simulation is time-centric, it is necessary to set the rate/time of various operations to ensure the accuracy of time calculation. In MicroCityWeb, there are some techniques that can be used for time advance simulation.

Update simulation time with system time

The os.clock() function can get the current system time (in seconds, but in decimal). With this function, synchronization between simulation time and real time can be achieved. Usage examples can be found in Time Lapse (Chinese only).

Since time is the core of the entire simulation, it is necessary to specify the time required for operations that were not previously defined. In the improved part, the additional time required for the following operations is considered:

  • Time required for goods to enter and leave the storage
  • Time required for the AGV to lift and lower the shelves

This post is translated using ChatGPT, please feedbackopen in new window if any omissions.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/en/notes/web-ui.html b/en/notes/web-ui.html new file mode 100644 index 00000000..fe60aa60 --- /dev/null +++ b/en/notes/web-ui.html @@ -0,0 +1,34 @@ + + + + + + + + + Introduction to the User Interface | MicroCity Notes + + + + + +

Introduction to the User Interface

The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb.

Overall interface

Overview of Interface Zones

Overall, the interface of MicroCityWeb can be roughly divided into four areas:

Interface zones

Next, we will provide a detailed description of the usage and functions of these areas.

Blue: Command Area

The content of this area is shown in the following figure, with nine available buttons.

Command bar

Program Control

The first three buttons are mainly used to control program execution. Their specific functions are as follows:

  1. Run/Debug: Clicking the left mouse button will run the code in the code editor on the left-hand side of the webpage, while right-clicking will debug the code.

  2. Pause: If the program is running, clicking this button will pause its execution (if supported).

  3. Stop/Force Stop: If the program is running, clicking the left mouse button will stop its execution. If left-clicking does not stop the script, right-clicking can forcibly terminate its execution.

Program control

Code Editing

Buttons 4-7 are mainly related to code editing.

  1. Show/Hide Editor: If the left code editor is open, clicking this button will close it. If it's closed, clicking it will reopen it. If you right-click, the editor can be expanded to full screen.

  2. Open Built-In Code: You can directly load built-in code (import built-in models), such as cubes, trucks, earth, world maps, etc. The specific models will be introduced in detail when the red canvas area is introduced.

Built-in code

Built-in code list

  1. Open Local Code:

    Left-click: A dialog box will pop up when you left-click, and you can choose a code file (.lua) on your local machine. After confirming the selection to open the file, the text of the code file will be automatically imported into the code editor on the left.

    Right-click: You can select one or more files to upload to MicroCityWeb by right-clicking. The "Save" button (⑦) on the right can be clicked to view the list of uploaded files.

  2. Save Code:

    Left-click: When you save a file for the first time, a save file dialog box will pop up after you click the save button. You can choose the save location and fill in the file name. If you have previously saved the file locally and you have made modifications to the file and want to save the changes, you can simply click the save button to save the changes directly to the previously saved file.

    Right-click: You can view the list of uploaded files, and you can click on a file in the list and download it to your local machine.

Others

  1. Share. After clicking the button, a dialog box for entering a password will pop up. Afterwards, you will receive a link that anyone can use to access your share.

    If you enter a password in the dialog box, others who open the link can only run your program code and observe the running result, but cannot view your code (unless you tell them the password); if you do not enter a password, others can not only run your code to view the running result but also view the code you have written.

  2. View help documentation.

Green: Code Editor

Code Editor

The integrated code editor on the left side of MicroCityWeb is based on AceEditor and therefore has some of its features.

Keyboard Shortcuts

Below are some commonly used keyboard shortcuts to help you edit code more efficiently.

Most Common

Ctrl+Z: Undo

Line Operations

Ctrl+D: Delete a line Ctrl+Shift+D: Duplicate a line

Alt+: Move line of code up Alt+: Move line of code down

Find Content

Ctrl+K: Find the next occurrence of selected content in the code

Indentation

Ctrl+[: Increase code indentation Ctrl+]: Decrease code indentation

Modify Values

Ctrl+Shift+: Increase the numeric value before the cursor by 1 Ctrl+Shift+: Decrease the numeric value before the cursor by 1

Red: Canvas area

Built-in code can be imported into the scene, see Command Area - Code Editing for details.

After importing the scene code, click the "Run" button to load the scene.

Built-in car model

Built-in car model

Built-in Earth model

Built-in Earth model

Scene Operations

Scene operations, including viewpoint movement and rotation, need to be performed in the canvas area. Therefore, the following will introduce the basic operations of the canvas area.

  • Zooming in and out of the scene: Scroll the mouse wheel up to zoom in and down to zoom out.
  • Translation: Hold down the right mouse button and drag.
  • Rotation
    • Scene rotation: Hold down the left mouse button and drag to rotate from your viewpoint.
    • Object rotation: Click on the object, the color of the object changes, and then hold down the left mouse button on the object to rotate around the object's center. Rotate object

These operation rules apply to both two-dimensional and three-dimensional objects.

Yellow: Code Output Area

After opening MicroCityWeb, the code output area is shown below. Clicking on the code output area will cause the entire area to move up, allowing you to see more historical output information.

Bottom bar

Regarding the information output in this area, the code output area will output the following information:

  • Script output: The left side is the output of the script, including the output time and content.
  • Script running status: The first line on the right side shows the script running status. "state: ready" indicates that the script is ready to start running (not yet running), and "state: running" indicates that the script is running.
  • MicroCityWeb version number: Indicates the current version number of MicroCityWeb being used. If there is a difference from the known version, you can force a refresh to load the latest version.

Notes

Turn off automatic translation

Turn off automatic translation: If your operating system language is not English and the browser has automatic translation enabled, it needs to be manually disabled, otherwise there will be errors when running the code.

Last Updated:
Contributors: huuhghhgyg
+ + + diff --git a/images/doc/index.html b/images/doc/index.html new file mode 100644 index 00000000..91d245a8 --- /dev/null +++ b/images/doc/index.html @@ -0,0 +1,34 @@ + + + + + + + + + MicroCity笔记 + + + + + + + + + diff --git a/index.html b/index.html index 125bfb5a..c5b4d2d5 100644 --- a/index.html +++ b/index.html @@ -22,14 +22,14 @@ document.documentElement.classList.toggle('dark', true); } - 首页 | MicroCity笔记 + 首页 | MicroCity笔记 - + -

MicroCity笔记

记录MicroCity的学习过程并提供快捷的参考

桌面版 文档 学习笔记

文档和搜索 🔍

桌面版文档内容搬运自 MicroCity 项目文档并稍作适应性修改,在这里可以使用网站提供的搜索功能快速查找并跳转至内容

学习笔记 📔

除了文档,还有 MicroCity Web/Desktop 使用和学习过程中的一些踩坑总结和记录,帮助你尽可能多地避开天坑

高颜值,流畅 ✨

VuePress 驱动的独立网站,提供流畅阅读和文档参考体验。支持以 PWA 方式安装为应用,随时查阅,不受网络限制

开始使用MicroCity Web

  1. 打开MicroCity Webopen in new window,默认加载方块旋转的示例代码。

  2. 点击运行Play按钮运行代码

  3. 程序运行,看到右侧视图中方块旋转。

如果想要深入了解 MicroCity Web 的用法和使用技巧,可以参阅本站提供的 学习笔记

开始使用MicroCity Desktop

GitHub release (latest by date) GitHub release (by tag)

  1. 转到MicroCity的文档仓库下载 MicroCity的最新版本open in new window

  2. 打开 iconScriptEditor 并输入:

Print("hello, world!")
+    

MicroCity笔记

记录MicroCity的学习过程并提供快捷的参考

桌面版 文档 学习笔记

文档和搜索 🔍

桌面版文档内容搬运自 MicroCity 项目文档并稍作适应性修改,在这里可以使用网站提供的搜索功能快速查找并跳转至内容

学习笔记 📔

除了文档,还有 MicroCity Web/Desktop 使用和学习过程中的一些踩坑总结和记录,帮助你尽可能多地避开天坑

高颜值,流畅 ✨

VuePress 驱动的独立网站,提供流畅阅读和文档参考体验。支持以 PWA 方式安装为应用,随时查阅,不受网络限制

开始使用MicroCity Web

  1. 打开MicroCity Webopen in new window,默认加载方块旋转的示例代码。

  2. 点击运行Play按钮运行代码

  3. 程序运行,看到右侧视图中方块旋转。

如果想要深入了解 MicroCity Web 的用法和使用技巧,可以参阅本站提供的 学习笔记

开始使用MicroCity Desktop

GitHub release (latest by date) GitHub release (by tag)

  1. 转到MicroCity的文档仓库下载 MicroCity的最新版本open in new window

  2. 打开 iconScriptEditor 并输入:

Print("hello, world!")
 
  1. 将脚本另存为 test.mcs 并将其拖入 iconMicroCity

  2. 在程序主界面左侧转到 Modules 标签页,打开 icontest ,双击其中的 iconmain ,执行刚刚编写的脚本。

  3. 程序界面下方的 Messages 栏中会输出执行脚本的信息。

更多MicroCity的使用方法可以参考本站搬运自GitHub的文档:MicroCity文档,也可以参考 MicroCtiyopen in new window 在GitHub上的文档。

MicroCityNotesopen in new window 仓库

GitHub last commit GitHub Workflow Status Netlify Statusopen in new window

国内用户如果不方便访问 GitHub 也可以访问本站在 Netlify 上搭建的 同步站点open in new window

如果发现文档或笔记有问题,欢迎 Pull Requestopen in new window 或者提供 Issuesopen in new window 让它变得更完善😋

- + diff --git a/notes/3d-objects.html b/notes/3d-objects.html index 76c9c875..5db3db18 100644 --- a/notes/3d-objects.html +++ b/notes/3d-objects.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3D 对象 | MicroCity笔记 + 3D 对象 | MicroCity笔记 - + -

3D 对象

本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。

添加对象

向场景中添加对象,函数形式如下

local obj = scene.addobj([类型], {key1 = value1, key2 = value2, ...})
+    

3D 对象

本节将介绍 MicroCity Web 中的三维场景对象及其控制函数。

添加对象

向场景中添加对象,函数形式如下

local obj = scene.addobj([类型], {key1 = value1, key2 = value2, ...})
 

对象可选属性列表

添加到场景中的对象通常支持设置以下属性中的某些属性

对象属性含义
color对象的颜色。颜色的格式支持内置颜色、十六进制、RGB。与 场景背景颜色 的设置相同
opacity透明度
hcolor选中时的颜色
size对象的大小,默认值为1
length对象的长度,常用于 box(立方体)
width对象的宽度,常用于 box(立方体)
height对象的高度,常用于 box(立方体)
radius对象圆角大小
segments份数,通常用于设置 sphere(球体) 绘制的精度
selectable是否可被选中
name对象名称
text对象文本值
font文本字体
vertices构成对应对象的点集合

支持添加到场景中的类型如下

对象类型

对象类型列表

注释

为了简洁起见,下方示例的对象可选属性中只展示对应对象的关键属性。其他通用的属性可以参考 对象可选属性列表 自行添加。

label

label 是文本标签。可以在 text 属性中设置label的文本。

local obj = scene.addobj('label', {text = "Hello World!"})
 

points

points 是点集合。可以只创建单个点,也可以创建多个点。每个点都有三个维度的坐标以确定其在三维空间中的位置。点的个数通过 vertices 属性确定。

下面是一个创建 points 点集对象的示例

-- 在坐标为(5,5,5)的位置创建一个点
 scene.addobj("points", {vertices = {5,5,5}, size = 5})
@@ -65,6 +65,6 @@
 

此处只返回一个数值

setparent()

设置 obj 对象的父对象为 obj0

obj:setparent(obj0)
 

delete()

删除 obj 对象

obj:delete()
 
Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/3d-scene-en.html b/notes/3d-scene-en.html deleted file mode 100644 index 3c728c5a..00000000 --- a/notes/3d-scene-en.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - 3D Scene | MicroCity笔记 - - - - - -

3D Scene

This section introduces 3D scenes and their settings.

MicroCityWeb 3D Scene Coordinate System

The 3D scene coordinate system in MicroCityWeb follows the right-hand coordinate system, and the specific direction of each coordinate axis is shown in the following figure.

Coordinate system in MicroCityWeb

Coordinate system in MicroCityWeb

Note that the three-dimensional coordinate axes x, y, and z here are manually drawn to show the coordinate system in MicroCityWeb and do not directly exist in the three-dimensional scene.

Setting up a Scene

Setting up a scene requires the use of the setenv function, with the specific usage as follows:

local s = scene.setenv({grid="plane|sphere|none", bgcolor="rgb(255, 255, 255)", rotspeed=1, transpeed=1, camtype="ortho|persp", clear=true})
-

It can be simplified as follows:

local s = scene.setenv({key1 = value1, key2 = value2, ...})
-

The variable s holds the returned environment object. The optional parameters of the function will be described in detail below.

Optional Parameters of a Scene

Parameter List

grid: Background grid of the scene

Optional values

ValueMeaning
"none"default, no grid
"plane"flat grid
"sphere"spherical grid

bgcolor: Background color of the scene

Optional value types:

Value TypeExample
Built-in colors"black", "white", "gray", etc.
Hexadecimal colors"#ffffff", "#fff", "#000000", "#000", etc.
Colors represented by RGB"rgb(255, 255, 255)", "rgb(0, 0, 0)", etc.

Example:

scene.setenv({bgcolor='gray'}) -- Sets the background color to the built-in color "gray"
-scene.setenv({bgcolor='#eee'}) -- Sets the background color to the hexadecimal color "#eee"
-scene.setenv({bgcolor='rgb(255, 255, 255)'}) -- Sets the background color to white
-

camtype: Camera angle of view

Optional values:

ValueMeaning
"ortho"Orthographic. Equivalent to a projection onto the x and y plane. User's view is in two-dimensional space.
"persp"Perspective (default). User's view is in three-dimensional space.

clear: Whether to clear the scene

When the value is set to true, the scene is cleared.

The setenv function does not clear the original scene by default, unless the value of the clear parameter is manually set to true.

rotspeed & transpeed

ValueMeaning
rotspeedSets the speed of rotating a 3D object with the mouse.
transpeedSets the speed of translating a 3D object with the mouse.

These two parameters usually do not need to be set specially, and the default values can be used.

Others

Regarding high-frequency setting scenarios

2023/03/21: It has been found that setting the scene too frequently can cause excessive memory usage and browser crashes. Therefore, it is recommended to avoid calling the scene.setenv() function in a loop as much as possible.

If it is necessary to do so, make sure that the frequency of calls is relatively low. This allows the browser to have enough time for garbage collection, otherwise it may cause the browser to crash.

Last Updated:
Contributors: huuhghhgyg
- - - diff --git a/notes/3d-scene.html b/notes/3d-scene.html index cf7856fe..479c85aa 100644 --- a/notes/3d-scene.html +++ b/notes/3d-scene.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 3D 场景 | MicroCity笔记 + 3D 场景 | MicroCity笔记 - + -

3D 场景

本节将介绍 MicroCity Web 中的三维场景及其设置。

MicroCityWeb三维场景坐标系

MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。

MicroCityWeb中的坐标系 MicroCity Web中的坐标系

手动绘制上图坐标轴的代码

scene.setenv({grid="plane"})
+    

3D 场景

本节将介绍 MicroCity Web 中的三维场景及其设置。

MicroCityWeb三维场景坐标系

MicroCity Web中的三维场景坐标系符合右手坐标系,各个坐标轴的正方向具体见下图。

MicroCityWeb中的坐标系 MicroCity Web中的坐标系

手动绘制上图坐标轴的代码

scene.setenv({grid="plane"})
 
 -- x
 scene.addobj("polyline", {vertices = {0,0,0, 10,0,0}, color = "blue"})
@@ -53,6 +53,6 @@
 scene.setenv({bgcolor='#eee'}) --设置背景颜色为#eee
 scene.setenv({bgcolor='rgb(255, 255, 255)'}) --设置背景颜色为白色
 

camtype:摄像机视角

可选值

含义
"ortho"正视。相当于向x和y构成的平面投影,用户视角在二维空间中。
"persp"透视(默认值)。用户视角在三维空间中。

clear:是否清除场景

值设置为 true 时,清除场景

setenv 函数默认不清除原来的场景,除非手动设置参数 clear 的值为 true

rotspeed & transpeed

含义
rotspeed设置鼠标的旋转三维对象的速度
transpeed设置鼠标平移三位对象的速度

提示

这两个参数通常不需要特别设置,使用默认值即可。

其他

有关高频率设置场景

2023/03/21:目前发现过高频次设置场景会导致内存占用过高,进而导致浏览器崩溃的问题。因此建议尽量不要循环调用 scene.setenv() 函数。

如果必须这么做,请确保调用频率相对较低,这样允许浏览器有一定的时间进行GC(垃圾清理),否则可能导致浏览器崩溃。

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/cy-simulation.html b/notes/cy-simulation.html index 4061c10b..7620e72e 100644 --- a/notes/cy-simulation.html +++ b/notes/cy-simulation.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 港口AGV服务流程三维仿真思路 | MicroCity笔记 + 港口AGV服务流程三维仿真思路 | MicroCity笔记 - + -

港口AGV服务流程三维仿真思路

本文思路仅供参考。

Banner

集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。

实现场桥对集装箱的抓取

问题1截图

总体思路

实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽象为对象。

总体结构

具体的想法是将堆场对象作为数据模型(DataModel),主要存放各种数据,如存放集装箱实体、对应位置(行、列、高度)的集装箱坐标等数据;将场桥对象作为操作器(Operator),主要实现场桥的三维动画、实现对堆场对象中数据的管理。

这样做的好处是可以将场桥和堆场解耦合,方便后续的扩展。此外,如果对象属性考虑得比较周全,可以方便地在同一个场景中创建多个对象,实现多个场桥对堆场的操作。

事件和任务

我打算为整体流程中涉及到需要移动的主要实体对象创建任务序列。这样可以做到在同一个场景中实现多个场桥的并行操作,各个场桥执行各自的任务,互不干扰。此外,还需要一个总控制程序控制每个时间节点的任务执行情况,并控制场桥的三维动画。

业务流程

在这部分的仿真中主要业务流程聚焦于集装箱的移动。因此,最重要的就是集装箱所有权的流转。集装箱的所有权流转流程如下图所示:

集装箱对象流转过程

集装箱对象流转过程

对象结构

以下是这个仿真中主要涉及到的对象的结构

问题1场桥对象结构图

问题1堆场对象结构图

实现方法

堆场规模

对于堆场对象,由于它的功能主要是存放集装箱对象及其相关数据(比如对应位置的坐标),那么就还会出现一个问题,堆场的规模有多大?因此确定堆场的规模是一个必要的步骤。在创建堆场对象时需要确定所创建的堆场的规模,即行数、列数、高度。这样可以在创建堆场对象时就确定堆场的规模,方便后续的操作。

我的做法是首先确定堆场对象的占地大小集装箱层数,然后由相关数据去计算最多能摆放几行几列的集装箱。

  • 堆场占地大小方面,通过在创建对象时输入两点坐标来确定,根据两点连成的对角线构成一个矩形,从而确定堆场的占地面积。
  • 集装箱层数方面,通过在创建对象时输入一个数字来确定。根据这两个输入就就可以确定堆场的规模。

堆场布局计算

事件和任务

由于在这个仿真中需要移动的对象主要是场桥,因此每次循环执行任务的时候只需要操作场桥即可。

因此,我打算将场桥的任务序列作为一个队列,每次循环执行任务的时候,从对象的任务序列中取出第一个任务执行,执行完毕后判断是否满足任务执行完毕的条件,如果满足则删除这个任务,执行下一个任务。这样可以保证每次循环执行任务的时候,场桥对象能够按照次序执行任务。

执行任务的方法为 executeTask(dt) ,对象根据推进时间的长短 dt 执行任务。在 executeTask(dt) 中存放了处理任务的逻辑,包括判断任务类型、执行任务、删除任务等。

如果场景中存在多个场桥,只需要将这些对象添加到执行任务对象的列表中即可。主控程序每次循环执行任务时,会遍历这个对象列表,依次执行每个对象的任务。

提示

注意此处任务执行虽然在时间点上看是同时执行的,但是其实和对象所处的序列位置有关。

一个例子就是:假设两个对象同时需要抢占位置A,那么按照任务序列的顺序,先执行的对象会抢占到位置A,后执行的对象会抢占失败,尽管它们在同一时刻都在抢占位置A。因此,此处不是严格的同时执行,而是同一时刻按照任务序列的顺序执行。

业务流程

  1. 场桥首先从堆场中获取对应位置(行、列、高度)集装箱的坐标,并将吊具移动到堆场指定集装箱位置,抓取集装箱。集装箱所有权从堆场(cy.containers)转移到场桥吊具(rmg.attached)(通过解除表引用实现,将值设为 nil)。
  2. 场桥将集装箱移动到过道并放下集装箱。以同样的方式将集装箱所有权从场桥吊具(rmg.attached)移动到过道(rmg.stash),表明集装箱可以被提取。
  3. 如果有车辆将集装箱接走,则可以进一步将集装箱所有权从场桥过道(rmg.stash)移动到车辆上。

运行结果

场桥仿真

实现AGV到达至服务的全流程

问题描述

问题2描述

使用事件调度法实现以上流程的三维化形式

What's New

上一个仿真的实现是实现这个仿真的基础。相比于上一个仿真,这个仿真最为显著的改进体现在:

  • 使用面向对象编程模式,创建场桥、堆场(数据模型)、AGV、岸桥、船(数据模型)共4个类型的对象,并实现对象本体和其各部件的移动方法。

如果不了解面向对象编程,可以参考通用知识-面向对象编程

  • 延续面向事件的仿真的思路,实现了总控制流程,实现同一时刻对多个对象同时进行控制(主要通过对象的 executeTask(dt)maxStep() 及相关函数实现)。在面向对象的编程模式中,可以将 executeTask(dt)maxStep() 视为接口,主程序通过实现这两个接口,实现对对象的控制。(尽管lua中似乎没有这部分的概念)
  • 使用任务序列实现各个对象的流程,实现场桥和AGV之间、AGV和岸桥之间的相互等待,实现不同对象之间的任务协同。
  • 尝试将流程从堆场至AGV延伸至岸桥、船,实现两级排队等待。

对象设计

由于属性和函数实在太多,因此使用思维导图的形式展示对象的设计。

提示

此处占用篇幅较大,您也可以直接跳转到下一部分总体布局

堆场

堆场仍然作为数据模型。 堆场

场桥

场桥

AGV

AGV

岸桥

岸桥的代码和涉及结构主要衍生自堆场,因此后面不详细叙述。 岸桥

船对象的主要作用也是作为数据模型,设计思路同堆场。

船

总体布局

总体布局

总体流程

总体流程图

集装箱流转流程

相比于之前的仿真,这个仿真在流程上更进了一步,添加了AGV到达、排队的流程,还添加了岸桥服务、集装箱装船的流程。

流程分析

AGV出现后,场桥、岸桥和AGV之间的流程也变得更加复杂。首先,AGV的到达是随机的,因此可能造成排队现象。其次,AGV的到达会触发场桥和AGV的流程,而场桥和AGV的流程又会触发岸桥的流程。因此,这个仿真的流程是一个多级流程,需要考虑多个对象之间的流程协同。

特别是AGV和场桥之间的流程,其中存在AGV和场桥的相互等待。AGV到达的时候需要通知场桥提取货物。在场桥提取的过程中:

  • 场桥需要等待AGV到达指定位置后,才能将货物移动到AGV上
  • AGV需要等待场桥的抓取并将集装箱放在AGV上以后,才能将集装箱的所有权从场桥转移到AGV上

因此,AGV和场桥之间的流程是一个相互等待的流程。具体流程可以参考下图。

AGV和场桥相互等待的流程图

而岸桥的流程和场桥的流程类似,也是一个相互等待的流程。主要体现在:

  • 当AGV到达指定位置时,岸桥可能在服务别的AGV,此时AGV要进行等待
  • 当AGV刚进入岸桥的服务区域时,通知岸桥到达指定位置,如果岸桥先到达指定位置,则此时岸桥要进行等待

实现方法

排队流程的实现

AGV排队的情况我选择使用元胞自动机作为停车位的数据模型。其中,停车位的长度为:

停车位长度=对应数据模型中1个集装箱的长度+集装箱间隔长度 \text{停车位长度}=\text{对应数据模型中1个集装箱的长度}+\text{集装箱间隔长度}

由于AGV的长度比1个集装箱略长,因此需要占用2个停车位的长度。每次执行任务时,AGV会判断前方空间是否被阻塞,如果没被阻塞则向前移动。如果前方位置为目标bay,则前进后等待场桥作业,获取集装箱后继续以元胞为单位向前移动直到离开。场桥部分排队和岸桥部分排队原理也相同。

AGV排队示意图

AGV元胞自动机排队模型示意图

事件调度法的实现

在之前的仿真中,我使用了非固定步长的时间推进法来实现仿真。在这个仿真中,我使用了事件调度法来实现仿真。相比于时间推进法,事件调度法的特点是可以准确地将事件推进到发生的时刻,从而执行对应事件。

你可能注意到了对象设计部分我将 executeTask()maxstep() 标记为(interface),这是由于为了计算准确的推进时间,我需要在每个对象中实现 executeTask()maxstep() 方法。其中,executeTask() 方法用于执行任务,maxstep() 方法用于计算距离到达下一个事件的发生时间(当前任务还剩多久能执行完),然后得到最大能够推进的时间,再去跟系统运行得到的间隔时间dt进行比较得到最大的推进时间。

我认为课件中的下面这张图能够很好地表示如何使用事件调度法来进行仿真并刷新场景。其中,第一行指的是仿真的业务流程,第二行Refresh部分指的是刷新场景。

事件调度法示意图

运行结果

注意

由于以下部分内容均为动图且图片体积较大。由于本站托管于GitHubPage,因此如果您没有的特殊网络环境可能会造成动图加载缓慢甚至加载失败。

提示

如果您直接观看动图的时候动图区域出现了摩尔纹,可以尝试将动图点开放大看,再看看是否有改善。

场桥运行过程 场桥运行过程1

场桥运行过程2

岸桥运行过程 岸桥运行过程

总体运行过程 总体运行过程1

总体运行过程2

Last Updated:
Contributors: huuhghhgyg
- +

港口AGV服务流程三维仿真思路

本文思路仅供参考。

Banner

集装箱码头的流程仿真是一个比较复杂的仿真,需要考虑的因素、涉及到的对象比较多。本文主要介绍如何使用MicroCityWeb实现AGV从接收场桥服务到接受岸桥服务流程的思路。

实现场桥对集装箱的抓取

问题1截图

总体思路

实现场桥对集装箱的抓取是实现堆场仿真的第一步。这个部分我打算使用面向对象的方法实现,即将场桥和堆场抽象为对象。

总体结构

具体的想法是将堆场对象作为数据模型(DataModel),主要存放各种数据,如存放集装箱实体、对应位置(行、列、高度)的集装箱坐标等数据;将场桥对象作为操作器(Operator),主要实现场桥的三维动画、实现对堆场对象中数据的管理。

这样做的好处是可以将场桥和堆场解耦合,方便后续的扩展。此外,如果对象属性考虑得比较周全,可以方便地在同一个场景中创建多个对象,实现多个场桥对堆场的操作。

事件和任务

我打算为整体流程中涉及到需要移动的主要实体对象创建任务序列。这样可以做到在同一个场景中实现多个场桥的并行操作,各个场桥执行各自的任务,互不干扰。此外,还需要一个总控制程序控制每个时间节点的任务执行情况,并控制场桥的三维动画。

业务流程

在这部分的仿真中主要业务流程聚焦于集装箱的移动。因此,最重要的就是集装箱所有权的流转。集装箱的所有权流转流程如下图所示:

集装箱对象流转过程

集装箱对象流转过程

对象结构

以下是这个仿真中主要涉及到的对象的结构

问题1场桥对象结构图

问题1堆场对象结构图

实现方法

堆场规模

对于堆场对象,由于它的功能主要是存放集装箱对象及其相关数据(比如对应位置的坐标),那么就还会出现一个问题,堆场的规模有多大?因此确定堆场的规模是一个必要的步骤。在创建堆场对象时需要确定所创建的堆场的规模,即行数、列数、高度。这样可以在创建堆场对象时就确定堆场的规模,方便后续的操作。

我的做法是首先确定堆场对象的占地大小集装箱层数,然后由相关数据去计算最多能摆放几行几列的集装箱。

  • 堆场占地大小方面,通过在创建对象时输入两点坐标来确定,根据两点连成的对角线构成一个矩形,从而确定堆场的占地面积。
  • 集装箱层数方面,通过在创建对象时输入一个数字来确定。根据这两个输入就就可以确定堆场的规模。

堆场布局计算

事件和任务

由于在这个仿真中需要移动的对象主要是场桥,因此每次循环执行任务的时候只需要操作场桥即可。

因此,我打算将场桥的任务序列作为一个队列,每次循环执行任务的时候,从对象的任务序列中取出第一个任务执行,执行完毕后判断是否满足任务执行完毕的条件,如果满足则删除这个任务,执行下一个任务。这样可以保证每次循环执行任务的时候,场桥对象能够按照次序执行任务。

执行任务的方法为 executeTask(dt) ,对象根据推进时间的长短 dt 执行任务。在 executeTask(dt) 中存放了处理任务的逻辑,包括判断任务类型、执行任务、删除任务等。

如果场景中存在多个场桥,只需要将这些对象添加到执行任务对象的列表中即可。主控程序每次循环执行任务时,会遍历这个对象列表,依次执行每个对象的任务。

提示

注意此处任务执行虽然在时间点上看是同时执行的,但是其实和对象所处的序列位置有关。

一个例子就是:假设两个对象同时需要抢占位置A,那么按照任务序列的顺序,先执行的对象会抢占到位置A,后执行的对象会抢占失败,尽管它们在同一时刻都在抢占位置A。因此,此处不是严格的同时执行,而是同一时刻按照任务序列的顺序执行。

业务流程

  1. 场桥首先从堆场中获取对应位置(行、列、高度)集装箱的坐标,并将吊具移动到堆场指定集装箱位置,抓取集装箱。集装箱所有权从堆场(cy.containers)转移到场桥吊具(rmg.attached)(通过解除表引用实现,将值设为 nil)。
  2. 场桥将集装箱移动到过道并放下集装箱。以同样的方式将集装箱所有权从场桥吊具(rmg.attached)移动到过道(rmg.stash),表明集装箱可以被提取。
  3. 如果有车辆将集装箱接走,则可以进一步将集装箱所有权从场桥过道(rmg.stash)移动到车辆上。

运行结果

场桥仿真

实现AGV到达至服务的全流程

问题描述

问题2描述

使用事件调度法实现以上流程的三维化形式

What's New

上一个仿真的实现是实现这个仿真的基础。相比于上一个仿真,这个仿真最为显著的改进体现在:

  • 使用面向对象编程模式,创建场桥、堆场(数据模型)、AGV、岸桥、船(数据模型)共4个类型的对象,并实现对象本体和其各部件的移动方法。

如果不了解面向对象编程,可以参考通用知识-面向对象编程

  • 延续面向事件的仿真的思路,实现了总控制流程,实现同一时刻对多个对象同时进行控制(主要通过对象的 executeTask(dt)maxStep() 及相关函数实现)。在面向对象的编程模式中,可以将 executeTask(dt)maxStep() 视为接口,主程序通过实现这两个接口,实现对对象的控制。(尽管lua中似乎没有这部分的概念)
  • 使用任务序列实现各个对象的流程,实现场桥和AGV之间、AGV和岸桥之间的相互等待,实现不同对象之间的任务协同。
  • 尝试将流程从堆场至AGV延伸至岸桥、船,实现两级排队等待。

对象设计

由于属性和函数实在太多,因此使用思维导图的形式展示对象的设计。

提示

此处占用篇幅较大,您也可以直接跳转到下一部分总体布局

堆场

堆场仍然作为数据模型。 堆场

场桥

场桥

AGV

AGV

岸桥

岸桥的代码和涉及结构主要衍生自堆场,因此后面不详细叙述。 岸桥

船对象的主要作用也是作为数据模型,设计思路同堆场。

船

总体布局

总体布局

总体流程

总体流程图

集装箱流转流程

相比于之前的仿真,这个仿真在流程上更进了一步,添加了AGV到达、排队的流程,还添加了岸桥服务、集装箱装船的流程。

流程分析

AGV出现后,场桥、岸桥和AGV之间的流程也变得更加复杂。首先,AGV的到达是随机的,因此可能造成排队现象。其次,AGV的到达会触发场桥和AGV的流程,而场桥和AGV的流程又会触发岸桥的流程。因此,这个仿真的流程是一个多级流程,需要考虑多个对象之间的流程协同。

特别是AGV和场桥之间的流程,其中存在AGV和场桥的相互等待。AGV到达的时候需要通知场桥提取货物。在场桥提取的过程中:

  • 场桥需要等待AGV到达指定位置后,才能将货物移动到AGV上
  • AGV需要等待场桥的抓取并将集装箱放在AGV上以后,才能将集装箱的所有权从场桥转移到AGV上

因此,AGV和场桥之间的流程是一个相互等待的流程。具体流程可以参考下图。

AGV和场桥相互等待的流程图

而岸桥的流程和场桥的流程类似,也是一个相互等待的流程。主要体现在:

  • 当AGV到达指定位置时,岸桥可能在服务别的AGV,此时AGV要进行等待
  • 当AGV刚进入岸桥的服务区域时,通知岸桥到达指定位置,如果岸桥先到达指定位置,则此时岸桥要进行等待

实现方法

排队流程的实现

AGV排队的情况我选择使用元胞自动机作为停车位的数据模型。其中,停车位的长度为:

停车位长度=对应数据模型中1个集装箱的长度+集装箱间隔长度 \text{停车位长度}=\text{对应数据模型中1个集装箱的长度}+\text{集装箱间隔长度}

由于AGV的长度比1个集装箱略长,因此需要占用2个停车位的长度。每次执行任务时,AGV会判断前方空间是否被阻塞,如果没被阻塞则向前移动。如果前方位置为目标bay,则前进后等待场桥作业,获取集装箱后继续以元胞为单位向前移动直到离开。场桥部分排队和岸桥部分排队原理也相同。

AGV排队示意图

AGV元胞自动机排队模型示意图

事件调度法的实现

在之前的仿真中,我使用了非固定步长的时间推进法来实现仿真。在这个仿真中,我使用了事件调度法来实现仿真。相比于时间推进法,事件调度法的特点是可以准确地将事件推进到发生的时刻,从而执行对应事件。

你可能注意到了对象设计部分我将 executeTask()maxstep() 标记为(interface),这是由于为了计算准确的推进时间,我需要在每个对象中实现 executeTask()maxstep() 方法。其中,executeTask() 方法用于执行任务,maxstep() 方法用于计算距离到达下一个事件的发生时间(当前任务还剩多久能执行完),然后得到最大能够推进的时间,再去跟系统运行得到的间隔时间dt进行比较得到最大的推进时间。

我认为课件中的下面这张图能够很好地表示如何使用事件调度法来进行仿真并刷新场景。其中,第一行指的是仿真的业务流程,第二行Refresh部分指的是刷新场景。

事件调度法示意图

运行结果

注意

由于以下部分内容均为动图且图片体积较大。由于本站托管于GitHubPage,因此如果您没有的特殊网络环境可能会造成动图加载缓慢甚至加载失败。

提示

如果您直接观看动图的时候动图区域出现了摩尔纹,可以尝试将动图点开放大看,再看看是否有改善。

场桥运行过程 场桥运行过程1

场桥运行过程2

岸桥运行过程 岸桥运行过程

总体运行过程 总体运行过程1

总体运行过程2

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/notes/debug.html b/notes/debug.html index 144a1801..e0398c2d 100644 --- a/notes/debug.html +++ b/notes/debug.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 调试相关 | MicroCity笔记 + 调试相关 | MicroCity笔记 - + -

调试相关

本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。

清除输出

右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。

调试器快捷键

在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。

  • F9 Step Over:跳过当前行,执行下一行
  • F10 Step Into:进入当前行,如果当前行是函数调用,则进入函数内部
  • F11 Step Out:跳出当前函数,执行函数调用的下一行

Debug命令

监视变量

在控制台使用 debug.watch() 命令监视变量。

例如,在调试的过程中想要监视 a 变量的值,可以使用 debug.watch('a') 命令。

右键输出区域可以输入命令

堆栈跟踪

使用 debug.traceback() 函数可以打印出当前的堆栈跟踪信息

function myFunction()
+    

调试相关

本页介绍 MicroCity Web 调试(debug)相关的函数和快捷键。

清除输出

右键输出区域可以输入命令,输入 print() 可以清除输出区域的内容。

调试器快捷键

在调试程序的过程中,特别是在断点处,可以使用F9(Step Over)、F10(Step Into)、F11(Step Out)控制程序运行。

  • F9 Step Over:跳过当前行,执行下一行
  • F10 Step Into:进入当前行,如果当前行是函数调用,则进入函数内部
  • F11 Step Out:跳出当前函数,执行函数调用的下一行

Debug命令

监视变量

在控制台使用 debug.watch() 命令监视变量。

例如,在调试的过程中想要监视 a 变量的值,可以使用 debug.watch('a') 命令。

右键输出区域可以输入命令

堆栈跟踪

使用 debug.traceback() 函数可以打印出当前的堆栈跟踪信息

function myFunction()
     -- 某些代码逻辑
     print(debug.traceback("Stack trace"))
     -- 其他代码逻辑
@@ -45,6 +45,6 @@
 [string "function myFunction() ..."]:8: in function 'anotherFunction'
 [string "function myFunction() ..."]:11: in main chunk
 

运行状态

  • debug.debug() 进入Debug模式。常用于在程序运行过程中进入Debug模式。如果想要启动时就进入Debug模式,可以右键顶部▶️按钮。详见 用户界面简介 - 运行状态
  • debug.pause() 暂停程序运行。顶部运行按钮▶️会亮起,暂停按钮⏸️熄灭。

其他调试命令

Lua 的 Debug 函数大多都适用于 MicroCity Web,可以参考:

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/event-scheduling-en.html b/notes/event-scheduling-en.html deleted file mode 100644 index ff861f4f..00000000 --- a/notes/event-scheduling-en.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - Discrete Event Simulation and Program Control | MicroCity笔记 - - - - - -

Discrete Event Simulation and Program Control

Coroutines

MicroCityWeb provides several coroutine-related functions that facilitate the implementation of event scheduling.

coroutine.queue

Adds a function or coroutine to the coroutine queue for execution after a specified relative time.

coroutine.queue(rt, f|co [, argument list...])
-

Parameters

ParameterDescription
rtRelative time from the current queue. It should be greater than or equal to 0. In other words, it specifies the time after which the input function or coroutine will be executed.
f/coFunction or coroutine. If it's a function, you only need to input the function name.

coroutine.qtime

Retrieves the current time of the queue.

local time = coroutine.qtime()
-

Example

Here are two examples provided:

Adding Coroutines to the Queue

This example demonstrates how to add coroutines to the queue and display the current queue time within the function.

function Show()
-    print("Current time:", coroutine.qtime())
-end
-
-function ShowShort()
-    print("Current time (short):", coroutine.qtime())
-end
-
-coroutine.queue(10, Show)
-coroutine.queue(20, Show)
-coroutine.queue(15, ShowShort)
-coroutine.queue(5, Show)
-
--- Result:
--- Current time: 5.0
--- Current time: 10.0
--- Current time (short): 15.0
--- Current time: 20.0
-

Vehicle Movement

This example demonstrates how to use coroutines to refresh the scene based on real-world time.

scene.setenv({grid='plane'}) -- Set the scene background grid
-
--- Vehicle
-local car = scene.addobj('/res/2axle.glb')
-car.speed = 1 -- Car speed
-
--- Initial time
-local t = os.clock()
-local dt = 0
-
--- Refresh time state t and dt (based on CPU intervals to synchronize with real-world time)
-function refreshtime()
-    dt = os.clock() - t
-    t = os.clock()
-end
-
--- Coroutine updates the scene
-function update()
-    if not scene.render() then return end -- Render the scene and check if the program is terminated
-    coroutine.queue(dt, update) -- Add the next update based on CPU step time
-    carmove() -- Move the vehicle
-    refreshtime() -- Calculate the current dt
-end
-
--- Vehicle movement
-function carmove()
-    print("Car moves at", t)
-    local x, y, z = car:getpos()
-    car:setpos(x, y, z + dt * car.speed)
-end
-
--- Initial update (add the first update)
--- Since subsequent updates are added within the function, the updates will loop automatically
-coroutine.queue(dt, update)
-

Random Numbers

Creating a Random Seed

local seed = math.randomseed(x [, dist])
-

Parameters

ParameterDescription
xRandom seed. Different input values will produce different random numbers. To get different values each time, consider setting the random seed x to the current time.
distRandom distribution (optional). If not set, the default is a uniform distribution. If this parameter is set, you can also specify mu and sigma as parameters for the corresponding distribution.

The dist parameter can be set to one of three distributions:

  • 'normal': Normal distribution
  • 'exponential': Exponential distribution
  • 'poisson': Poisson distribution

In addition, you can set parameters for these distributions, where the mu key represents the mean and the sigma key represents the standard deviation.

Example

-- Create a random seed with a Poisson distribution
-local seed = math.randomseed(os.time(), {distribution = "poisson", mu = "3"}) -- Poisson distribution with a mean of 3
-
--- Output a random number
-print(seed:random())
-

Program Control

Program control, in this context, mainly refers to controlling the execution of a program using the buttons in the user interface, including pause, resume, and stop.

This mainly refers to the first three buttons in the command bar.

In MicroCityWeb, program control refers to the pause, resume, and stop of the 3D interface rendering implemented through the scene object. The specific function is as follows:

local state = scene.render()
-

Here, the return value of scene.render() is stored in the state variable. The state variable can be either true or false, representing the running or terminated state of the program (button 3 in the command bar).

Pausing the rendering of 3D objects is also achieved by calling scene.render(). If the refresh of 3D objects is implemented by continuously calling the scene.render() function and the refresh interval is not controlled by os.sleep(), it is possible to pause the rendering of the 3D interface at a certain state. This is because if os.sleep() is used to control the speed of 3D object movement and the pause button is clicked while the program is in the os.sleep() process, the program may not respond immediately, resulting in the pause button becoming ineffective. Therefore, it is recommended not to use os.sleep() for controlling the speed of 3D object movement, but to use other parameters to control the duration of advancement in order to control the speed of 3D object movement.

Last Updated:
Contributors: huuhghhgyg
- - - diff --git a/notes/event-scheduling.html b/notes/event-scheduling.html index efe59d1d..f7b3c61f 100644 --- a/notes/event-scheduling.html +++ b/notes/event-scheduling.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 离散事件模拟和程序控制 | MicroCity笔记 + 离散事件模拟和程序控制 | MicroCity笔记 - + -

离散事件模拟和程序控制

本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。

协程

MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 部分了解相关概念。

coroutine.queue

将函数或协程添加到协程队列中等待

coroutine.queue(rt, f|co [, 参数列表...])
+    

离散事件模拟和程序控制

本文主要介绍如何在 MicroCity Web 中实现离散事件模拟和程序控制。

协程

MicroCity Web中提供了几个协程相关函数,方便实现事件调度法。如果主要用于实现事件调度法且尚不清楚事件调度法的原理,可以阅读 时间推进法-事件调度法 部分了解相关概念。

coroutine.queue

将函数或协程添加到协程队列中等待

coroutine.queue(rt, f|co [, 参数列表...])
 

参数

参数含义
rt相对当前队列的时间,要求大于等于0。换句话说,也就是再过rt执行输入的函数或协程
f/co函数或协程。如果是函数,只需要输入函数名

coroutine.qtime

获取当前队列的时间

local time = coroutine.qtime()
 

示例

此处提供两个示例

  1. 协程添加任务:使用协程添加任务,并在函数中显示当前队列时间
  2. 车辆移动:使用协程实现以真实世界的时间刷新场景

协程添加任务

这个示例中展示了如何使用协程添加任务,并在函数中显示当前队列时间

function Show()
     print("当前时间:",coroutine.qtime())
@@ -89,6 +89,6 @@
 print(seed:random())
 

程序控制

本文中的程序控制主要是指如何使用用户界面中的按钮控制程序的运行,包括暂停、恢复、停止等。

命令栏 命令栏

主要是指命令栏的前3个按钮

MicroCity Web中的程序控制主要是指3D界面渲染中通过 scene 对象实现的3D界面运动的暂停、恢复、停止,具体的函数如下:

local state = scene.render()
 

此处将 scene.render() 的返回值存放于 state 变量中,state 变量的值为 true 或者 false,分别代表程序的运行状态为运行或者被终止(命令栏中按下按钮3)。

3D对象的暂停渲染也是通过调用 scene.render() 来实现的。如果刷新3D对象是通过不断调用 scene.render() 函数实现,并且刷新间隔时间不是通过 os.sleep() 来控制,那么可以实现在3D界面上将渲染暂停在某个状态。这是因为如果使用 os.sleep() 来控制3D对象的运动速度,那么当点击暂停按钮时,很可能正好处于 os.sleep() 的过程中,导致程序无法立即响应,从而导致暂停按钮无效。因此,建议在控制3D对象的运动速度时避免使用 os.sleep(),而是通过添加其他参数的方式来控制推进时长,以达到控制3D对象运动速度的目的。

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/index.html b/notes/index.html index 4d0a9d61..329bb366 100644 --- a/notes/index.html +++ b/notes/index.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 笔记 | MicroCity笔记 + 笔记 | MicroCity笔记 - + -
Last Updated:
Contributors: huuhghhgyg
- +
Last Updated:
Contributors: huuhghhgyg
+ diff --git a/notes/lp.html b/notes/lp.html index 5923ee4f..76f60b35 100644 --- a/notes/lp.html +++ b/notes/lp.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 模型求解 | MicroCity笔记 + 模型求解 | MicroCity笔记 - + -

模型求解

在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。

规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划

提示

本页内容基于 MicroCity 桌面版。如果你在寻找 MicroCity Web 版的混合整数规划求解方法,请参考 MicroCity Web 笔记中对应的 混合整数规划 部分。

创建模型对象

创建规划模型对象,存入变量lp中。

local lp = CreateLP()
+    

模型求解

在MicroCity中可以对数学模型进行求解。接下来,本文将介绍在MicroCity中求解数学模型的常见过程,并提供一些技巧帮助你更好地建模。

规划模型中所有函数的详细用法可以参考文档 4.8混合整数线性规划

提示

本页内容基于 MicroCity 桌面版。如果你在寻找 MicroCity Web 版的混合整数规划求解方法,请参考 MicroCity Web 笔记中对应的 混合整数规划 部分。

创建模型对象

创建规划模型对象,存入变量lp中。

local lp = CreateLP()
 

官方文档中将创建的数学模型对象存入变量LPModel中,作用同本文的lp

写入数学模型

此时,数学模型的对象已经创建并存入了变量lp中,可以对其进行更进一步的操作。数学模型一般分为两个部分:

接下来,先介绍创建目标函数的具体做法。

创建目标函数

MicroCity中,使用SetObjectFunction()设置模型对象的目标函数。允许选择目标函数求最大值最小值。具体用法如下:

最大值
SetObjFunction(lp, coeff, "max") --求最大值
 

"min"和"max"不区分大小写,写"MIN"和"MAX"也可以

参数说明及示例

参数作用
lp数学模型对象。将数学模型输入函数中,为模型设置目标函数
coeff目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。
"min""max"确定目标函数求最大还是求最小。

coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数4x1+12x2+18x34x_1+12x_2+18x_3最小值,则添加目标函数的做法如下:

-- 假设你已经创建了模型对象,并存入变量lp中
@@ -189,6 +189,6 @@
 x[4][2]=1
 
结果配送工件
x13=1x_{13}=1C
x21=1x_{21}=1A
x34=1x_{34}=1D
x42=1x_{42}=1B

中间变量的处理

有时候模型中会存在一些中间变量,这些变量必须要在矩阵中有对应的位置才能对其进行求解,而这些中间变量不参与目标函数值的运算。可以将中间变量对应位置的系数设为0。

假设x1,x2,x3,x4x_1,x_2,x_3,x_4为决策变量,y1,y2y_1,y_2为中间变量。目标函数为:

z=i=14xi z=\sum_{i=1}^4x_i

则目标函数系数可以设为:

local fcons = {1, 1, 1, 1, 0, 0}
 

接下来按照一般流程做就可以啦😎

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/lua.html b/notes/lua.html index 0fd58e32..691e0e0f 100644 --- a/notes/lua.html +++ b/notes/lua.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - Lua语言快速上手 | MicroCity笔记 + Lua语言快速上手 | MicroCity笔记 - + -

Lua语言快速上手

由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。

变量和函数定义

lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。

a = 1.5
+    

Lua语言快速上手

由于MicroCity采用的脚本语言是Lua,因此在开始使用MicroCity编写脚本之前需要先熟悉Lua的基本用法。本文介绍了MicroCity编写Lua脚本的常用的语法,能够帮助你快速地根据其他编程语言中的概念理解MicroCity脚本编写的总体思路。

变量和函数定义

lua会自动识别变量类型,因此无需在变量名称前定义变量类型,直接赋值即可。

a = 1.5
 b = "string"
 c = {} -- c为表,见下文介绍
 

函数的定义

function add(a, b)
@@ -237,6 +237,6 @@
 PrintList(list1)
 -- 1 2 3 4 5 (没有发生变化)
 

在这个例子中,修改深拷贝得到的list2中的元素并不会对原来的list1产生影响。

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/mip.html b/notes/mip.html index a9cc05f4..74e1f287 100644 --- a/notes/mip.html +++ b/notes/mip.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 混合整数规划 | MicroCity笔记 + 混合整数规划 | MicroCity笔记 - + -

混合整数规划

本文档介绍MicroCity Web中混合整数规划的建模方法。

创建混合整数规划模型

创建整数规划模型对象

local mip = math.newmip() -- 将创建的模型对象赋值给 mip
+    

混合整数规划

本文档介绍MicroCity Web中混合整数规划的建模方法。

创建混合整数规划模型

创建整数规划模型对象

local mip = math.newmip() -- 将创建的模型对象赋值给 mip
 

设置目标函数

MicroCity Web中,模型的第一行是目标函数,使用mip:addrow()函数添加。

允许选择目标函数求最大值最小值。具体用法如下:

最大值
mip:addrow(coeff, 'max') --求最大值
 

参数说明及示例

参数作用
mip数学模型对象。将数学模型输入函数中,为模型设置目标函数
coeff目标函数系数,是一个table类型的变量。用于确定模型中目标函数的系数。
"min""max"确定目标函数求最大还是求最小。

coeff是目标函数的系数列表,是一个table类型的变量。假设你要求函数

4x1+12x2+18x3 4x_1+12x_2+18x_3

最小值,则添加目标函数的做法如下:

-- 假设你已经创建了模型对象,并存入变量mip中
@@ -152,6 +152,6 @@
 x[4][2]= 1.0
 

在线运行

在MicroCity Web中查看这个示例open in new window

结果配送工件
x13=1x_{13}=1C
x21=1x_{21}=1A
x34=1x_{34}=1D
x42=1x_{42}=1B

中间变量的处理

有时候模型中会存在一些中间变量,这些变量必须要在矩阵中有对应的位置才能对其进行求解,而这些中间变量不参与目标函数值的运算。可以将中间变量对应位置的系数设为0。

假设x1,x2,x3,x4x_1,x_2,x_3,x_4为决策变量,y1,y2y_1,y_2为中间变量。目标函数为:

z=i=14xi z=\sum_{i=1}^4x_i

则目标函数系数可以设为:

local fcons = {1, 1, 1, 1, 0, 0} -- 前面4位为决策变量,后面2位为中间变量
 

接下来按照一般流程做就可以啦😎

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/network.html b/notes/network.html index 82b9656e..9120b7d9 100644 --- a/notes/network.html +++ b/notes/network.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 操作网络 | MicroCity笔记 + 操作网络 | MicroCity笔记 - + -

操作网络

网络拓补化

网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题:

  1. 这条路是单向通行的还是双向通行?
  2. 这条路的起点是哪?终点是哪?

一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的符号为O,目的点的符号为D,这样,使用O和D就能清晰地描述每条路的方向。

对于上图的示例,上方的道路O=1,D=2,所以方向描述为从1到2;下方的道路O=2,D=1,方向描述为从2到1。

使用函数对网络进行拓补

MicroCity可以处理网络,所有函数的具体用法见参考文档:4.6 网络

此处简单列举几种创建MicroCity中网络对象的方法:

local network = CreateNetwork() 
+    

操作网络

网络拓补化

网络拓补化简单来说就是一个网络有节点,有节点之间的连线。如果把连线理解为道路,那么你需要解决以下问题:

  1. 这条路是单向通行的还是双向通行?
  2. 这条路的起点是哪?终点是哪?

一般认为一个网络图中,每条道路都是单向的。如果需要一条双向通行的道路,只需要反向添加一条道路即可。像这样: 双向通行 这样,每条路就有了通行方向。一般规定出发点的符号为O,目的点的符号为D,这样,使用O和D就能清晰地描述每条路的方向。

对于上图的示例,上方的道路O=1,D=2,所以方向描述为从1到2;下方的道路O=2,D=1,方向描述为从2到1。

使用函数对网络进行拓补

MicroCity可以处理网络,所有函数的具体用法见参考文档:4.6 网络

此处简单列举几种创建MicroCity中网络对象的方法:

local network = CreateNetwork() 
 

创建一个空网络对象并返回此对象。network就是返回得到的空网络对象。

创建对象后,可以使用AddLinkDelLink等函数在网络对象中创建连接。具体用法见参考文档。

local network, nodes, links = CreateNetwork(Lines)
 

此处的Lines为一个矢量图形对象,类型为Line。MicroCity中的CreateNetwork()函数在这种用法中可以直接帮你在道路连线上添加起点和终点,并自动在返回的links对象中标上O点和D点的编号。

也就是说,你只需要提供网络连线即可,剩下的拓补化工作可以由函数自动完成。我认为这可能是最常用的创建网络图并进行拓补化的方法。

网络拓补的简单示例

-- 打开连线图层
 Shapes = Open("Shapes.shp")
@@ -98,6 +98,6 @@
 

既然等号左边没有办法改变,就从等号右边做出改变。还记得怎么定义一个最简单的table吗?

local list = {1, 2, 3, 4, 5}
 

右边的1, 2, 3, 4, 5其实可以看做一个序列。所以,只要给函数的返回值加上括号就能把他们全部捞起来 ( •̀ ω •́ )✧

local indexList = { GetSTPPath(Network, endID, "iLinkShp") }
 

上面的这种做法得到的indexList就是一个table类型的变量了。然后就可以开始执行集合的各种操作了捏😋

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/oop.html b/notes/oop.html index 4bcc610c..c4b40eea 100644 --- a/notes/oop.html +++ b/notes/oop.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 面向对象编程 | MicroCity笔记 + 面向对象编程 | MicroCity笔记 - + -

面向对象编程

面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。

堆场对象

网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实现过对象的消息传递,如果实现了会继续更新本文。因此下面主要介绍一下如何在适用于MicroCity的lua代码中使用封装。

提示

本文中的代码示例适用于MicroCityWeb,对于桌面版的MicroCity不一定适用。此外,本文均为个人感悟,不保证概念绝对的正确性。

面向对象编程的基本概念

类和对象

通俗来说,类是对象的模板,对象是类的实例(实体)。

类是面向对象编程的基本概念,它是对一类事物的抽象。类的概念可以理解为一类对象,比如AGV、货架、场桥等。你可以把类理解为一类事物的模板,而对象则是根据这个模板创建出来的具体的事物。

一个比较好的例子是上面提到的货架。货架是一个类,那么具体的货架就是一个对象。货架类中包含了货架的各种属性,比如货架的位置,装载的货物等。通过货架类创建出来的不同的货架对象都属于货架类,比如货架1、货架2等,尽管它们的属性可能不同,但是它们都是货架类的对象。

类的属性和方法

在MicroCity的仿真中,就我个人遇到的情况而言,类一般会有属性,但是不一定会有方法。延续上面举的货架的例子来说,属性是类的特征,比如货架的位置、货架上的货物等。方法是类的行为,通常使用函数体现,比如AGV将货架抬起、放下、AGV移动或者带动货架移动。

仿真中使用面向对象的优点和缺点

优点

在MicroCity中,就涉及到多个同类物体移动、播放物体移动动画等场景而言(如AGV、货架、场桥移动等),需要进行比较大量的坐标计算和位置设置。如果对每个对象都实现一次,那么修改各个对象坐标的代码将会非常冗长,而且不易于维护。如果使用面向对象的编程思想,可以将数据处理的代码封装成一个个的对象,也能使代码更加更具有可读性和可维护性。

此外,如果在场景中创建多个同类对象,各个对象的参数也可能各不相同。如果使用面向对象的方法封装,可以将各个对象的参数封装在各个对象自身中。当仿真流程或者规模变得复杂时,能够增加代码的复用性。

对于仿真来说,最重要的是搞清楚仿真的业务流程和业务逻辑。使用面向对象编程可以使仿真的业务流程和业务逻辑体现得更清晰,使代码的可读性提高,更具有可维护性。 此外,当需要修改一类对象的业务逻辑时,只需要进入类中修改即可。比如修改一个港口中所有场桥的调度算法,由于所有场桥共用一套调度算法,因此只需要修改一次即可。

就我个人的情况而言,采用面向对象的方法封装对象时大多是希望创建一个通用的对象,然后在后续的仿真中通过自动或手动的方式创建多个同类对象,而各个对象的参数各不相同。这么做会使得代码通用性增加,而且也能够使得代码更加易懂,为后续的维护和修改提供便利,为大规模的仿真打下基础。

缺点

如果仿真规模很小,代码量不大的简单的操作,不建议使用面向对象的方法封装代码。 使用面向对象的方法会增加代码行数,甚至会使代码看起来显得比原问题更加复杂。(当然你要用也不会有什么后果,只是看起来会比较奇怪而已)具体可以参考下文提供的代码示例,不难发现,代码主要篇幅用在描述类及其业务逻辑上,而业务流程的代码很简单,且占比很小。

面向对象在Lua中的实现

在Lua中,面向对象的概念通常使用table实现。table是Lua中的一种数据结构,它可以用来表示数组、字典、对象等。在面向对象的编程中,table也可以用来表示对象。

示例

由于MicroCity中创建的对象都是table,因此我们可以在创建对象时,将对象的属性直接封装在table中,然后返回这个table。

下面是一个例子:

-- 函数将返回一个AGV对象
+    

面向对象编程

面向对象编程(Object Oriented Programming)是一种编程思想,它将真实世界中的事物抽象成程序世界中的对象,对象之间通过消息传递进行通信,从而构成程序的功能。

堆场对象

网上说的面向对象编程具有三大特征,即封装、继承和多态。但是我认为在这个仿真中用得最多的就是封装,继承和多态用的机会很少。此外,我暂时还没有在MicroCity中实现过对象的消息传递,如果实现了会继续更新本文。因此下面主要介绍一下如何在适用于MicroCity的lua代码中使用封装。

提示

本文中的代码示例适用于MicroCityWeb,对于桌面版的MicroCity不一定适用。此外,本文均为个人感悟,不保证概念绝对的正确性。

面向对象编程的基本概念

类和对象

通俗来说,类是对象的模板,对象是类的实例(实体)。

类是面向对象编程的基本概念,它是对一类事物的抽象。类的概念可以理解为一类对象,比如AGV、货架、场桥等。你可以把类理解为一类事物的模板,而对象则是根据这个模板创建出来的具体的事物。

一个比较好的例子是上面提到的货架。货架是一个类,那么具体的货架就是一个对象。货架类中包含了货架的各种属性,比如货架的位置,装载的货物等。通过货架类创建出来的不同的货架对象都属于货架类,比如货架1、货架2等,尽管它们的属性可能不同,但是它们都是货架类的对象。

类的属性和方法

在MicroCity的仿真中,就我个人遇到的情况而言,类一般会有属性,但是不一定会有方法。延续上面举的货架的例子来说,属性是类的特征,比如货架的位置、货架上的货物等。方法是类的行为,通常使用函数体现,比如AGV将货架抬起、放下、AGV移动或者带动货架移动。

仿真中使用面向对象的优点和缺点

优点

在MicroCity中,就涉及到多个同类物体移动、播放物体移动动画等场景而言(如AGV、货架、场桥移动等),需要进行比较大量的坐标计算和位置设置。如果对每个对象都实现一次,那么修改各个对象坐标的代码将会非常冗长,而且不易于维护。如果使用面向对象的编程思想,可以将数据处理的代码封装成一个个的对象,也能使代码更加更具有可读性和可维护性。

此外,如果在场景中创建多个同类对象,各个对象的参数也可能各不相同。如果使用面向对象的方法封装,可以将各个对象的参数封装在各个对象自身中。当仿真流程或者规模变得复杂时,能够增加代码的复用性。

对于仿真来说,最重要的是搞清楚仿真的业务流程和业务逻辑。使用面向对象编程可以使仿真的业务流程和业务逻辑体现得更清晰,使代码的可读性提高,更具有可维护性。 此外,当需要修改一类对象的业务逻辑时,只需要进入类中修改即可。比如修改一个港口中所有场桥的调度算法,由于所有场桥共用一套调度算法,因此只需要修改一次即可。

就我个人的情况而言,采用面向对象的方法封装对象时大多是希望创建一个通用的对象,然后在后续的仿真中通过自动或手动的方式创建多个同类对象,而各个对象的参数各不相同。这么做会使得代码通用性增加,而且也能够使得代码更加易懂,为后续的维护和修改提供便利,为大规模的仿真打下基础。

缺点

如果仿真规模很小,代码量不大的简单的操作,不建议使用面向对象的方法封装代码。 使用面向对象的方法会增加代码行数,甚至会使代码看起来显得比原问题更加复杂。(当然你要用也不会有什么后果,只是看起来会比较奇怪而已)具体可以参考下文提供的代码示例,不难发现,代码主要篇幅用在描述类及其业务逻辑上,而业务流程的代码很简单,且占比很小。

面向对象在Lua中的实现

在Lua中,面向对象的概念通常使用table实现。table是Lua中的一种数据结构,它可以用来表示数组、字典、对象等。在面向对象的编程中,table也可以用来表示对象。

示例

由于MicroCity中创建的对象都是table,因此我们可以在创建对象时,将对象的属性直接封装在table中,然后返回这个table。

下面是一个例子:

-- 函数将返回一个AGV对象
 function AGV()
     -- 在MicroCity中创建一个AGV的3d对象
     local agv = scene.addobj('/res/agv.glb')
@@ -96,6 +96,6 @@
     return self
 end
 

类的类型

我在这里还想总结一下我创建过的类主要有什么类型。

  1. 3D实体类。 主要控制3D实体的运动,如AGV、场桥等,它们大多具有实体且需要移动。有的甚至还包含子对象,比如场桥对象具有吊具、绳索、吊车等子对象。
  2. 数据模型。 比如堆场,货架、货物。具体来说比如堆场类中包含堆场的长宽、堆场中的货物、堆场中的集装箱等数据。

需要注意的是,我认为这些类型也不是严格区分的,某些类甚至共同具有这些类的特性,严格区分这个类属于哪种类型也没有太大意义。比如AGV类中也包含了AGV的位置、速度等数据,而货架类只是存储了货架模型,货架模型的移动还是交由AGV控制,而其更重要的功能是记录货架上货物的信息。因此,我认为这些类型只是一种大致的划分,具体的实现还是要根据实际业务流程和需求情况来。

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/plots.html b/notes/plots.html index ec042c16..a389d5f8 100644 --- a/notes/plots.html +++ b/notes/plots.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 通用绘图代码 | MicroCity笔记 + 通用绘图代码 | MicroCity笔记 - + -

通用绘图代码

本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。

相关信息

本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。

直方图

直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的分布情况。

以下是用我包装的直方图对象绘制的直方图的示例

直方图示例

导入直方图

首先导入直方图的代码。目前有两种选择:

  1. 下载代码文件并导入(推荐)下载直方图代码文件 Histogram.lua,在MicroCityWeb中导入该文件,再引用该文件后即可使用。引用的代码如下:
require("Histogram") --引用直方图
+    

通用绘图代码

本节提供了一些写好的绘图对象,方便需要数据可视化绘图时直接使用。

相关信息

本页所有开放源代码遵循MIT协议,可以随意使用,但公开发布时请保留版权信息。

直方图

直方图(Histogram)一般用于显示数据集中各数据值的频数或频率分布情况。它将数据按照一定的间隔划分为若干个区间(或称为“箱子”),然后绘制出每个区间的频数(或频率)在纵轴上的柱状图,以此反映数据的分布情况。

以下是用我包装的直方图对象绘制的直方图的示例

直方图示例

导入直方图

首先导入直方图的代码。目前有两种选择:

  1. 下载代码文件并导入(推荐)下载直方图代码文件 Histogram.lua,在MicroCityWeb中导入该文件,再引用该文件后即可使用。引用的代码如下:
require("Histogram") --引用直方图
 
  1. 复制代码:直接将Histogram.lua文件中的代码复制到你的代码中,代码见下方

创建直方图对象

创建一个直方图对象

local plot = Histogram(list) -- list为数据集
 

还可以在创建对象时对图的属性进行设置。

local plot = Histogram(list, {range={40,90,0,100}, scale={10, 50}, fdisp=function(x) return (x/n*100).."%" end})
 

属性的设置不是必须的,可以仅根据需要设置。此处就只设置了rangescalefdisp属性。

直方图属性设置

上面提供了直方图属性设置的简单例子。根据代码,还可以设置更多的属性。具体见下表:

属性值作用示例
origin设置图原点(左下角点)origin = {-50, -50},将图的原点设置在(-50,-50)的位置
size设置图横纵轴长度,可以理解为图的大小size = {100, 100},将图的x轴和y轴长度分别设置为100、100
scale设置横纵坐标轴的分度值scale = {3, 2},将图的x轴和y轴分度值分别设置为3和2
axislabel设置横纵轴标题axislabel = {"x", "y"},将图的x轴和y轴标题分别设置为"x"和"y"
range设置横纵坐标轴的显示范围range = {0, 10, 0, 20},将图的x轴范围设置为[0,10],y轴范围设置为[0,20]
filled设置是否填充柱状图filled = false,将柱状图设置为空心。默认样式为填充
fdisp数据标签的显示函数,默认返回数量。设置数据标签显示函数时也会影响y轴刻度的显示。fdisp = function(v) return (v/n*100).."%" end,将数据标签改为按照比例显示(假设n为样本数)

直方图高级用法

动态刷新数据图

  1. 修改图中的数据。此处以向图中添加数据为例。其中假设rnd为添加的数据。也可以直接修改plot.data的值。
table.insert(plot.data, rnd)
@@ -343,6 +343,6 @@
     return subplot
 end
 
Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/timelapse.html b/notes/timelapse.html index b47ca336..00a75cd9 100644 --- a/notes/timelapse.html +++ b/notes/timelapse.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 时间推进法 | MicroCity笔记 + 时间推进法 | MicroCity笔记 - + -

时间推进法

仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。

时间推进法的分类

常见的仿真时间推进方法有三大类:

  • 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。
  • 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。
  • 主导时钟推进法:主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。

实例

事件调度法

事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。在仿真过程中,仿真系统会根据当前仿真时间和各个事件发生的时间来确定下一个要发生的事件,并将仿真时间推进到该事件发生的时间。

事件调度法主要分为以下3个主要步骤,这3个步骤也是控制事件调度法的主控程序的主要步骤:

  • 时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻
  • 事件辨识:正确地辨识当前要发生的事件
  • 事件执行:正确地执行当前发生的事件

事件调度法基本原理流程图如下:

事件调度法在MicroCityWeb中的具体实现参见 离散事件模拟和程序控制 - 协程

固定增量推进法

固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。在每个步长内,若无事件发生,则仿真钟再推进一个单位时间T;若在该步内有若干个事件发生,则认为这些事件均发生在该步的结束时刻。

固定增量推进法

例题

代码流程示例

while scene.render() do
+    

时间推进法

仿真中的时间推进法是指在仿真过程中,如何推进仿真时间。

时间推进法的分类

常见的仿真时间推进方法有三大类:

  • 事件调度法:事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。
  • 固定增量推进法:固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。
  • 主导时钟推进法:主导时钟推进法是指在仿真过程中,由一个主导时钟控制整个仿真系统的运行,它通过控制时钟来控制仿真过程。

实例

事件调度法

事件调度法是一种基于事件的仿真方法,它通过对仿真系统中各个事件进行排序,按照事件发生的先后顺序来进行仿真。在仿真过程中,仿真系统会根据当前仿真时间和各个事件发生的时间来确定下一个要发生的事件,并将仿真时间推进到该事件发生的时间。

事件调度法主要分为以下3个主要步骤,这3个步骤也是控制事件调度法的主控程序的主要步骤:

  • 时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻
  • 事件辨识:正确地辨识当前要发生的事件
  • 事件执行:正确地执行当前发生的事件

事件调度法基本原理流程图如下:

事件调度法在MicroCityWeb中的具体实现参见 离散事件模拟和程序控制 - 协程

固定增量推进法

固定增量推进法是指在仿真过程中,固定一个时间增量,在设定起始时间后,在起始时间的基础上根据时间的增量来对时间进行推进模拟。在每个步长内,若无事件发生,则仿真钟再推进一个单位时间T;若在该步内有若干个事件发生,则认为这些事件均发生在该步的结束时刻。

固定增量推进法

例题

代码流程示例

while scene.render() do
     t = t + dt
     if t % cycle ~= work_time then
         d = d + v * dt
@@ -65,6 +65,6 @@
     t0 = os.clock() -- 记录仿真时间
 end
 

相关说明

  • 当仿真速度 simspeed 为1时,表示仿真时钟与真实世界时钟的速度相同。simspeed 可以视作加速倍率。
  • dt 表示两次记录时间之间的时间差,仿真中的时间步进根据 dt*simspeed 计算得到。

    相关信息

    需要注意的是,时间增量 dt 的数值在每个循环周期一般都不相同,dt 的具体大小一般取决于电脑的运算能力

    提示

    有时两次记录时间之间没有太多耗时的操作,计算得到的 dt 可能为0。一般两次时间记录之间存在一个 scene.render(),这样一般能够保证两次采样的时间之间能够计算得到一个不为0的时间差值。

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/tools.html b/notes/tools.html index 1e20f964..96915bfc 100644 --- a/notes/tools.html +++ b/notes/tools.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 有关工具 | MicroCity笔记 + 有关工具 | MicroCity笔记 - + - - + + diff --git a/notes/versions.html b/notes/versions.html index 00dedee9..8922b705 100644 --- a/notes/versions.html +++ b/notes/versions.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - MicroCity的版本 | MicroCity笔记 + MicroCity的版本 | MicroCity笔记 - + -

MicroCity的版本

MicroCity

GitHub release (latest by date) GitHub release (by tag)open in new window

MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwindopen in new window)意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他操作系统,比如MacOS、Linux等。

MicroCityWeb

GitHub last commit (branch)

🎯访问MicroCity Webopen in new window 📍(离线版)下载open in new window

为了解决这个问题,开发者决定开发 MicroCity Web,这是一个可以直接在浏览器中运行的版本。 MicroCity Web 不需要任何安装,只需要使用现代浏览器(如Google Chrome、Microsoft Edge)访问它的网站即可。虽然相比于桌面版,运行在浏览器上可能会造成一定的性能损失,但是这使得用户可以在几乎任何操作系统上使用该软件,比如电脑系统Windows、MacOS、Linux和手机/平板系统Android等。

尽管MicroCity的开发者推出了 MicroCity Web,您仍然可以继续使用以前开发的桌面版MicroCity。然而,桌面版本将不再更新新功能,所有新的功能和改进都将集中在 MicroCity Web 版中。这个决定的目的是确保 MicroCity 能够专注于一种版本,并在这个版本中提供最好的体验。这也使得 MicroCity 更容易管理和维护,避免了版本控制问题。

值得一提的是,尽管桌面版本不再更新新功能,它仍然可以继续使用。如果用户已经习惯使用桌面版本,他们可以继续使用它。然而,如果用户希望体验最新的功能和改进,则需要改用 MicroCity Web 版。

MicroCity Web 版也提供使用浏览器打包导出的离线版本(见上方 🔗链接)。

注意

但是由于 Chromium 浏览器内核的更新,某些老旧的系统版本可能不受支持(如 Windows 8.1 及以下的 Windows 版本、32 位的 Windows 操作系统等)

兼容性

MicroCity Web 版使用 Lua 5.4 作为脚本语言编写脚本。您可以在 MicroCity Web 运行环境或编辑器中输入 print(_VERSION) 指令查看使用的 Lua 版本。

由于使用了实验性的 JavaScript函数,MicroCity Web 可能在以下浏览器内核中运行存在兼容性问题:

  • iOS和iPad OS上的大多数浏览器(由于Apple强制使用Safari的浏览器内核)
  • FireFox浏览器

2023/9/29测试遇到的兼容性问题及部分技术细节

  • iOS 和 iPad OS:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)
  • FireFox:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)

关于 showOpenFilePicker() 方法的影响参见 MDN Web Docs | showOpenFilePicker()open in new window

总结

MicroCity Web 版的推出使得软件更加易用和普及,让更多的用户可以从中受益。同时,MicroCity 桌面版本仍然可用,使得那些已经习惯于使用该版本的用户可以继续使用,并让他们更容易地过渡到 MicroCity Web 版。

本文作者在写这篇笔记的时候 MicroCity Web 正在被第一次用于教学环境中,已经基本能够正常运行并实现一定的仿真功能。本文作者的学习经历如下:

  • MicroCity(桌面版):物流信息管理
  • MicroCity Web :物流系统仿真

本站笔记内容仅供参考。如果本文内容由于时间的因素出现偏差,也欢迎各位在 Github 上通过 Pull Requestopen in new window 的方式对本站内容进行修正🥳

Last Updated:
Contributors: huuhghhgyg
- +

MicroCity的版本

MicroCity

GitHub release (latest by date) GitHub release (by tag)open in new window

MicroCity 软件最初推出时只有一个桌面版本,只能在 Windows 操作系统上运行。随着时间的推移,开发者(@mixwindopen in new window)意识到这个限制使得许多潜在的用户无法使用该软件,因为他们的电脑使用的可能是其他操作系统,比如MacOS、Linux等。

MicroCityWeb

GitHub last commit (branch)

🎯访问MicroCity Webopen in new window 📍(离线版)下载open in new window

为了解决这个问题,开发者决定开发 MicroCity Web,这是一个可以直接在浏览器中运行的版本。 MicroCity Web 不需要任何安装,只需要使用现代浏览器(如Google Chrome、Microsoft Edge)访问它的网站即可。虽然相比于桌面版,运行在浏览器上可能会造成一定的性能损失,但是这使得用户可以在几乎任何操作系统上使用该软件,比如电脑系统Windows、MacOS、Linux和手机/平板系统Android等。

尽管MicroCity的开发者推出了 MicroCity Web,您仍然可以继续使用以前开发的桌面版MicroCity。然而,桌面版本将不再更新新功能,所有新的功能和改进都将集中在 MicroCity Web 版中。这个决定的目的是确保 MicroCity 能够专注于一种版本,并在这个版本中提供最好的体验。这也使得 MicroCity 更容易管理和维护,避免了版本控制问题。

值得一提的是,尽管桌面版本不再更新新功能,它仍然可以继续使用。如果用户已经习惯使用桌面版本,他们可以继续使用它。然而,如果用户希望体验最新的功能和改进,则需要改用 MicroCity Web 版。

MicroCity Web 版也提供使用浏览器打包导出的离线版本(见上方 🔗链接)。

注意

但是由于 Chromium 浏览器内核的更新,某些老旧的系统版本可能不受支持(如 Windows 8.1 及以下的 Windows 版本、32 位的 Windows 操作系统等)

兼容性

MicroCity Web 版使用 Lua 5.4 作为脚本语言编写脚本。您可以在 MicroCity Web 运行环境或编辑器中输入 print(_VERSION) 指令查看使用的 Lua 版本。

由于使用了实验性的 JavaScript函数,MicroCity Web 可能在以下浏览器内核中运行存在兼容性问题:

  • iOS和iPad OS上的大多数浏览器(由于Apple强制使用Safari的浏览器内核)
  • FireFox浏览器

2023/9/29测试遇到的兼容性问题及部分技术细节

  • iOS 和 iPad OS:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)
  • FireFox:
    • 无法打开本地文件(由于使用了 showOpenFilePicker() 方法)

关于 showOpenFilePicker() 方法的影响参见 MDN Web Docs | showOpenFilePicker()open in new window

总结

MicroCity Web 版的推出使得软件更加易用和普及,让更多的用户可以从中受益。同时,MicroCity 桌面版本仍然可用,使得那些已经习惯于使用该版本的用户可以继续使用,并让他们更容易地过渡到 MicroCity Web 版。

本文作者在写这篇笔记的时候 MicroCity Web 正在被第一次用于教学环境中,已经基本能够正常运行并实现一定的仿真功能。本文作者的学习经历如下:

  • MicroCity(桌面版):物流信息管理
  • MicroCity Web :物流系统仿真

本站笔记内容仅供参考。如果本文内容由于时间的因素出现偏差,也欢迎各位在 Github 上通过 Pull Requestopen in new window 的方式对本站内容进行修正🥳

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/notes/visualization.html b/notes/visualization.html index ab83308d..c36e2b14 100644 --- a/notes/visualization.html +++ b/notes/visualization.html @@ -22,16 +22,16 @@ document.documentElement.classList.toggle('dark', true); } - 结果可视化 | MicroCity笔记 + 结果可视化 | MicroCity笔记 - + -

结果可视化

本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。

改变形状颜色

在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项:

  • Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。
  • Lookup Table:通过数值查询表格显示对应的颜色。
  • Graduated Color:根据表中数值大小设置渐变色。

Lookup Table 通过表中值改变颜色

Type的属性值改为Lookup Table,根据表格中的数值改变图形的颜色,达到选中指定图形的效果。

LookupTableProperties.png

此处示例将Lookup Table中的Attribute改为表格中的SELECT,通过表中的SELECT列值控制线的颜色(属性设置见上图)。当值为0时显示黑色,值为1时显示红色。表格中SELECT列的值和Lookup Table中的具体设置如下图。

TableSelect.pngLookupTableColor.png

最终实现的效果 SelectLinksColor.png

Graduated Color 根据值的大小显示渐变色

Type的属性值改为Graduated Color,根据表格中不同数值的大小显示不同的颜色,达到显示渐变色的效果。

GraduatedColorProperties.png

此处示例根据每个国家的人口数量显示渐变色。可以看到中国人口数量大,因此显示红色,印度人口数量也较大,因此显示橙色。其他地区人口数量较低,但也能通过颜色看出一些差别。

GraduatedColorResult.png

Graduated Color下的Colors属性中还可以调整其他配色方案。设置界面如下图,此处就不不一一列举了。

GraduatedColorSettings.png

如果感兴趣可以参考文档2.1 展示世界地图中的示例手动尝试更改此属性。

更改图形和标签的显示大小

参考系的选择

显示内容尺寸的参考系有2个,一个是以地图为参考系,一个是以屏幕为参考系。此处将图形和标签的显示尺寸都设置为相同的参考系。

内容以地图为参考系时,显示内容的大小会根据地图大小同步缩放,如下图:

RelateToMapBig.png (以地图为参考系放大)

RelateToMapSmall.png (以地图为参考系缩小)

内容以屏幕为参考系时,无论地图怎么缩放内容的大小都差不多,如下图:

RelateToScreenBig.png (以屏幕为参考系放大)

RelateToScreenSmall.png (以屏幕为参考系缩小)

因此,绘图的时候要根据绘图的目的选定参考系

  • 如果需要在地图上绘制确定尺寸的形状或者标明确定尺寸的标签,如绘制一个半径为10km的圆,此时应选用以地图为参考系
  • 如果仅需要在任何尺寸下都能清晰显示标签和图形,此时可以选择以屏幕为参考系

参考系应用实例

在图中绘制圆点,将圆的半径设置为圆的大小,并将圆的中心设置在每个绿点的中心上,灰色圆的大小表示每个绿点的覆盖范围大小

RangeDotRelateToMap.png

图中以地图为参考系(Map Units),以16为半径为每个绿点都绘制了一个灰色的圆,表示每个绿点的覆盖范围。这些灰色的圆存放在名为Range.shp的图层内,图层类型为Points

参考系的设定

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。 SizeProperties.png

如图标记的两个位置可以分别调整图形尺寸的参考系和标签尺寸的参考系。

  • 图形尺寸参考系设置Size栏目下的Size relates to...调整图形尺寸的参考系,Default Size调整图形的相对于坐标系的尺寸。
  • 标签尺寸参考系设置Labels栏目下的Size relates to...调整标签尺寸的参考系,Default Size调整的是标签(Labels)相对于坐标系的尺寸。

更改显示的标签

手动更改显示的标签

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。上图中显示的标签为ID,如果需要改为表格中的其他列,可以更改Lables栏目下的Attribute属性实现。

需要更改的属性位置如图,图中需要显示表中对应MSG列的值,只需要将Labels栏目下的Attribute属性值改为MSG即可。

LabelAttribProperties.png

但是每次更改图形并执行Update()函数后标签(Label)会取消显示。如果需要执行的脚本中含有此对于此图层的Update()函数,不必在每次执行完脚本后手动重新设置显示的标签,可以通过脚本自动选择显示的标签

自动更改显示的标签

通过SetParameter()函数可以更改属性值。以上图Labels栏目下的Attribute属性为例,选中这条属性后可以看到底栏显示其IDLABEL_ATTRIB,其类型为Choice

需要注意的是,当类型为Choice时,参数值从1开始编号,编号顺次对应下拉菜单的内容。

点开这条属性以后,可以看到MSG在第二个。

SetParameterProperties.png

由于Lua中编号一般由1开始,因此此处ID的编号对应1,MSG的编号对应2。需要操作对象为MSG,所以函数中需要填入Choice类型的参数值为2。

此时已经得到了所有需要的参数,可以使用SetParameter()函数对显示的标签进行更改。

-- transports为图形图层
+    

结果可视化

本文介绍了多种将计算结果可视化的方法。包括改变内容的颜色,改变形状大小,改变元素显示的属性标签等。

改变形状颜色

在程序界面左下角的图形属性框内可以通过改变Colors栏目下的Type属性改变显示颜色的种类。共有3种选项:

  • Unique Symbol:为同一个图层的所有图形指定某种颜色,此处不做过多介绍。
  • Lookup Table:通过数值查询表格显示对应的颜色。
  • Graduated Color:根据表中数值大小设置渐变色。

Lookup Table 通过表中值改变颜色

Type的属性值改为Lookup Table,根据表格中的数值改变图形的颜色,达到选中指定图形的效果。

LookupTableProperties.png

此处示例将Lookup Table中的Attribute改为表格中的SELECT,通过表中的SELECT列值控制线的颜色(属性设置见上图)。当值为0时显示黑色,值为1时显示红色。表格中SELECT列的值和Lookup Table中的具体设置如下图。

TableSelect.pngLookupTableColor.png

最终实现的效果 SelectLinksColor.png

Graduated Color 根据值的大小显示渐变色

Type的属性值改为Graduated Color,根据表格中不同数值的大小显示不同的颜色,达到显示渐变色的效果。

GraduatedColorProperties.png

此处示例根据每个国家的人口数量显示渐变色。可以看到中国人口数量大,因此显示红色,印度人口数量也较大,因此显示橙色。其他地区人口数量较低,但也能通过颜色看出一些差别。

GraduatedColorResult.png

Graduated Color下的Colors属性中还可以调整其他配色方案。设置界面如下图,此处就不不一一列举了。

GraduatedColorSettings.png

如果感兴趣可以参考文档2.1 展示世界地图中的示例手动尝试更改此属性。

更改图形和标签的显示大小

参考系的选择

显示内容尺寸的参考系有2个,一个是以地图为参考系,一个是以屏幕为参考系。此处将图形和标签的显示尺寸都设置为相同的参考系。

内容以地图为参考系时,显示内容的大小会根据地图大小同步缩放,如下图:

RelateToMapBig.png (以地图为参考系放大)

RelateToMapSmall.png (以地图为参考系缩小)

内容以屏幕为参考系时,无论地图怎么缩放内容的大小都差不多,如下图:

RelateToScreenBig.png (以屏幕为参考系放大)

RelateToScreenSmall.png (以屏幕为参考系缩小)

因此,绘图的时候要根据绘图的目的选定参考系

  • 如果需要在地图上绘制确定尺寸的形状或者标明确定尺寸的标签,如绘制一个半径为10km的圆,此时应选用以地图为参考系
  • 如果仅需要在任何尺寸下都能清晰显示标签和图形,此时可以选择以屏幕为参考系

参考系应用实例

在图中绘制圆点,将圆的半径设置为圆的大小,并将圆的中心设置在每个绿点的中心上,灰色圆的大小表示每个绿点的覆盖范围大小

RangeDotRelateToMap.png

图中以地图为参考系(Map Units),以16为半径为每个绿点都绘制了一个灰色的圆,表示每个绿点的覆盖范围。这些灰色的圆存放在名为Range.shp的图层内,图层类型为Points

参考系的设定

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。 SizeProperties.png

如图标记的两个位置可以分别调整图形尺寸的参考系和标签尺寸的参考系。

  • 图形尺寸参考系设置Size栏目下的Size relates to...调整图形尺寸的参考系,Default Size调整图形的相对于坐标系的尺寸。
  • 标签尺寸参考系设置Labels栏目下的Size relates to...调整标签尺寸的参考系,Default Size调整的是标签(Labels)相对于坐标系的尺寸。

更改显示的标签

手动更改显示的标签

在程序界面左下角的图形属性框内可以设置图形及其标签的尺寸参考系。上图中显示的标签为ID,如果需要改为表格中的其他列,可以更改Lables栏目下的Attribute属性实现。

需要更改的属性位置如图,图中需要显示表中对应MSG列的值,只需要将Labels栏目下的Attribute属性值改为MSG即可。

LabelAttribProperties.png

但是每次更改图形并执行Update()函数后标签(Label)会取消显示。如果需要执行的脚本中含有此对于此图层的Update()函数,不必在每次执行完脚本后手动重新设置显示的标签,可以通过脚本自动选择显示的标签

自动更改显示的标签

通过SetParameter()函数可以更改属性值。以上图Labels栏目下的Attribute属性为例,选中这条属性后可以看到底栏显示其IDLABEL_ATTRIB,其类型为Choice

需要注意的是,当类型为Choice时,参数值从1开始编号,编号顺次对应下拉菜单的内容。

点开这条属性以后,可以看到MSG在第二个。

SetParameterProperties.png

由于Lua中编号一般由1开始,因此此处ID的编号对应1,MSG的编号对应2。需要操作对象为MSG,所以函数中需要填入Choice类型的参数值为2。

此时已经得到了所有需要的参数,可以使用SetParameter()函数对显示的标签进行更改。

-- transports为图形图层
 SetParameter(transports, "LABEL_ATTRIB", 2)
 

SetParameter()函数需要在Update()函数执行后再执行,否则效果会被Update()函数覆盖。

现在回过头来再看看SetParameter()函数的具体用法:

SetParameter (Shapes|Table|Grid|Scene|Module, "id", Number|"String"|Object)
 
参数含义
参数1输入的对象,可以是ShapesTableGridSceneModule
参数2其中的id为属性对应的ID。如果是上文的情况,就是LABEL_ATTRIB
参数3如果需要更改属性值,只接受数值(Number)、字符串(String)、对象(Object)三种类型

SetParameter()函数的介绍出现在文档 4.2 控制用户界面 中,请参阅。

借助栅格图

栅格图也可以用于可视化,我认为栅格图最常用的场景就是绘制热力图。热力图的绘制主要通过修改栅格图上每个格子的值实现。如果不清楚栅格图的具体结构,可以先参考文档 3.3 栅格图。关于使用脚本控制栅格图,可以参考文档 4.4 栅格图形

一种使用栅格图绘制热力图的场景就是绘制地价图。在绘制地价图时,我们可以遍历栅格图上的每个格点,计算该格点到每个仓库的距离之和。然后将该格点的值设置为这个值,就可以得到一张热力图。这种方法可以帮助我们可视化地价的分布情况,并且可以用来发现地价的趋势和规律。

PlotPrice1.pngPlotPrice2.pngDL_Heatmap.png

Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/warehouse-simulation.html b/notes/warehouse-simulation.html index 97defd5a..0db2e6c3 100644 --- a/notes/warehouse-simulation.html +++ b/notes/warehouse-simulation.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 自动化仓库仿真思路 | MicroCity笔记 + 自动化仓库仿真思路 | MicroCity笔记 - + -

自动化仓库仿真思路

本文思路仅供参考,建议做出适当改进。

具体问题:基于元胞自动机的仓库仿真

Problem1

其中,出入库位置可以更改,叉车为AGV。

也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。

基本假设

  • 所有货架上的货物相同
  • 一个货架只放一个货物

因此,出库和入库可以看做完全相反的过程,所以此处只需要详细讨论出库的情况。即默认货架上本身就有货物。

总体实现思路

  • 将整个 3×33\times3 的仓库中每个元胞的位置赋予 (x,y)(x,y) 坐标,方便后续的移动操作。
  • 以AGV为核心,对货架进行操作。AGV处于升起状态移动货架时,只需要将货架的坐标位置同步设为AGV的位置即可达到AGV移动货架的效果。

业务流程

先按照需求数量乱序生成订单列表,AGV根据订单顺序依次将货架移动到出库点进行出库操作。

业务逻辑

当执行出库时,AGV先找到最近的货架并移动到那个货架的位置,抬起货架。为货架(AGV)设定移动的终点,计算曼哈顿距离差值。

  • 每次移动前都通过是否有障碍物判断货架移动的方向(xx 方向或 yy 方向)。
  • 如果两个方向都被堵塞,则优先选择 yy 方向(人为规定),将这个方向的障碍物递归移走,为货架移动腾出空间。如果 yy 方向没有空间才选择移动 xx 方向。

过程优化:关于旧方法和新方法

这两种方法都是可用的方法,但是 新方法对特定场景进行了优化,通过对障碍进行预判减少了操作步骤。 问题见下图

旧方法:无障碍预判(进出货点在 x=3,y=3x=3,y=3 的位置)

旧方法效果动图

👉 AGV完成第一个货架的出库后,向第二个货架移动,但是发现第一个货架挡住了去路,因此又回到第一个货架的位置将其移开,再回到第二个货架进行出库操作。

新方法:预判障碍(进出货点在 x=3,y=3x=3,y=3 的位置)

新方法效果动图

👉 AGV完成第一个货架的出库操作后判断后一个货架是否需要移动其他位置的货架才能到达出入库点。如果需要,则移动障碍货架后才前往后一个货架进行出库。

相关信息

本着尽量少占用出入库点的原则,当有空位时AGV将把在出入口的货架移走。因此某些看起来冗余的操作并非没有考虑全面。

不同数量货架对应的最优布局方案(动图) 8个货架的情况,上面已经进行了展示。下面仅展示表中货架数为5和7的情况。其他情况详见附件。

仿真数据收集分析

出入库效率最高

仿真结果如下图所示,表示相同货架数量下得到的效率最佳货架的货架布局

  • 最佳货架布局:相同货架数量下,取出所有货物操作次数(ticks)最小

布局图说明

  • 白色:没有放置货架
  • 浅灰色:货架,但是AGV一开始位于这个货架下方
  • 灰色:货架。

表格说明

  • 货架数量:存在于布局图中的货架数量
  • 旧ticks:使用旧方法(无预判障碍)实现取货的操作次数。
  • 新ticks:使用新方法(预判障碍)实现取货的操作次数。后面将对新方法进行说明。
  • 黄色高亮:相同布局下操作次数最少(ticks最小)的方案

最佳布局

空间利用率最大

如果所有位置都放置货架,则无法访问到所有货架。因此,空间利用率最大的方法是放置8个货架。

颜色说明

  • 绿色:有货物的货架
  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

有时候刷新太快可能看不出AGV抬起

进出货点在x=2,y=3的位置

8个货架动图

创新点

  • 额外考虑货物种类不同的情况。
  • 每次仿真会根据货架上的货物乱序生成需求。
  • 面向对象编程。使用面向对象的思想编程有助于将问题抽象化、有助于流程细节的改进;再加上好的命名方式会让整个程序的流程和逻辑清晰很多,不至于睡一觉起来就忘了😂

不同的货物类型用不同的颜色表示。AGV状态颜色、空货架的颜色、进出库点的颜色含义与之前相同。

  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

5个货架的情况示例

不同种类货物-5个货架

8个货架的情况示例

不同种类货物-8个货架

仿真改进:三维化自动仓库仿真

Problem2

在这一部分题目也稍微有所变化,要求将元胞自动机仿真仓库案例三维化,进行自动化仓库仿真。具体要求如上图。

总体思路

三维化

基于元胞自动机的仓库仿真为核心,将其中元胞自动机仿真的部分改写为内部数据表,作为内部数据模型,对整个仿真过程的状态进行监视和控制。

由于基于元胞自动机的仓库仿真使用了面向对象的方法封装对象,业务逻辑和流程的构建中大面积使用了对象方法,因此此处只需要改写对象方法(如 Agv:Move(dx, dy) 等)即可实现由元胞自动机仿真到三维化自动仓库的仿真。

如果程序整体结构设计优良,应用“面向对象”将会大幅提升程序的可维护性,降低移植难度。

对于AGV、货架直接套用现成模型;对于货物,只需要设置其距离货架的相对高度列表即可实现货物自动存放于指定高度。

提示

如果需要套用现成模型,或者申请上传模型到本文作者维护的仓库,请参考文档 3D对象-外部模型

出入库需求波动极大

  • 根据题目要求,基本上只存在有限的2种情况:3个货架、6个货架。
  • 由于货架数量情况有限,而基于元胞自动机的仓库仿真中得到了性能最佳的仓库布局,因此可以直接套用对应货架数量的最佳布局,本问题中只需要考虑固定货架布局下货物的位置摆放问题。
  • 对于3个货架的情况,其最佳布局属于高度对称的形态,距离出入库点的距离都为1,因此这种情况下只需要对1种情况进行仿真、收集其数据。
  • 对于6个货架的情况,选取了3种情况进行多次仿真,得到每种情况出入库耗费Ticks的平均值、最大值、最小值。

    当前Ticks是AGV移动的次数,相当于单位操作时间。后文改进空间中提到了可以进行的改进

  • 经过以上分析可以看出情况有限,因此可以通过控制货物需求总数不变,每次随机生成需求货物种类的方式对各种货物摆放位置进行仿真、对得到数据进行分析,最终确定最佳的货物布局方案。

改进

在测试的过程中发现原有移动货架的策略不合理,改进了移动货架的策略。

旧策略: 找到离AGV最近的装有需求货物的货架,将其移动到出入库点。

旧策略

可以看到AGV已经将需要出库的同种货物(青色方块)移动到了出入库点,但是由于AGV移动的货架对象是旁边的货架,因此没有对已经在出入库点的货物进行出库。

新策略: 找到离出入库点最近的装有需求货物的货架,将其移动到出入库点。改变策略后,没有发现以上提到的不合理情况出现。

新策略

创新

由于测试的次数较多,因此将主体流程写入函数并进行适应性改进,实现自动对所有情况进行仿真测试并将数据输出。下图为自动仿真测试运行为示例。

自动测试

自动仿真测试流程代码,仅供参考

-- 批量测试
+    

自动化仓库仿真思路

本文思路仅供参考,建议做出适当改进。

具体问题:基于元胞自动机的仓库仿真

Problem1

其中,出入库位置可以更改,叉车为AGV。

也就是说,这其实是一个移动货架仓库的元胞自动机仿真。AGV可以从货架底部穿过,可以移动到货架底部,把货架抬起并运送到出入库点。

基本假设

  • 所有货架上的货物相同
  • 一个货架只放一个货物

因此,出库和入库可以看做完全相反的过程,所以此处只需要详细讨论出库的情况。即默认货架上本身就有货物。

总体实现思路

  • 将整个 3×33\times3 的仓库中每个元胞的位置赋予 (x,y)(x,y) 坐标,方便后续的移动操作。
  • 以AGV为核心,对货架进行操作。AGV处于升起状态移动货架时,只需要将货架的坐标位置同步设为AGV的位置即可达到AGV移动货架的效果。

业务流程

先按照需求数量乱序生成订单列表,AGV根据订单顺序依次将货架移动到出库点进行出库操作。

业务逻辑

当执行出库时,AGV先找到最近的货架并移动到那个货架的位置,抬起货架。为货架(AGV)设定移动的终点,计算曼哈顿距离差值。

  • 每次移动前都通过是否有障碍物判断货架移动的方向(xx 方向或 yy 方向)。
  • 如果两个方向都被堵塞,则优先选择 yy 方向(人为规定),将这个方向的障碍物递归移走,为货架移动腾出空间。如果 yy 方向没有空间才选择移动 xx 方向。

过程优化:关于旧方法和新方法

这两种方法都是可用的方法,但是 新方法对特定场景进行了优化,通过对障碍进行预判减少了操作步骤。 问题见下图

旧方法:无障碍预判(进出货点在 x=3,y=3x=3,y=3 的位置)

旧方法效果动图

👉 AGV完成第一个货架的出库后,向第二个货架移动,但是发现第一个货架挡住了去路,因此又回到第一个货架的位置将其移开,再回到第二个货架进行出库操作。

新方法:预判障碍(进出货点在 x=3,y=3x=3,y=3 的位置)

新方法效果动图

👉 AGV完成第一个货架的出库操作后判断后一个货架是否需要移动其他位置的货架才能到达出入库点。如果需要,则移动障碍货架后才前往后一个货架进行出库。

相关信息

本着尽量少占用出入库点的原则,当有空位时AGV将把在出入口的货架移走。因此某些看起来冗余的操作并非没有考虑全面。

不同数量货架对应的最优布局方案(动图) 8个货架的情况,上面已经进行了展示。下面仅展示表中货架数为5和7的情况。其他情况详见附件。

仿真数据收集分析

出入库效率最高

仿真结果如下图所示,表示相同货架数量下得到的效率最佳货架的货架布局

  • 最佳货架布局:相同货架数量下,取出所有货物操作次数(ticks)最小

布局图说明

  • 白色:没有放置货架
  • 浅灰色:货架,但是AGV一开始位于这个货架下方
  • 灰色:货架。

表格说明

  • 货架数量:存在于布局图中的货架数量
  • 旧ticks:使用旧方法(无预判障碍)实现取货的操作次数。
  • 新ticks:使用新方法(预判障碍)实现取货的操作次数。后面将对新方法进行说明。
  • 黄色高亮:相同布局下操作次数最少(ticks最小)的方案

最佳布局

空间利用率最大

如果所有位置都放置货架,则无法访问到所有货架。因此,空间利用率最大的方法是放置8个货架。

颜色说明

  • 绿色:有货物的货架
  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

有时候刷新太快可能看不出AGV抬起

进出货点在x=2,y=3的位置

8个货架动图

创新点

  • 额外考虑货物种类不同的情况。
  • 每次仿真会根据货架上的货物乱序生成需求。
  • 面向对象编程。使用面向对象的思想编程有助于将问题抽象化、有助于流程细节的改进;再加上好的命名方式会让整个程序的流程和逻辑清晰很多,不至于睡一觉起来就忘了😂

不同的货物类型用不同的颜色表示。AGV状态颜色、空货架的颜色、进出库点的颜色含义与之前相同。

  • 紫色:没有货物的货架
  • 浅紫色:AGV抬起的货架
  • 深紫色:AGV在这个货架下面,但是没有抬起货架
  • 深灰色:进出货点

5个货架的情况示例

不同种类货物-5个货架

8个货架的情况示例

不同种类货物-8个货架

仿真改进:三维化自动仓库仿真

Problem2

在这一部分题目也稍微有所变化,要求将元胞自动机仿真仓库案例三维化,进行自动化仓库仿真。具体要求如上图。

总体思路

三维化

基于元胞自动机的仓库仿真为核心,将其中元胞自动机仿真的部分改写为内部数据表,作为内部数据模型,对整个仿真过程的状态进行监视和控制。

由于基于元胞自动机的仓库仿真使用了面向对象的方法封装对象,业务逻辑和流程的构建中大面积使用了对象方法,因此此处只需要改写对象方法(如 Agv:Move(dx, dy) 等)即可实现由元胞自动机仿真到三维化自动仓库的仿真。

如果程序整体结构设计优良,应用“面向对象”将会大幅提升程序的可维护性,降低移植难度。

对于AGV、货架直接套用现成模型;对于货物,只需要设置其距离货架的相对高度列表即可实现货物自动存放于指定高度。

提示

如果需要套用现成模型,或者申请上传模型到本文作者维护的仓库,请参考文档 3D对象-外部模型

出入库需求波动极大

  • 根据题目要求,基本上只存在有限的2种情况:3个货架、6个货架。
  • 由于货架数量情况有限,而基于元胞自动机的仓库仿真中得到了性能最佳的仓库布局,因此可以直接套用对应货架数量的最佳布局,本问题中只需要考虑固定货架布局下货物的位置摆放问题。
  • 对于3个货架的情况,其最佳布局属于高度对称的形态,距离出入库点的距离都为1,因此这种情况下只需要对1种情况进行仿真、收集其数据。
  • 对于6个货架的情况,选取了3种情况进行多次仿真,得到每种情况出入库耗费Ticks的平均值、最大值、最小值。

    当前Ticks是AGV移动的次数,相当于单位操作时间。后文改进空间中提到了可以进行的改进

  • 经过以上分析可以看出情况有限,因此可以通过控制货物需求总数不变,每次随机生成需求货物种类的方式对各种货物摆放位置进行仿真、对得到数据进行分析,最终确定最佳的货物布局方案。

改进

在测试的过程中发现原有移动货架的策略不合理,改进了移动货架的策略。

旧策略: 找到离AGV最近的装有需求货物的货架,将其移动到出入库点。

旧策略

可以看到AGV已经将需要出库的同种货物(青色方块)移动到了出入库点,但是由于AGV移动的货架对象是旁边的货架,因此没有对已经在出入库点的货物进行出库。

新策略: 找到离出入库点最近的装有需求货物的货架,将其移动到出入库点。改变策略后,没有发现以上提到的不合理情况出现。

新策略

创新

由于测试的次数较多,因此将主体流程写入函数并进行适应性改进,实现自动对所有情况进行仿真测试并将数据输出。下图为自动仿真测试运行为示例。

自动测试

自动仿真测试流程代码,仅供参考

-- 批量测试
 local cargo_ubs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} -- 测试需求(上限)序列
 
 local output_string_list = {} -- 测试结果列表字符串
@@ -60,6 +60,6 @@
     print("需求数量为", cargo_ubs[i], "的测试结果序列:", str)
 end
 

在自动仿真测试的过程中发现了BUG,详见下文说明。

货架布局方案

货架布局方案

颜色说明

  • 浅蓝色:出入库点
  • 白色:空格
  • 深蓝、红、黄:3种货物对应的颜色

条件假设

  • 每个货架上都放有2个同类货物
  • 货物需求随机,没有种类偏好
  • 每次只取出一个货物

仿真结果及分析

对每个货物布局方案中每种需求数量的情况仿真测试30次,求单方案结果中的最大值、最小值、平均值。最终得到结论为在6个货架的情况中,方案2的布局表现最优。

方案3:3个货架

方案3

方案6

方案6平均Ticks总趋势图 方案6平均Ticks总趋势图

方案6最优布局方案:方案2 方案6最优布局方案

还应绘制分方案的“需求量-最短平均服务时间”单位趋势图。以下以方案6-1为例,横坐标为货物需求数量,纵轴为最短平均服务时间(Ticks)。

方案6-1

改进空间

由于题目没有给定具体事件的执行时间,也没有指定时间单位,因此此处只计量货架的操作次数作为耗费的时间。也就是说,时间是后计算的,我想大部分同学做到这里可能都是这样的思路。虽然最终得出的结果没有问题,但是思路还可以转变一下,适应于后面的学习。

当前思路是以任务驱动的。虽然能够得到一个正确的结果,但是没有利用仿真时间,这种做法在只控制一个实体的时候不会出现问题。当要同时处理多个实体的时候,当前思路就无法做到同时操作多个实体完成任务,只能实现多个实体依次完成任务的情况。当前思路的具体流程如下:

由于应用的是时间推进法,因此仿真世界中有属于它自己的时间。对于我们来说,我们可以通过在仿真时间上乘一个倍率实现控制仿真速度,这个倍率就是仿真速度。此外,这种做法更加容易支持考虑多对象的情况。具体流程如下:

这样就改为了以时间为核心的仿真,在刷新任务执行进度的时候就可以直接刷新场景中的所有实体。由于仿真以时间为核心,因此就需要设定各种操作的速率/时间,保证时间计算的准确性。在MicroCityWeb中,有一些技巧可以用于时间推进法的仿真。

使用系统时间更新仿真时间

os.clock()函数可以获取系统当前的时间(以秒为单位,但是是小数)。有了这个函数就可以做到仿真与现实时间的同步。用法示例可以参考时间推进法

由于整个仿真的核心为时间,因此需要对之前没有规定的操作规定其需要花费的时间长度。在改进的部分中,又额外考虑了以下操作所要花费的时间:

  • 货物出入库所要花费的时间
  • AGV举起和降落货架所要花费的时间
Last Updated:
Contributors: huuhghhgyg
- + diff --git a/notes/web-ui-en.html b/notes/web-ui-en.html deleted file mode 100644 index a77d3f91..00000000 --- a/notes/web-ui-en.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - Introduction to the User Interface | MicroCity笔记 - - - - - -

Introduction to the User Interface

The overall interface of MicroCityWeb is shown in the following figure. This article will provide a detailed introduction to the user interface (UI) operations of MicroCityWeb.

Overall interface

Overview of Interface Zones

Overall, the interface of MicroCityWeb can be roughly divided into four areas:

Interface zones

Next, we will provide a detailed description of the usage and functions of these areas.

Blue: Command Area

The content of this area is shown in the following figure, with nine available buttons.

Command bar

Program Control

The first three buttons are mainly used to control program execution. Their specific functions are as follows:

  1. Run/Debug: Clicking the left mouse button will run the code in the code editor on the left-hand side of the webpage, while right-clicking will debug the code.

  2. Pause: If the program is running, clicking this button will pause its execution (if supported).

  3. Stop/Force Stop: If the program is running, clicking the left mouse button will stop its execution. If left-clicking does not stop the script, right-clicking can forcibly terminate its execution.

Program control

Code Editing

Buttons 4-7 are mainly related to code editing.

  1. Show/Hide Editor: If the left code editor is open, clicking this button will close it. If it's closed, clicking it will reopen it. If you right-click, the editor can be expanded to full screen.

  2. Open Built-In Code: You can directly load built-in code (import built-in models), such as cubes, trucks, earth, world maps, etc. The specific models will be introduced in detail when the red canvas area is introduced.

Built-in code

Built-in code list

  1. Open Local Code:

    Left-click: A dialog box will pop up when you left-click, and you can choose a code file (.lua) on your local machine. After confirming the selection to open the file, the text of the code file will be automatically imported into the code editor on the left.

    Right-click: You can select one or more files to upload to MicroCityWeb by right-clicking. The "Save" button (⑦) on the right can be clicked to view the list of uploaded files.

  2. Save Code:

    Left-click: When you save a file for the first time, a save file dialog box will pop up after you click the save button. You can choose the save location and fill in the file name. If you have previously saved the file locally and you have made modifications to the file and want to save the changes, you can simply click the save button to save the changes directly to the previously saved file.

    Right-click: You can view the list of uploaded files, and you can click on a file in the list and download it to your local machine.

Others

  1. Share. After clicking the button, a dialog box for entering a password will pop up. Afterwards, you will receive a link that anyone can use to access your share.

    If you enter a password in the dialog box, others who open the link can only run your program code and observe the running result, but cannot view your code (unless you tell them the password); if you do not enter a password, others can not only run your code to view the running result but also view the code you have written.

  2. View help documentation.

Green: Code Editor

Code Editor

The integrated code editor on the left side of MicroCityWeb is based on AceEditor and therefore has some of its features.

Keyboard Shortcuts

Below are some commonly used keyboard shortcuts to help you edit code more efficiently.

Most Common

Ctrl+Z: Undo

Line Operations

Ctrl+D: Delete a line Ctrl+Shift+D: Duplicate a line

Alt+: Move line of code up Alt+: Move line of code down

Find Content

Ctrl+K: Find the next occurrence of selected content in the code

Indentation

Ctrl+[: Increase code indentation Ctrl+]: Decrease code indentation

Modify Values

Ctrl+Shift+: Increase the numeric value before the cursor by 1 Ctrl+Shift+: Decrease the numeric value before the cursor by 1

Red: Canvas area

Built-in code can be imported into the scene, see Command Area - Code Editing for details.

After importing the scene code, click the "Run" button to load the scene.

Built-in car model

Built-in car model

Built-in Earth model

Built-in Earth model

Scene Operations

Scene operations, including viewpoint movement and rotation, need to be performed in the canvas area. Therefore, the following will introduce the basic operations of the canvas area.

  • Zooming in and out of the scene: Scroll the mouse wheel up to zoom in and down to zoom out.
  • Translation: Hold down the right mouse button and drag.
  • Rotation
    • Scene rotation: Hold down the left mouse button and drag to rotate from your viewpoint.
    • Object rotation: Click on the object, the color of the object changes, and then hold down the left mouse button on the object to rotate around the object's center. Rotate object

These operation rules apply to both two-dimensional and three-dimensional objects.

Yellow: Code Output Area

After opening MicroCityWeb, the code output area is shown below. Clicking on the code output area will cause the entire area to move up, allowing you to see more historical output information.

Bottom bar

Regarding the information output in this area, the code output area will output the following information:

  • Script output: The left side is the output of the script, including the output time and content.
  • Script running status: The first line on the right side shows the script running status. "state: ready" indicates that the script is ready to start running (not yet running), and "state: running" indicates that the script is running.
  • MicroCityWeb version number: Indicates the current version number of MicroCityWeb being used. If there is a difference from the known version, you can force a refresh to load the latest version.

Notes

Turn off automatic translation

Turn off automatic translation: If your operating system language is not English and the browser has automatic translation enabled, it needs to be manually disabled, otherwise there will be errors when running the code.

Last Updated:
Contributors: huuhghhgyg
- - - diff --git a/notes/web-ui.html b/notes/web-ui.html index c883ef5f..a9c80a9b 100644 --- a/notes/web-ui.html +++ b/notes/web-ui.html @@ -22,13 +22,13 @@ document.documentElement.classList.toggle('dark', true); } - 用户界面简介 | MicroCity笔记 + 用户界面简介 | MicroCity笔记 - + -

用户界面简介

MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。

总体界面

界面分区概览

整体来看,MicroCity Web的界面大致可以划分为4个区域。

界面分区

下面将详细介绍这几个区域的用法和功能。

蓝色:命令区域

此区域的的内容如下图所示,共有9个可用按钮。

命令栏

程序控制

前3个按钮的功能大致都用于控制程序运行。详细作用分别如下:

  1. 开始运行/debug: 左键点击后将运行网页左侧代码编辑器内的代码;右键点击后进行代码调试(debug)

  2. 暂停运行: 如果程序正在运行,点击后程序将暂停运行(如果程序支持)。

  3. 停止运行/强行停止: 如果程序正在运行,左键点击后程序将停止运行。有时存在左键点击无法停止运行脚本的情况,右键点击可以强行终止其运行。

程序控制

代码编辑

编号4~7的按钮主要与代码编辑有关。

  1. 显示/隐藏编辑器。 如果左侧的代码编辑器为开启状态,点击这个按钮后将关闭。如果为关闭状态,点击后会重新打开。如果使用右键点击,编辑器可以展开到全屏状态。

  2. 打开内置的代码 可以直接载入内置的代码(导入内置模型),如立方体、卡车、地球、世界地图等。具体的模型将在介绍画布区域时详细介绍。

内置代码

内置代码列表

  1. 打开本地代码/上传文件

    左键点击:弹出打开文件的对话框,您可以选择本机上的某个代码文件(.lua)。确定打开文件后,代码文件文本将自动导入到左侧代码编辑器中。

    右键点击:可以选择一个或多个文件上传到MicroCity Web中。右键“保存”按钮(⑦)可以查看已上传的文件列表。

  2. 保存代码/下载

    左键点击:当您第一次保存文件时,点击保存按钮后会弹出保存文件对话框,您可以选择保存位置并填写文件名。如果您之前已经将该文件保存到本地,而此时您又对该文件进行了修改并想要保存更改,直接点击保存按钮即可直接将更改保存到之前保存的文件中。

    右键点击:可以查看已上传的文件列表,您可以点击列表中的文件并下载到本地。

其他

  1. 共享。 点击按钮后,将会弹出一个输入密码的对话框。随后,您将会得到一个链接,任何人都可以通过这个链接打开您的共享。

    如果您在弹出的对话框中输入了密码,那么在其他人打开链接后,他们只能运行您的程序代码并观察运行结果,而无法查看您的代码(除非您告知他们密码);如果您没有输入密码,则其他人不仅可以运行您的代码查看运行结果,还可以查看您编写的代码。

  2. 查看帮助文档。

绿色:代码编辑器

代码编辑器

MicroCity Web左侧整合的代码编辑器源于AceEditor,因此也具有AceEditor的一些特性。

快捷键

下面将介绍一些常用的快捷键,帮助你更好地编辑代码。

最常用

  • Ctrl+Z:撤销

行操作

  • Ctrl+D:删除一行
  • Ctrl+Shift+D:复制一行
  • Alt+:行代码上移
  • Alt+:行代码下移

查找内容

  • Ctrl+K:在代码中查找下一个与选中内容

代码缩进

  • Ctrl+[:增加代码缩进
  • Ctrl+]:减少代码缩进

修改数值

  • Ctrl+Shift+:光标前的数字数值+1
  • Ctrl+Shift+:光标前的数字数值-1

红色:画布区域

可以从内置代码导入场景,详见 命令区域 - 代码编辑

导入场景代码后要点击“运行”按钮才会载入场景

内置代码_方块 内置汽车模型

内置代码_方块 内置地球模型

场景操作

对场景的操作包括视角移动、旋转都需要在画布区域进行。因此,下面将介绍画布区域的基本操作。

  • 场景的放大缩小:鼠标滚轮向上滚动为放大,向下滚动为缩小。
  • 平移:按住鼠标右键拖动。
  • 旋转
    • 场景旋转:按住鼠标左键拖动,以你的视角进行旋转
    • 对象旋转:点击对象,对象颜色改变后从对象上按住鼠标左键拖动,以对象为中心旋转。 旋转对象

无论是二维对象还是三维对象都遵循上述操作逻辑。

黄色:代码输出区域

打开MicroCity Web后,代码输出区域如下。点击代码输出区域后整个区域会上移,能够看到更多的历史输出信息。

底栏

说到这个区域输出的信息,代码输出区域会输出以下信息:

  • 脚本输出: 左侧是脚本的输出,包含输出时间、脚本输出内容。
  • 脚本运行状态: 右边第一行为脚本运行状态。state:ready表示脚本已经准备好开始运行(未运行),state:running表示脚本正在运行。
  • MicroCityWeb版本号: 表示当前使用的MicroCityWeb版本号。如果与已知版本有差异,可以通过强制刷新加载最新版本。

注意事项

关闭自动翻译

关闭自动翻译: 如果你的操作系统语言不是英语且浏览器开启了自动翻译,需要手动关闭,否则代码运行将出现错误。

Last Updated:
Contributors: huuhghhgyg
- +

用户界面简介

MicroCity Web的总体界面如下图,本文将详细介绍MicroCity Web的用户界面(UI)操作。

总体界面

界面分区概览

整体来看,MicroCity Web的界面大致可以划分为4个区域。

界面分区

下面将详细介绍这几个区域的用法和功能。

蓝色:命令区域

此区域的的内容如下图所示,共有9个可用按钮。

命令栏

程序控制

前3个按钮的功能大致都用于控制程序运行。详细作用分别如下:

  1. 开始运行/debug: 左键点击后将运行网页左侧代码编辑器内的代码;右键点击后进行代码调试(debug)

  2. 暂停运行: 如果程序正在运行,点击后程序将暂停运行(如果程序支持)。

  3. 停止运行/强行停止: 如果程序正在运行,左键点击后程序将停止运行。有时存在左键点击无法停止运行脚本的情况,右键点击可以强行终止其运行。

程序控制

代码编辑

编号4~7的按钮主要与代码编辑有关。

  1. 显示/隐藏编辑器。 如果左侧的代码编辑器为开启状态,点击这个按钮后将关闭。如果为关闭状态,点击后会重新打开。如果使用右键点击,编辑器可以展开到全屏状态。

  2. 打开内置的代码 可以直接载入内置的代码(导入内置模型),如立方体、卡车、地球、世界地图等。具体的模型将在介绍画布区域时详细介绍。

内置代码

内置代码列表

  1. 打开本地代码/上传文件

    左键点击:弹出打开文件的对话框,您可以选择本机上的某个代码文件(.lua)。确定打开文件后,代码文件文本将自动导入到左侧代码编辑器中。

    右键点击:可以选择一个或多个文件上传到MicroCity Web中。右键“保存”按钮(⑦)可以查看已上传的文件列表。

  2. 保存代码/下载

    左键点击:当您第一次保存文件时,点击保存按钮后会弹出保存文件对话框,您可以选择保存位置并填写文件名。如果您之前已经将该文件保存到本地,而此时您又对该文件进行了修改并想要保存更改,直接点击保存按钮即可直接将更改保存到之前保存的文件中。

    右键点击:可以查看已上传的文件列表,您可以点击列表中的文件并下载到本地。

其他

  1. 共享。 点击按钮后,将会弹出一个输入密码的对话框。随后,您将会得到一个链接,任何人都可以通过这个链接打开您的共享。

    如果您在弹出的对话框中输入了密码,那么在其他人打开链接后,他们只能运行您的程序代码并观察运行结果,而无法查看您的代码(除非您告知他们密码);如果您没有输入密码,则其他人不仅可以运行您的代码查看运行结果,还可以查看您编写的代码。

  2. 查看帮助文档。

绿色:代码编辑器

代码编辑器

MicroCity Web左侧整合的代码编辑器源于AceEditor,因此也具有AceEditor的一些特性。

快捷键

下面将介绍一些常用的快捷键,帮助你更好地编辑代码。

最常用

  • Ctrl+Z:撤销

行操作

  • Ctrl+D:删除一行
  • Ctrl+Shift+D:复制一行
  • Alt+:行代码上移
  • Alt+:行代码下移

查找内容

  • Ctrl+K:在代码中查找下一个与选中内容

代码缩进

  • Ctrl+[:增加代码缩进
  • Ctrl+]:减少代码缩进

修改数值

  • Ctrl+Shift+:光标前的数字数值+1
  • Ctrl+Shift+:光标前的数字数值-1

红色:画布区域

可以从内置代码导入场景,详见 命令区域 - 代码编辑

导入场景代码后要点击“运行”按钮才会载入场景

内置代码_方块 内置汽车模型

内置代码_方块 内置地球模型

场景操作

对场景的操作包括视角移动、旋转都需要在画布区域进行。因此,下面将介绍画布区域的基本操作。

  • 场景的放大缩小:鼠标滚轮向上滚动为放大,向下滚动为缩小。
  • 平移:按住鼠标右键拖动。
  • 旋转
    • 场景旋转:按住鼠标左键拖动,以你的视角进行旋转
    • 对象旋转:点击对象,对象颜色改变后从对象上按住鼠标左键拖动,以对象为中心旋转。 旋转对象

无论是二维对象还是三维对象都遵循上述操作逻辑。

黄色:代码输出区域

打开MicroCity Web后,代码输出区域如下。点击代码输出区域后整个区域会上移,能够看到更多的历史输出信息。

底栏

说到这个区域输出的信息,代码输出区域会输出以下信息:

  • 脚本输出: 左侧是脚本的输出,包含输出时间、脚本输出内容。
  • 脚本运行状态: 右边第一行为脚本运行状态。state:ready表示脚本已经准备好开始运行(未运行),state:running表示脚本正在运行。
  • MicroCityWeb版本号: 表示当前使用的MicroCityWeb版本号。如果与已知版本有差异,可以通过强制刷新加载最新版本。

注意事项

关闭自动翻译

关闭自动翻译: 如果你的操作系统语言不是英语且浏览器开启了自动翻译,需要手动关闭,否则代码运行将出现错误。

Last Updated:
Contributors: huuhghhgyg
+ diff --git a/service-worker.js b/service-worker.js index 7c770297..280f8572 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1,2 +1,2 @@ -if(!self.define){let e,s={};const a=(a,i)=>(a=new URL(a+".js",i).href,s[a]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()})).then((()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e})));self.define=(i,r)=>{const f=e||("document"in self?document.currentScript.src:"")||location.href;if(s[f])return;let d={};const c=e=>a(e,f),t={module:{uri:f},exports:d,require:c};s[f]=Promise.all(i.map((e=>t[e]||c(e)))).then((e=>(r(...e),d)))}}define(["./workbox-6db16f92"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.clientsClaim(),e.precacheAndRoute([{url:"assets/1.1_what_microcity_can_do.html-FdnWldjW.js",revision:"7344a33da1ce343e83d394182088de17"},{url:"assets/1.1_what_microcity_can_do.html-XJqtRZkC.js",revision:"0ab7378c0495d0df88d1b2bee90405ff"},{url:"assets/2.1_showing_a_world_map.html-MkZfvyzh.js",revision:"6876a1cbced2335017061c6faf8c56f8"},{url:"assets/2.1_showing_a_world_map.html-nIk_uI4l.js",revision:"d6e4ab1e690053e3944dab0c0973a9ca"},{url:"assets/2.2_searching_for_countries.html-eO0KcF_W.js",revision:"f8f96d4a976e48583e5343c3feb1aee7"},{url:"assets/2.2_searching_for_countries.html-JlV76Wlp.js",revision:"761f50b088c067219b2362a82794d7c6"},{url:"assets/3.1_ui_overview.html-9iOHDqCk.js",revision:"b5d49db3a3f5119a66560f69bf55d151"},{url:"assets/3.1_ui_overview.html-w-bvZnF-.js",revision:"6019c61ccafc14de13ccef35cddeb21b"},{url:"assets/3.2_vector_shapes.html-Ifn-q5O4.js",revision:"464e56896bb8a789a4d4fbd53ec4860e"},{url:"assets/3.2_vector_shapes.html-LHAJ_5Cg.js",revision:"d7bfa7d459fc73bdd06a7155c0097548"},{url:"assets/3.3_raster_grids.html-RHwKcATS.js",revision:"416f18073b6cb4ba294e1eb801ce5fab"},{url:"assets/3.3_raster_grids.html-xKWq9pqo.js",revision:"5edb00b8304d4ac6a38f925db92662cd"},{url:"assets/3.4_3d_scenes.html-f5Qwa3ic.js",revision:"a3da8c8beedf9fbe4355892967a84eba"},{url:"assets/3.4_3d_scenes.html-SpQlhrPf.js",revision:"b156765cc75d445563904375287def63"},{url:"assets/3.5_tables.html-p-Cvt07d.js",revision:"adb25e20fa218855c1df565a527dbaf6"},{url:"assets/3.5_tables.html-zF8D9g8c.js",revision:"11b1bbc88d8ef0b40f463ad1c8ca8ce3"},{url:"assets/3.6_maps_and_layers.html-0HlObXq2.js",revision:"66200e2565317e6a14498c0e9c7a43d4"},{url:"assets/3.6_maps_and_layers.html-XuAmYobJ.js",revision:"c91d1546445358d73abca7b793739cd4"},{url:"assets/3.7_modules.html-heS1MNUm.js",revision:"3b8c7fddeef042d26f70ccddf52a4e86"},{url:"assets/3.7_modules.html-q0PqEjdM.js",revision:"ab8c1c301741f7abd1071d3be7a15fb0"},{url:"assets/3d-objects-en.html-7DC5k-lZ.js",revision:"42b8960717d86c0fb63c26ae3cd42602"},{url:"assets/3d-objects-en.html-rNfsYRE-.js",revision:"c6af5c14e6807d2d8207da0aae1abef4"},{url:"assets/3d-objects.html-0syC6c1Y.js",revision:"766ccaf4ed05f3e1e4fe66066e29f35d"},{url:"assets/3d-objects.html-lKAwFYq5.js",revision:"b5b8a7991d443bfecddb17f6a5683ac3"},{url:"assets/3d-scene-en.html-iUVl-UL0.js",revision:"0ab99ddb72ddd6532cd1fd7c4b02aa55"},{url:"assets/3d-scene-en.html-M1ONxEpk.js",revision:"5aa5e17b956da78bb76fc694e79025ab"},{url:"assets/3d-scene.html-_tzv6BUx.js",revision:"d56951ddb0cc7d024b118f0888c6d56b"},{url:"assets/3d-scene.html-A33RmZzw.js",revision:"4317deb1a5513d262ea76b5459bac50d"},{url:"assets/4.1_si_overview.html-iNqEh7u3.js",revision:"feb6417dd656ee452976f5e53f3f298e"},{url:"assets/4.1_si_overview.html-umQYu3pM.js",revision:"02d2ef2ac8115b345d80c74d576436b3"},{url:"assets/4.2_ui_control.html-P4QU671J.js",revision:"e700b2ad44dfe0836ae6e8109910d9d8"},{url:"assets/4.2_ui_control.html-PXdKdANV.js",revision:"35790318273e3b5b5c2f410c563afb56"},{url:"assets/4.3_shapes_and_tables.html-kM2JYXcO.js",revision:"cc204711980e6ea90313152865922997"},{url:"assets/4.3_shapes_and_tables.html-ujzvaZYV.js",revision:"ed61b01ec19780188349dfd95daef44f"},{url:"assets/4.4_grids.html-7i5R0Lmo.js",revision:"6fc4056926277bcd713c390c876078d9"},{url:"assets/4.4_grids.html-sbNpid1M.js",revision:"c3b71f04c9bd5f0cde5524671710fcc8"},{url:"assets/4.5_3d_scenes.html-2AMaq24g.js",revision:"fa01e9e88a6a6f4e38ada3b478e680d5"},{url:"assets/4.5_3d_scenes.html-FkF6l2hE.js",revision:"d8976a7c4da55861764c001ea39bf482"},{url:"assets/4.6_networks.html-O88jEbX0.js",revision:"4fd7a53a6c44170f856c4a2afccb7a22"},{url:"assets/4.6_networks.html-PK_mfd9Y.js",revision:"1dc6eef3c4af226fe7f38b0a6d994e6f"},{url:"assets/4.7_des_simulations.html-8bSUiGUz.js",revision:"bd2a27922ac8e47d4fae24be7410863f"},{url:"assets/4.7_des_simulations.html-Ztj4rB4B.js",revision:"b422b32de1f64841ced212359926d055"},{url:"assets/4.8_mixed_integer_programming.html-bEUkQ8el.js",revision:"7ffa2a018a336ee7060aa9a589496f19"},{url:"assets/4.8_mixed_integer_programming.html-E59_LnJJ.js",revision:"f796daed751e4cb95e0a918635a085aa"},{url:"assets/404.html-G5wmh19c.js",revision:"d1c1345bc7f03c8bf1b4bddd811a571e"},{url:"assets/404.html-O1A74s9P.js",revision:"d9d8bbe4476db75f55602a872936c43a"},{url:"assets/A2hs-xakqhU9I.js",revision:"8645e2cec1595bb1fdd1a3fd04461178"},{url:"assets/app-DaLjD81q.js",revision:"616e01c7af55f7f65ad71269af7e69e1"},{url:"assets/AutoTranslate-DxMBsWAh.js",revision:"cdab077a6f396da2b7c8b2a2436c305a"},{url:"assets/button_3d-coWyniAs.js",revision:"b1d87c2188190dc8f9ad758ff3209930"},{url:"assets/button_action-tmG_4IgV.js",revision:"a45c2da3625b69f983ea2f3f250ed37f"},{url:"assets/button_load-GOP3K2yO.js",revision:"391a5543a75ec54a6c326b181f2841e4"},{url:"assets/CommandBar-jgj8yIQP.js",revision:"a9054c9490e70200bc2a4f8fdd523d63"},{url:"assets/coordinate-R7ZKfirG.js",revision:"141fa761610279516cdcbc64554f02a9"},{url:"assets/cy-simulation.html-bcA0fx8Y.js",revision:"bd77e66463d079c9698d0880e61dc5ee"},{url:"assets/cy-simulation.html-YeLzi-Ut.js",revision:"12534670508f0a24ca41eebeae5e6269"},{url:"assets/debug.html-mpPtl8CL.js",revision:"5cc4bb74570fc3ff1fa3404e5f168866"},{url:"assets/debug.html-yFg7dMCo.js",revision:"eb21819f5483a77bc21e0a0e1b06b765"},{url:"assets/event-scheduling-en.html-gRProVKn.js",revision:"f0bc586ec830d6353977e7f48297559a"},{url:"assets/event-scheduling-en.html-gy_6i2Mu.js",revision:"6f2854684011d84f59e12a9a685354c7"},{url:"assets/event-scheduling.html-7ezvA1AX.js",revision:"7c160ddbd2d30399ec12eed8a9d44de3"},{url:"assets/event-scheduling.html-o4tYPrMB.js",revision:"892130c78961166d5ff053f7f03f3112"},{url:"assets/flowchart-loQwkp6e.js",revision:"d0922e56732b0ff9f2eb72eccb4e7e36"},{url:"assets/giscus-unEZQsJ0.js",revision:"34c4288ad53e7d9be8d0f44c9fdba069"},{url:"assets/icon_microcity-Je85-7MO.js",revision:"0e7e05a07396d393fc7977851d9d6556"},{url:"assets/icon_module-AxwvBQMt.js",revision:"927274ea2b678bc32f744ed0e157301f"},{url:"assets/icon_script_editor-ibm_2NsU.js",revision:"2a9329638f5d3bdd769734a539f336b3"},{url:"assets/icon_shapes_polygon-5WS2EZQN.js",revision:"780fc09847b268c582be5334dce3ca5f"},{url:"assets/index-7SG8bi1h.js",revision:"46a193641571106d3b7b43f9bc2a2735"},{url:"assets/index.html-8_XflqQA.js",revision:"85ab13090c155db4e8e7e075bf0a495c"},{url:"assets/index.html-ciQEBxId.js",revision:"a3a26a5025e50ce083931f1d98d9b9cf"},{url:"assets/index.html-hph7Dv3o.js",revision:"e0173cc7b6b4369c18e2ed850ad7b5a3"},{url:"assets/index.html-HwGLrUxL.js",revision:"725e46b0abce3b136519f1f0e950ce11"},{url:"assets/index.html-ijEhgMTC.js",revision:"9f5fd939c5027d9494f5f4f1cd282973"},{url:"assets/index.html-lZExp6Yz.js",revision:"183ca6e222c60f27c3fdefd1793019dd"},{url:"assets/index.html-nFm7KTWc.js",revision:"3db036f82763891587e590de9a10f2d2"},{url:"assets/index.html-ps9YKXkA.js",revision:"d34b9b5e9f4dfa2056862771068d2add"},{url:"assets/KaTeX_AMS-Regular-0YIAJWTb.ttf",revision:"56573229753fad48910bda2ea1a6dd54"},{url:"assets/KaTeX_AMS-Regular-UIXRTGNW.woff2",revision:"66c678209ce93b6e2b583f02ce41529e"},{url:"assets/KaTeX_AMS-Regular-zJvWDgGp.woff",revision:"10824af77e9961cfd548c8a458f10851"},{url:"assets/KaTeX_Caligraphic-Bold-6vyEfazt.woff2",revision:"a9e9b0953b078cd40f5e19ef4face6fc"},{url:"assets/KaTeX_Caligraphic-Bold-AE18XbF9.ttf",revision:"497bf407c4c609c6cf1f1ad38f437f7f"},{url:"assets/KaTeX_Caligraphic-Bold-RIlxi71x.woff",revision:"de2ba279933d60f7819ff61f71c17bed"},{url:"assets/KaTeX_Caligraphic-Regular-4uo0fsfh.woff2",revision:"08d95d99bf4a2b2dc7a876653857f154"},{url:"assets/KaTeX_Caligraphic-Regular-k0QPq0y-.woff",revision:"a25140fbe6692bffe71a2ab861572eb3"},{url:"assets/KaTeX_Caligraphic-Regular-MF_e1AYw.ttf",revision:"e6fb499fc8f9925eea3138cccba17fff"},{url:"assets/KaTeX_Fraktur-Bold-bAz-dThZ.woff",revision:"40934fc076960bb989d590db044fef62"},{url:"assets/KaTeX_Fraktur-Bold-i-oP291Y.woff2",revision:"796f3797cdf36fcaea18c3070a608378"},{url:"assets/KaTeX_Fraktur-Bold-XZxETTVq.ttf",revision:"b9d7c4497cab3702487214651ab03744"},{url:"assets/KaTeX_Fraktur-Regular-8XXOHEfX.woff",revision:"e435cda5784e21b26ab2d03fbcb56a99"},{url:"assets/KaTeX_Fraktur-Regular-gf8Lq3rE.ttf",revision:"97a699d83318e9334a0deaea6ae5eda2"},{url:"assets/KaTeX_Fraktur-Regular-k2IhepQP.woff2",revision:"f9e6a99f4a543b7d6cad1efb6cf1e4b1"},{url:"assets/KaTeX_Main-Bold-CZtwCMuf.woff",revision:"4cdba6465ab9fac5d3833c6cdba7a8c3"},{url:"assets/KaTeX_Main-Bold-MGqDlVzd.ttf",revision:"8e431f7ece346b6282dae3d9d0e7a970"},{url:"assets/KaTeX_Main-Bold-sffOiHVw.woff2",revision:"a9382e25bcf75d856718fcef54d7acdb"},{url:"assets/KaTeX_Main-BoldItalic-88TzJhul.ttf",revision:"52fb39b0434c463d5df32419608ab08a"},{url:"assets/KaTeX_Main-BoldItalic-8QydwDku.woff2",revision:"d873734390c716d6e18ff3f71ac6eb8b"},{url:"assets/KaTeX_Main-BoldItalic-EqUi0SPe.woff",revision:"5f875f986a9bce1264e8c42417b56f74"},{url:"assets/KaTeX_Main-Italic-DVgO3ulm.woff2",revision:"652970624cde999882102fa2b6a8871f"},{url:"assets/KaTeX_Main-Italic-N1npxqDf.ttf",revision:"39349e0a2b366f38e2672b45aded2030"},{url:"assets/KaTeX_Main-Italic-TCzgZvdR.woff",revision:"8ffd28f6390231548ead99d7835887fa"},{url:"assets/KaTeX_Main-Regular-6_eCWgYQ.woff",revision:"f1cdb692ee31c10b37262caffced5271"},{url:"assets/KaTeX_Main-Regular-dtjb4qKe.woff2",revision:"f8a7f19f45060f7a177314855b8c7aa3"},{url:"assets/KaTeX_Main-Regular-MqWbzbVV.ttf",revision:"818582dae57e6fac46202cfd844afabb"},{url:"assets/KaTeX_Math-BoldItalic-d10o37uD.ttf",revision:"6589c4f1f587f73f0ad0af8ae35ccb53"},{url:"assets/KaTeX_Math-BoldItalic-ImPtsMme.woff",revision:"48155e43d9a284b54753e50e4ba586dc"},{url:"assets/KaTeX_Math-BoldItalic-mZ7zbAmZ.woff2",revision:"1320454d951ec809a7dbccb4f23fccf0"},{url:"assets/KaTeX_Math-Italic-H5Tq_9FA.ttf",revision:"fe5ed5875d95b18c98546cb4f47304ff"},{url:"assets/KaTeX_Math-Italic-LedwBEzP.woff2",revision:"d8b7a801bd87b324efcbae7394119c24"},{url:"assets/KaTeX_Math-Italic-wNP_z16f.woff",revision:"ed7aea12d765f9e2d0f9bc7fa2be626c"},{url:"assets/KaTeX_SansSerif-Bold-2yISjogg.woff",revision:"0e897d27f063facef504667290e408bd"},{url:"assets/KaTeX_SansSerif-Bold-9bFEtBg9.woff2",revision:"ad546b4719bcf690a3604944b90b7e42"},{url:"assets/KaTeX_SansSerif-Bold-hTHqZ76u.ttf",revision:"f2ac73121357210d91e5c3eaa42f72ea"},{url:"assets/KaTeX_SansSerif-Italic-Azdo-3Wm.woff",revision:"ef725de572b71381dccf53918e300744"},{url:"assets/KaTeX_SansSerif-Italic-GGIydc0p.ttf",revision:"f60b4a34842bb524b562df092917a542"},{url:"assets/KaTeX_SansSerif-Italic-tx9FahgZ.woff2",revision:"e934cbc86e2d59ceaf04102c43dc0b50"},{url:"assets/KaTeX_SansSerif-Regular-kun6lKiW.woff",revision:"5f8637ee731482c44a37789723f5e499"},{url:"assets/KaTeX_SansSerif-Regular-TaO4USHJ.ttf",revision:"3243452ee6817acd761c9757aef93c29"},{url:"assets/KaTeX_SansSerif-Regular-wwQp5Se8.woff2",revision:"1ac3ed6ebe34e473519ca1da86f7a384"},{url:"assets/KaTeX_Script-Regular--ckFYqpa.woff",revision:"a82fa2a7e18b8c7a1a9f6069844ebfb9"},{url:"assets/KaTeX_Script-Regular-98CFnxev.woff2",revision:"1b3161eb8cc67462d6e8c2fb96c68507"},{url:"assets/KaTeX_Script-Regular-uSZBlqPg.ttf",revision:"a189c37d73ffce63464635dc12cbbc96"},{url:"assets/KaTeX_Size1-Regular-27J7nvyK.ttf",revision:"0d8d9204004bdf126342605f7bbdffe6"},{url:"assets/KaTeX_Size1-Regular-Jgg_JgPA.woff2",revision:"82ef26dc680ba60d884e051c73d9a42d"},{url:"assets/KaTeX_Size1-Regular-tfebZ-uE.woff",revision:"4788ba5b6247e336f734b742fe9900d5"},{url:"assets/KaTeX_Size2-Regular-8uHcfdJu.woff2",revision:"95a1da914c20455a07b7c9e2dcf2836d"},{url:"assets/KaTeX_Size2-Regular-e4ClFoQr.ttf",revision:"1fdda0e59ed35495ebac28badf210574"},{url:"assets/KaTeX_Size2-Regular-KA9bXP1N.woff",revision:"b0628bfd27c979a09f702a2277979888"},{url:"assets/KaTeX_Size3-Regular-4KV7NJM_.ttf",revision:"963af864cbb10611ba33267ba7953777"},{url:"assets/KaTeX_Size3-Regular-k6uTKqBB.woff",revision:"4de844d4552e941f6b9c38837a8d487b"},{url:"assets/KaTeX_Size4-Regular-1hQb9ONy.ttf",revision:"27a23ee69999affa55491c7dab8e53bf"},{url:"assets/KaTeX_Size4-Regular-5eZcWcVX.woff2",revision:"61522cd3d9043622e235ab57762754f2"},{url:"assets/KaTeX_Size4-Regular-RfuIJGSk.woff",revision:"3045a61f722bc4b198450ce69b3e3824"},{url:"assets/KaTeX_Typewriter-Regular-9yG-_x36.ttf",revision:"6bf4287568e1d3004b54d5d60f9f08f9"},{url:"assets/KaTeX_Typewriter-Regular-juq-IZ9c.woff2",revision:"b8b8393d2e65fcebda5fa99fa3264f41"},{url:"assets/KaTeX_Typewriter-Regular-tMUvZjwd.woff",revision:"0e0460587676d22eae09accd6dcfebc6"},{url:"assets/lp.html-I7wRJlfF.js",revision:"73e78f76ccf3e544d1815ae6c4be0268"},{url:"assets/lp.html-NKzjcq8T.js",revision:"e469607be84d2c72afb35c12c8c36b7b"},{url:"assets/lua.html-x5twFLDp.js",revision:"986e735f4b44488517237f02812d7f26"},{url:"assets/lua.html-zCkaxI4j.js",revision:"f4c31548b9d4451b270e33c3d520a72f"},{url:"assets/mip-en.html-23DYx6JR.js",revision:"c387d933a956b9ca4c9d45147933bedf"},{url:"assets/mip-en.html-IS2AhQjv.js",revision:"22df9ba494886c5b7612429629e435fe"},{url:"assets/mip.html-B6IhijhB.js",revision:"8fbc56f876e3cfa84f97c76386b20408"},{url:"assets/mip.html-Jt_OOSuJ.js",revision:"a244a41f6081ef8afe6805942d8bb049"},{url:"assets/network.html-m23VzkXJ.js",revision:"301fd7cb2b71676ab9a598d87c3235fb"},{url:"assets/network.html-td-Kb3D8.js",revision:"5a35c481d99eb07566b6e593c22e90ab"},{url:"assets/oop.html-3LUP3-Yz.js",revision:"74008a05fa1e374820db98ffd4291119"},{url:"assets/oop.html-azlXcYwP.js",revision:"9254b3b86ba10479af96ca199cea9b89"},{url:"assets/plots.html-JiB_VWcB.js",revision:"a2ce12dc052a1510fb6e8e63019a8531"},{url:"assets/plots.html-ODP8nuzQ.js",revision:"989ad3b461d29fb59dda4515dbb80d33"},{url:"assets/polygon_sizes-bVJYQmiT.js",revision:"bab1b960c9f3f02a8de0a0f0be67d603"},{url:"assets/SearchBox-cTU2Stp4.js",revision:"ae3f72117b33e33ce436da5c97928579"},{url:"assets/style-gRAOaLx9.css",revision:"256c72c20e5fe4f6831f8a2a0af2c87d"},{url:"assets/timelapse.html-hdyuE7Lk.js",revision:"1d0e9843035bc3656d961901023e5cae"},{url:"assets/timelapse.html-mpQRHhbv.js",revision:"0e1e78a1eff5754faf8f0e600a843d22"},{url:"assets/tools.html-kWg64VtA.js",revision:"6e9453fbc21afe4906a14f2681717e00"},{url:"assets/tools.html-zf97O5Kc.js",revision:"bc284426edc777de344faaa30fbba52a"},{url:"assets/versions.html-9uZsLBnu.js",revision:"77a821c48d5cb3c9eec77f0705aa75d9"},{url:"assets/versions.html-HjNHjtrH.js",revision:"ef57ae6a5e3557acf10ca9deba3dce56"},{url:"assets/visualization.html--w3hFG24.js",revision:"441c692190d7274db6c5b8c38a7de5d2"},{url:"assets/visualization.html-xF8N-_EY.js",revision:"546940ef4c0a29e36d90973137ccbd49"},{url:"assets/warehouse-simulation.html-3NwF3MxT.js",revision:"19335076774294adfc8748752315ed91"},{url:"assets/warehouse-simulation.html-GfcmApNM.js",revision:"a3cc462c1483cc228f0a048d1ba532c6"},{url:"assets/web-ui-en.html-9hWYZBEN.js",revision:"a0b47462faa918f2795e57ecaa4eaa95"},{url:"assets/web-ui-en.html-FPAIksJ9.js",revision:"1a324ae30026932aea1cb0d97a0151ea"},{url:"assets/web-ui.html-cjOV8UTz.js",revision:"d251b838391b3194f56974bab2a347e6"},{url:"assets/web-ui.html-zrAeLt4a.js",revision:"01c1accc3a425a63329dacd4423fe788"},{url:"404.html",revision:"dd7866e72fc3f4d299abfd27946d3b85"},{url:"docs/1.1_what_microcity_can_do.html",revision:"b76f00c02a1128b742eb12818f928372"},{url:"docs/2.1_showing_a_world_map.html",revision:"e64941f12c26314cb02bf7a1e175676b"},{url:"docs/2.2_searching_for_countries.html",revision:"bef8e41517ea71b7a1edb12f46c75840"},{url:"docs/3.1_ui_overview.html",revision:"685c833c837a5188afa532dfa2584c4b"},{url:"docs/3.2_vector_shapes.html",revision:"456a4a413f8017eb4e257c5aa908211f"},{url:"docs/3.3_raster_grids.html",revision:"0c62cda412d0eaaec2f6d20ebf0a3ee0"},{url:"docs/3.4_3d_scenes.html",revision:"85cc759550c82a4fe461884e3f637c1f"},{url:"docs/3.5_tables.html",revision:"cade86c3bcf15c8b70cd5122d405c55c"},{url:"docs/3.6_maps_and_layers.html",revision:"0a9c3b29e9ae13ec4e11ed239efa2ae8"},{url:"docs/3.7_modules.html",revision:"70d1c6f7cef8d5df9b3e891577d27e17"},{url:"docs/4.1_si_overview.html",revision:"4a2c4951c208582aeddb778eb29f9c00"},{url:"docs/4.2_ui_control.html",revision:"c890b080d1e524fbb88bf478adae5070"},{url:"docs/4.3_shapes_and_tables.html",revision:"42aa4081f6f75e297e2b941eaafbd956"},{url:"docs/4.4_grids.html",revision:"312a11f10d238f18f863ea704a73f645"},{url:"docs/4.5_3d_scenes.html",revision:"904acbefb1fd6586a755e66199049eec"},{url:"docs/4.6_networks.html",revision:"355c830511fc1efec74761ce1e28480c"},{url:"docs/4.7_des_simulations.html",revision:"9ae752a8d844a6aaac3466eb0a513dfd"},{url:"docs/4.8_mixed_integer_programming.html",revision:"18b2d41ae0395859fb577b930b36ddde"},{url:"docs/imgs/index.html",revision:"98b03fe69260b6a020bde822b1091595"},{url:"docs/index.html",revision:"305fdfb377346acf0985b0e86a8c1318"},{url:"google3a9084eedb90aa13.html",revision:"5fdd561cbfed9c1a090e11665147df61"},{url:"index.html",revision:"5a7a6298a6bcdd90070640b79dcd4623"},{url:"notes/3d-objects-en.html",revision:"c9cffc498d111b3f7736f10b1c5b2572"},{url:"notes/3d-objects.html",revision:"1dfea4089f4636a823efa1f96943dd27"},{url:"notes/3d-scene-en.html",revision:"f94c977c6717501d824fdc691af74efe"},{url:"notes/3d-scene.html",revision:"f289dc7d9a1230c31c9e0fc7544a8ad0"},{url:"notes/cy-simulation.html",revision:"c1087df9c5adc4c8374e2411c7331ead"},{url:"notes/debug.html",revision:"eb4681ef7d14a224b64290a16bac8210"},{url:"notes/event-scheduling-en.html",revision:"5ac3b82266508eed1448ad8662ddafb3"},{url:"notes/event-scheduling.html",revision:"7367a34b5f885a47deab6e11f59a7c5d"},{url:"notes/index.html",revision:"f753fb653c733456fa446c071bb8fdf0"},{url:"notes/lp.html",revision:"a0cbcd40db9a650cbdae3ab88feabafe"},{url:"notes/lua.html",revision:"48762ce35d314f03f42c8f89cb054864"},{url:"notes/mip-en.html",revision:"55a92a21833f0dc50a313ef6eacadc05"},{url:"notes/mip.html",revision:"6567828fd786f0c1696fe09dc02c0639"},{url:"notes/network.html",revision:"bc2633a867e8eea8da23541b6d07d5ad"},{url:"notes/oop.html",revision:"e88b479cc1b4947014fb314be900e733"},{url:"notes/plots.html",revision:"c1ca6af908fc17826a13408a248e3943"},{url:"notes/timelapse.html",revision:"81270f4d58216846077730421233508d"},{url:"notes/tools.html",revision:"c77ad6c6c5797fc41ddbb0de6d72fea1"},{url:"notes/versions.html",revision:"3790516c8edc480d200979ea767c0b43"},{url:"notes/visualization.html",revision:"b05923335337842dc6d03cac617c2d20"},{url:"notes/warehouse-simulation.html",revision:"f8910b97a29643576e000667ee5805c6"},{url:"notes/web-ui-en.html",revision:"22d2d414438c6498e1a7875215c3b09e"},{url:"notes/web-ui.html",revision:"3ca0db04542a231792323d33208c8610"},{url:"assets/3trend-e8Vz-nOo.webp",revision:"62e6f891c43c490d73e9c40baced8bda"},{url:"assets/6-1trend-iFlvvd90.webp",revision:"77b688d0752c48c1d9ceaa7543f08116"},{url:"assets/6trend-tHF37BNC.webp",revision:"29a2a9741a7f5953bb3c394f3f70a644"},{url:"assets/AceEditor-8UZqygeG.png",revision:"d79c0c73bbf389f15e08dc2aa04f6c9d"},{url:"assets/AGV2-cOVBigXf.png",revision:"ac9d28e8b7f46a60dcdb8c430ac65a04"},{url:"assets/AGVQueueModel-VbkDUcno.png",revision:"5494bf4bbcee87a6d49427e6f32ff4b5"},{url:"assets/auto_test-ttcTMf95.webp",revision:"a32c2b274444d267076dfa6f94e6d63c"},{url:"assets/AutoTranslate-oqY-EbbE.png",revision:"7cd770336647da7598fe161fa99df301"},{url:"assets/Banner-O--M2FyY.png",revision:"4126c10b826d601e7ae4ef5e11c5a747"},{url:"assets/BottomBar-Il3Sa37D.gif",revision:"63e38d376fe4a371b8d97947b73fbd8c"},{url:"assets/box_lwh-6iD8r0MK.jpg",revision:"9c29ae29f4e3a90f4bbb1bc323488e6e"},{url:"assets/city_logistics-8RxmuTB1.png",revision:"f0e83dfc21b4da0afee21ec1645a5ce4"},{url:"assets/close_save_grid-mxdTfyrH.png",revision:"06823158f287c332e303ce9e74f119b1"},{url:"assets/close_save_shapes-bnfKINWq.png",revision:"6285144c1d85e6c8d7c12459ea8ecfa2"},{url:"assets/color5-PRdlG8aV.gif",revision:"7d57428b2e042e57250ff788e5214737"},{url:"assets/color8-KLKGFsL4.gif",revision:"7190cdbbc801e3598b39822c2f4449f1"},{url:"assets/CommandBar-Pu56Q_KU.png",revision:"48edae64a9b9429350f896d96e0d7af2"},{url:"assets/coordinate-KcPjAH3b.png",revision:"4696bfa608a3929ab8ffee4ed9da17f0"},{url:"assets/CY1-KhoqZKrQ.png",revision:"8fbbafb3f2d20b7b3542517162747e4b"},{url:"assets/CY2-uRljosmO.png",revision:"54659101f5e756f8d5ae99f230a325da"},{url:"assets/CYLayout-XevrzO6A.jpg",revision:"a83265003c673e906301a65be920056d"},{url:"assets/data_visualization-HBg0SLXW.png",revision:"bcf2333bc33ffde8b5f201e79ae4fb2b"},{url:"assets/DL_Heatmap-uiGWW-lH.png",revision:"5f26dd003befff9e1f6eb994197cf3ce"},{url:"assets/edit_point-krh9tqYD.png",revision:"b56499ca449e9cb42efa0ef5fe21aefd"},{url:"assets/edit_shape-3r72h2cB.png",revision:"5ee823e7cf71f04215c697036c15acb0"},{url:"assets/EventSchedulingRefresh-P9P75NgW.jpg",revision:"47874df6c7bd878c2a64d800de62e747"},{url:"assets/fixed_increment_advance-ufFIwQjw.png",revision:"20f2f4c8bbc3113184537da242398b9c"},{url:"assets/gis_data_structure-OyzSP1K_.png",revision:"77fa044dae581369badf8cb87d8e006c"},{url:"assets/GraduatedColorProperties-QL7AyCTd.png",revision:"acaa6f8e656886bcec42e74379e9eee5"},{url:"assets/GraduatedColorResult-c1P6KfFi.png",revision:"9869925032dbd7d448f4b1b60ab3c8a9"},{url:"assets/GraduatedColorSettings-sd7MRVbC.png",revision:"74ff570e2d95f95663e1565bb86a75e8"},{url:"assets/grid_attributes-e5wa0ZGb.png",revision:"99da94947795b278ee0bb4410dcf5e0e"},{url:"assets/grid_menu-7jPQkAi1.png",revision:"636dff6ad1216aa74de6214aba408e9f"},{url:"assets/grid_selection-bdt61Cd7.png",revision:"a854dc544ec5239818be6a245b4d558a"},{url:"assets/grid_structure-vhTlEgf-.png",revision:"4be1f0e0a70ddd24dfe875312edef079"},{url:"assets/Histogram-hCqM-8K4.png",revision:"b088afe8f4f8e21e5221a00aff8e6efd"},{url:"assets/LabelAttribProperties-BNSD9rBn.png",revision:"f95bfff89484f9f07ec316c996da5cf3"},{url:"assets/layer_menu-lHo367yT.png",revision:"55d3c08736142acc4245d482c2c0ce6a"},{url:"assets/LookupTableColor-VSXylHlz.png",revision:"af9601eb62ef3be4d01eb33f51a63661"},{url:"assets/LookupTableProperties-P0W9jYQE.png",revision:"16ab4c133ef51f5e9db60a401211c0da"},{url:"assets/main_window-kvL2HSJd.png",revision:"312ba4b6c91267ecef63c6ee00bc21e9"},{url:"assets/map_coordinates-8ybUOErD.png",revision:"c39aa1c8a4c3ed6e5b507f8cf3874160"},{url:"assets/map_menu-zU_XTli2.png",revision:"a95051447bc04efd2d5e706c872d3493"},{url:"assets/module_libraries_settings-lee40Qvj.png",revision:"bf0570b0b6130844d28fa3c402a27ffb"},{url:"assets/module_settings-3JBvpV80.png",revision:"ba28f8624752e27c514377e213ea642a"},{url:"assets/modules-cY5Kwc-8.png",revision:"55cea6ae301455d142cec78857a08aa9"},{url:"assets/new_grid-4i1mP770.png",revision:"cf382a920be3a7338877a71b78d66365"},{url:"assets/new_scene-8_vgmKnR.png",revision:"d5e69908016913fe08d8e00c90f6fb13"},{url:"assets/new_shapes-RVv9IgwR.png",revision:"36c06984f09ac60f8161c8d6aa860cf7"},{url:"assets/new_table-Elg2D_3m.png",revision:"89408a0284dd95c1421c0d5b4e6131f7"},{url:"assets/new-GF873AfJ.gif",revision:"aadcfac586760bc33926ca5ce7f02a9c"},{url:"assets/object_menu-rLYhy67y.png",revision:"eec516547d2a3ac027546ae348f4f054"},{url:"assets/old-FpQSFo63.gif",revision:"4080855b1419e2c04463cebd35711270"},{url:"assets/optimal_layout-bCy9JRge.webp",revision:"584a4e39d1b598fc7c4fb08653ba0477"},{url:"assets/PlotPrice1-QAaVF6hQ.png",revision:"2343fd9de1abdbbaf15f5413236f76fb"},{url:"assets/PlotPrice2-DeodiEK_.png",revision:"1a853fda82ea81fff7b44d65ba15346a"},{url:"assets/polygon_sizes-naWR0jXW.jpg",revision:"dc376be92b128dadabd35eace5ccee21"},{url:"assets/polylines_order-v8d3qUyG.jpg",revision:"31638de01c4de5ae632f20f1b6403fee"},{url:"assets/Preset_Earth-Tllgpkll.png",revision:"f55773fa09d457dd715992b6835564b7"},{url:"assets/Preset_Truck-ZFTcQbsO.png",revision:"a77828aa329b3c20d7cd8cb8696db5dd"},{url:"assets/Presets-dDpjg8aZ.png",revision:"26dee069587516d47812b816f671eac8"},{url:"assets/problem1-AJuFUHVQ.webp",revision:"c245c369ed623e8e388767d4f830afa3"},{url:"assets/problem2-KunKgJbC.webp",revision:"325bed85492b9881ea786baa7245e353"},{url:"assets/Q1Banner-BxB6kPmr.png",revision:"bc503822f53bcbca271785e032b28a45"},{url:"assets/Q1ContainerProcessFlow-t0XYjgJ-.png",revision:"13ba28ee1e19abc2be46756fe982d86a"},{url:"assets/Q2-hS2yYPEB.jpg",revision:"7d824da5c6d3a040b3f24a27ba42171a"},{url:"assets/Q2Layout-jXHR-iYn.png",revision:"419a6e710279298f56fa3405cb685e26"},{url:"assets/query_results-8DtTlPIZ.png",revision:"527d9a24621e0953478d8cd1224d973a"},{url:"assets/RangeDotRelateToMap-s6apr58V.png",revision:"503a9b2bb8e9a9106462e15478480baa"},{url:"assets/RelateToMapBig-co0riIjm.png",revision:"f0dd5026b6fa4bee47c155db6d44d822"},{url:"assets/RelateToMapSmall-8yIwZc0w.png",revision:"10945aba05b9286a9182b5957f15ef01"},{url:"assets/RelateToScreenBig-H3UhFI8t.png",revision:"2095d6f27c66191ed2f3a5c55e4e286f"},{url:"assets/RelateToScreenSmall-RgyFR_Ap.png",revision:"9bb544030d3ed11649649524ea8d4bb4"},{url:"assets/RMG-AGV-ProcessFlow-aQWltqys.png",revision:"4d7c0cb8ca470de4c7e17eb49394de69"},{url:"assets/RMG1-zXf9sSV8.png",revision:"f2362f6e69a941146929feef9262df73"},{url:"assets/RMG2-ea6huW81.png",revision:"18bc24c71d84d836806a35f090182811"},{url:"assets/RMGObjects-yrTAIJHV.png",revision:"22386c7fb35c3987fd9fe92090a08fe8"},{url:"assets/RMGQC2-BO9lyakQ.png",revision:"b179f5f2a4bc3d9043503617887201e8"},{url:"assets/RunCode-xHWq8U-i.gif",revision:"5f634a99c4fc97eea5525a02b8f51677"},{url:"assets/scene_coordinate-muj-oFBk.png",revision:"4a5134bd71717c44e496080a75478b39"},{url:"assets/scene_menu-RSZKJk7N.png",revision:"92664f67e27932c0d91c26ade6252378"},{url:"assets/script_editor-51w4xjN9.png",revision:"5cee3858ed9d28fd46d30d87477de338"},{url:"assets/segments-wNxhsxV0.jpg",revision:"adfe33d8ae64831aebeedec7a91a1f99"},{url:"assets/SelectLinksColor--zZDTT73.png",revision:"90ba31fd0a8532b3f841b39f898c8b7e"},{url:"assets/SetParameterProperties-m8LPKWT1.png",revision:"fdbc3e7d199a408b5526279c6d1c6474"},{url:"assets/shapes_files-ShfoHRZo.png",revision:"9a734a267477ee4d92b1cf39554bd4e2"},{url:"assets/shapes_menu-aime3jTY.png",revision:"1ce52bb22c77de1d9b138fac30adbf95"},{url:"assets/SHIP2-pz8IHA_0.png",revision:"f598e405a60027016fb59b8b3b3d195c"},{url:"assets/shipping_planning-_Mkxb6xn.png",revision:"73ff5ae946bc1b3408af6852a40f14b2"},{url:"assets/shot_parameter_id-ljNzzofT.png",revision:"c89a255188060a166f8890523d9596af"},{url:"assets/shot_script_editor-_OW8Kkrd.png",revision:"d7f18072054f41155cde343988a8a176"},{url:"assets/sim-result-nEPKqIkR.webp",revision:"4d4fb876261b1b2f812c26a2459287ce"},{url:"assets/SizeProperties-xZe9_-WE.png",revision:"0c1b64600f1cac883992d07661a4832d"},{url:"assets/Subplot_Vertical-X1t_RUlM.png",revision:"d0afcb66a5aeec2fd0b1fdbdc6426337"},{url:"assets/table_menu-enNFenIu.png",revision:"568acc7e16f0e89d9aab0846e6b37969"},{url:"assets/table_view_menu-1OnsnofR.png",revision:"a5b97ce1a8ed91d31c4fe571e0d5da4e"},{url:"assets/TableSelect-jKGsdf_N.png",revision:"a2f14a33f90021823a66786f4be84fae"},{url:"assets/terminal_simulation-rx4w_Kp0.gif",revision:"b2c8c2047ae16200788732a65d9d342a"},{url:"assets/test_layout-3LvNhD-0.webp",revision:"04e32d297a5182f881182b3b039c3680"},{url:"assets/warehouse_simulation-CPwzj5dU.gif",revision:"f62546662765fda4f41338846a1af6a6"},{url:"assets/WebUIOverview-NmRQvsO9.png",revision:"769241be4e6ed733ce783a4a7bd63443"},{url:"assets/WebUIParts-yq4WXR5p.png",revision:"411be83677e6ad958f5f7fb506ec1026"},{url:"assets/world_countries-K0FhRM3K.png",revision:"e850582792c99b09af68ca948e2aff8e"},{url:"assets/无预判障碍-p5itt-RJ.gif",revision:"6b6189014d83c82c480cd0dad1d3aec0"},{url:"assets/预判障碍-hw2PZ_-s.gif",revision:"8236b76fb86d617e815a12382aa2c140"},{url:"images/icon_microcity.png",revision:"08f31df45215c6018336c0acf1ff5e4d"},{url:"images/icon_microcitynotes.png",revision:"8fab94c045ebfa93980673848abc96b2"},{url:"images/icon/icon-144.png",revision:"06593bf0bb1b7646ed53c336be5ee07b"},{url:"images/icon/icon-192.png",revision:"dd4c61d0beacce8e965296d679fff0ca"},{url:"images/icon/icon-512.png",revision:"65e0e189f0e4f4fe72e6a6c47480c655"}],{}),e.cleanupOutdatedCaches()})); +if(!self.define){let e,s={};const a=(a,i)=>(a=new URL(a+".js",i).href,s[a]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()})).then((()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e})));self.define=(i,r)=>{const d=e||("document"in self?document.currentScript.src:"")||location.href;if(s[d])return;let c={};const f=e=>a(e,d),t={module:{uri:d},exports:c,require:f};s[d]=Promise.all(i.map((e=>t[e]||f(e)))).then((e=>(r(...e),c)))}}define(["./workbox-6db16f92"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.clientsClaim(),e.precacheAndRoute([{url:"assets/1.1_what_microcity_can_do.html-BudeEahj.js",revision:"cb0291f908ebf4dff4c593b7c388868e"},{url:"assets/1.1_what_microcity_can_do.html-HcIFtvfI.js",revision:"5feaea56c63e9e54f21f95c1ea973fa1"},{url:"assets/1.1_what_microcity_can_do.html-m1yQS0yR.js",revision:"202d178cfc2007b9e95f7f0ddceecaac"},{url:"assets/1.1_what_microcity_can_do.html-YHpuvmc-.js",revision:"3ab3c24555a0c9b7a1b54c2f195fae04"},{url:"assets/2.1_showing_a_world_map.html-6qnXe-uR.js",revision:"a08a857bb7a2e4a6fd683a7ea94e4c51"},{url:"assets/2.1_showing_a_world_map.html-F73HLlmh.js",revision:"8bf0eaa37a5339257a352112ba456d5c"},{url:"assets/2.1_showing_a_world_map.html-GZyM8T_I.js",revision:"630c976ef0d3555c323d68637ab1b734"},{url:"assets/2.1_showing_a_world_map.html-Ybz9X3FC.js",revision:"d39d69b8b91a8a678a8a1c4edcdef9d4"},{url:"assets/2.2_searching_for_countries.html-I1-AYfhY.js",revision:"3ca0380620c99d950fbd70aca8248cbe"},{url:"assets/2.2_searching_for_countries.html-OCp2-Zt6.js",revision:"681b9588dd2c743ffab021b93e57f49c"},{url:"assets/2.2_searching_for_countries.html-t7DQyHf7.js",revision:"66694b76e641e4857987e40bfca86266"},{url:"assets/2.2_searching_for_countries.html-Y0QCK0Nw.js",revision:"9874a64f07c3b4171103d6a0d549d678"},{url:"assets/3.1_ui_overview.html-3VU9Yk9s.js",revision:"843ceeaead657f1e475037551471b6d2"},{url:"assets/3.1_ui_overview.html-6J3N08CW.js",revision:"ebd7e07061ce2e93b8b35a2d2d2566e4"},{url:"assets/3.1_ui_overview.html-MdRgXeyu.js",revision:"a2fbfd91eb2fd7fd46674a8c13ada58d"},{url:"assets/3.1_ui_overview.html-v38UIHQc.js",revision:"2bdb9c693b83fb64b0b8e47af6edf94e"},{url:"assets/3.2_vector_shapes.html-Ggy6120F.js",revision:"0b9a7b956a4cd3fe26c59b1e6364002c"},{url:"assets/3.2_vector_shapes.html-hHGdBrtV.js",revision:"39c9bbb22eae7d20ce6b53458785f2a7"},{url:"assets/3.2_vector_shapes.html-o5HA4H30.js",revision:"1a93e013c29b95215275ed78f544021f"},{url:"assets/3.2_vector_shapes.html-uMTzJRD1.js",revision:"f0b9ccc940bc43c9eaaed7c1cb3d3363"},{url:"assets/3.3_raster_grids.html-_OMWjBic.js",revision:"e49369e12c65a091e5a7ff2bd42e2dcc"},{url:"assets/3.3_raster_grids.html-KMfHWMMp.js",revision:"1315c95fe419e5ded38aff3244321a47"},{url:"assets/3.3_raster_grids.html-OMCyU_6r.js",revision:"9298e0bc116b87de9e6a80b8700c46ba"},{url:"assets/3.3_raster_grids.html-t2xEoSZE.js",revision:"1a2449917bf1131929bfdca0f4df51c9"},{url:"assets/3.4_3d_scenes.html-2qe1Dffq.js",revision:"f1c3a668d1b2386da152ad51a7de868c"},{url:"assets/3.4_3d_scenes.html-E-00tpZF.js",revision:"f15e9b83ada3b9910a6afe6fdc59a318"},{url:"assets/3.4_3d_scenes.html-IfcyMMcw.js",revision:"62a22eacc8276445b1793572636f8510"},{url:"assets/3.4_3d_scenes.html-Q6eGIaTn.js",revision:"4d4c97efef0cdcdcd1030491549e0d13"},{url:"assets/3.5_tables.html-KMEBPMHz.js",revision:"576f04f4b3ce3be2b91a54f00266ff2a"},{url:"assets/3.5_tables.html-LpE0kpTR.js",revision:"f12b59a6605923c7fcba04f681272d09"},{url:"assets/3.5_tables.html-p1nKqUcK.js",revision:"6c573cdb51e696a8be5def3b4dafc58f"},{url:"assets/3.5_tables.html-rfKSY5-v.js",revision:"167c188f4300fc54671e63772a40f4da"},{url:"assets/3.6_maps_and_layers.html-IZMNuK0Y.js",revision:"cf43517de6e390f9bfa86bffe888427a"},{url:"assets/3.6_maps_and_layers.html-KNvuRdkG.js",revision:"96a0613891e2196f8d272fc1af9653e2"},{url:"assets/3.6_maps_and_layers.html-T_p6rWde.js",revision:"55e2ef5e5bacf9baa29d1fa7b05ab1a0"},{url:"assets/3.6_maps_and_layers.html-Zp7Na5N3.js",revision:"6479df3f21ee871bb4a5b118fae06309"},{url:"assets/3.7_modules.html-acS-BfiZ.js",revision:"f5e4bb2103fe19682c84dea7c9e9192f"},{url:"assets/3.7_modules.html-d3BG3VZc.js",revision:"027718608c542ae258a4536adfa9cd99"},{url:"assets/3.7_modules.html-mmRRzoSK.js",revision:"7c7d26e5f29a41b2273255d369fec6a3"},{url:"assets/3.7_modules.html-yzio17Ud.js",revision:"87e68594b9e0ccc50ccd9b89f11fddde"},{url:"assets/3d-objects.html-AEqGn78x.js",revision:"9f706206d96fe62920c59b49369f7532"},{url:"assets/3d-objects.html-frmlnhRb.js",revision:"79460193fd95ef858861a948b4d73fd3"},{url:"assets/3d-objects.html-jGytICR_.js",revision:"d5b0a215bd813a5d3a87308ef4d4f073"},{url:"assets/3d-objects.html-l7ht6tpD.js",revision:"c0b5fc7f1f5fc09476d4774196d56b2e"},{url:"assets/3d-scene.html-iJwBMXhE.js",revision:"8de4eb2b56ff653ac9109f342212191f"},{url:"assets/3d-scene.html-pmrdLLCG.js",revision:"f651b354357642c6b01635a46488276c"},{url:"assets/3d-scene.html-QeNNxNdQ.js",revision:"ac2f364be8b6f76d99c84350ec8dbb74"},{url:"assets/3d-scene.html-smFwVKZl.js",revision:"79bd8400b98b1802f4856de49f878e61"},{url:"assets/4.1_si_overview.html-3JNy66LR.js",revision:"bfd889632330ebcbc5d657ec496d2833"},{url:"assets/4.1_si_overview.html-aQjVZ38p.js",revision:"937ae5cdc486f1e73bb76e7613f40626"},{url:"assets/4.1_si_overview.html-mGhzJSIB.js",revision:"aac7651b53a30a6ffe5b891a5c20712e"},{url:"assets/4.1_si_overview.html-niv4qRLq.js",revision:"03b6d83b4bd33259b3d40a2200a90aa4"},{url:"assets/4.2_ui_control.html-it8dN_Kd.js",revision:"d3a6d2116d5afd8865baca6ee0ceaa69"},{url:"assets/4.2_ui_control.html-n4jA58yX.js",revision:"7608e8e218e4ca30ea085ce37ed01b3b"},{url:"assets/4.2_ui_control.html-qgHwWAaN.js",revision:"9c0339071c7f204f3425ec06b2d233fc"},{url:"assets/4.2_ui_control.html-Zsu36Eou.js",revision:"9a55c2948ff4b1e5d23e6087181d5e32"},{url:"assets/4.3_shapes_and_tables.html-9CbssTxf.js",revision:"0c2e6d17fa2542a0f359dc5d9b44da88"},{url:"assets/4.3_shapes_and_tables.html-Ix5omLFZ.js",revision:"100f9d7826261aa2d0939c5437dc5797"},{url:"assets/4.3_shapes_and_tables.html-SxckQf89.js",revision:"4094406db447a86d408ec0232d747be6"},{url:"assets/4.3_shapes_and_tables.html-TBHhEBxq.js",revision:"bc506d14389ed368a2851318d3a64d1d"},{url:"assets/4.4_grids.html-1OY5s52Z.js",revision:"b2dad7515a90e4c6b35572afe3daada0"},{url:"assets/4.4_grids.html-exxRQ7PN.js",revision:"1ed8a20a8f499d769208fbee67a72abc"},{url:"assets/4.4_grids.html-H6iZCbel.js",revision:"e1cd82f2ab18039b06fbb437f3cebee8"},{url:"assets/4.4_grids.html-JfxVQVat.js",revision:"7bb54a78f70d95f03eb83ad9619d5313"},{url:"assets/4.5_3d_scenes.html-I_su3OaS.js",revision:"3ff8fd95c4cf90205752840a29094bcb"},{url:"assets/4.5_3d_scenes.html-IYlmTIee.js",revision:"ee2648795f89d542acf61f94350a1116"},{url:"assets/4.5_3d_scenes.html-rRFZU4Tx.js",revision:"7335abb03b648309433bd1a260225f1c"},{url:"assets/4.5_3d_scenes.html-wmTORBrk.js",revision:"531a535c22fe8e549a7c3d536c79be15"},{url:"assets/4.6_networks.html-0YdpivDj.js",revision:"b27e00123f43da0995c58770eeab9f6b"},{url:"assets/4.6_networks.html-HJVUieG0.js",revision:"819df90cfac4b7e1a38ffd252053c88f"},{url:"assets/4.6_networks.html-kqO_isZV.js",revision:"89a4f98be45c03fb784b212114f4c646"},{url:"assets/4.6_networks.html-Z1GoybBX.js",revision:"b835fd7b2015c2144e40b23c7248fd08"},{url:"assets/4.7_des_simulations_zh.html-dVopgWmS.js",revision:"ff385f224575c8dff49da5b36f4cc0a6"},{url:"assets/4.7_des_simulations_zh.html-PYbnXFlK.js",revision:"85897bfb02a4bd5801eff4fe8905a956"},{url:"assets/4.7_des_simulations.html-Ie9zDG_n.js",revision:"c9a88484f8e21fb519faa53a4ed0b056"},{url:"assets/4.7_des_simulations.html-JlfYhUg2.js",revision:"a7892b80d467a4dd3324f1ea6381064a"},{url:"assets/4.7_des_simulations.html-W4OcSvr1.js",revision:"ed5377561cdc68b82babb03cc30364c8"},{url:"assets/4.7_des_simulations.html-WnzqINmi.js",revision:"f43cc11e4107ca429c70783ce70cf2e4"},{url:"assets/4.8_mixed_integer_programming.html-ixWGOETF.js",revision:"a5c12615e437e1739d6d7ea3ac909e0a"},{url:"assets/4.8_mixed_integer_programming.html-MExXnfeH.js",revision:"128634a14b4ac3d8e096a8fb6df46436"},{url:"assets/4.8_mixed_integer_programming.html-spXsyES8.js",revision:"5c8f511d999d56f26c500489c96d0667"},{url:"assets/4.8_mixed_integer_programming.html-TGfmzRJO.js",revision:"aaa1ac49a5767f35c2c9266e60ed24e2"},{url:"assets/404.html-O1A74s9P.js",revision:"d9d8bbe4476db75f55602a872936c43a"},{url:"assets/404.html-tJ8VjSOS.js",revision:"8c1c828efd6590cf001958bd2779f3e2"},{url:"assets/6-1trend-atJpgMOK.js",revision:"88c80d3213ed2759f43df19e5415c7e0"},{url:"assets/A2hs-LwmLJR8r.js",revision:"eb5177b4dd756facb4195b00a4856fee"},{url:"assets/add_field-ZFhY51wb.js",revision:"f3ae3d0717ce3f1b08575d9ab24fe7b4"},{url:"assets/app-LOf__QKq.js",revision:"0a251a62d29152943699be940ed07c83"},{url:"assets/AutoTranslate-DxMBsWAh.js",revision:"cdab077a6f396da2b7c8b2a2436c305a"},{url:"assets/button_3d-coWyniAs.js",revision:"b1d87c2188190dc8f9ad758ff3209930"},{url:"assets/button_action-tmG_4IgV.js",revision:"a45c2da3625b69f983ea2f3f250ed37f"},{url:"assets/button_load-GOP3K2yO.js",revision:"391a5543a75ec54a6c326b181f2841e4"},{url:"assets/button_ruler-TjPjykp6.js",revision:"85978e9104a2ffdc5bc0a70e57406a1a"},{url:"assets/CommandBar-jgj8yIQP.js",revision:"a9054c9490e70200bc2a4f8fdd523d63"},{url:"assets/coordinate-R7ZKfirG.js",revision:"141fa761610279516cdcbc64554f02a9"},{url:"assets/cy-simulation.html-0hk7J5DH.js",revision:"65f5231cce4d47ce35d44756fc38bf96"},{url:"assets/cy-simulation.html-5ddk20cl.js",revision:"bad1162346c50be9ab8d70fac2771250"},{url:"assets/cy-simulation.html-ms-pVG5v.js",revision:"8651dcbfc7ff3c0d1db1dbbd0fbdf093"},{url:"assets/cy-simulation.html-x04vq-Lr.js",revision:"af9211cc19a0aa821a21e8890d58ab9e"},{url:"assets/data_visualization-NDO9FqTF.js",revision:"747175bdc3a6382a86d95e8e2f2235d1"},{url:"assets/debug.html-80fcUM2q.js",revision:"9c7dca47d4443ca8ea19a7ed492ae2a4"},{url:"assets/debug.html-Pj0zKe-s.js",revision:"d227123d8f7af9df0e53cd3816c6925b"},{url:"assets/debug.html-vC47hElk.js",revision:"f300271cb8a897afcead571d139d5a5b"},{url:"assets/debug.html-YQ27enDU.js",revision:"7efea725a844e42c64fcd5100ede149b"},{url:"assets/DL_Heatmap-RXB-9ZZK.js",revision:"69db2faeab7d5948158145e27669982e"},{url:"assets/edit_point-Z0R1Z63o.js",revision:"9a9b8413c46df7b403983ec0cccde203"},{url:"assets/event-scheduling.html-_wHScoNu.js",revision:"9e54dea262d14b3c4c5866f3e6e6e6b7"},{url:"assets/event-scheduling.html-3ysZ_CTt.js",revision:"aeb11ee564034e31f390a8148156e1d0"},{url:"assets/event-scheduling.html-py4kt8T8.js",revision:"6ea888e991ba1e2f4ecd5426c7a1e7c8"},{url:"assets/event-scheduling.html-UZg_AtmL.js",revision:"fd097dad87d6a364a4b627ecff783b19"},{url:"assets/fixed_increment_advance-iwDvqivb.js",revision:"5e576c226069a2d9fcca516a02cba73a"},{url:"assets/flowchart-loQwkp6e.js",revision:"d0922e56732b0ff9f2eb72eccb4e7e36"},{url:"assets/giscus-unEZQsJ0.js",revision:"34c4288ad53e7d9be8d0f44c9fdba069"},{url:"assets/grid_attributes-xxRYXyrC.js",revision:"27ccac6184ab099332a5a65f4b4056d5"},{url:"assets/icon_microcity-Je85-7MO.js",revision:"0e7e05a07396d393fc7977851d9d6556"},{url:"assets/icon_module-AxwvBQMt.js",revision:"927274ea2b678bc32f744ed0e157301f"},{url:"assets/icon_script_editor-ibm_2NsU.js",revision:"2a9329638f5d3bdd769734a539f336b3"},{url:"assets/icon_shapes_polygon-5WS2EZQN.js",revision:"780fc09847b268c582be5334dce3ca5f"},{url:"assets/index-7SG8bi1h.js",revision:"46a193641571106d3b7b43f9bc2a2735"},{url:"assets/index.html-2U8qpeQG.js",revision:"44d28ad2eaebb766e081fc7c29547ba2"},{url:"assets/index.html-92lUUdK6.js",revision:"8e66d9798dbd7b640c897ffe75286ab5"},{url:"assets/index.html-a5Ef1Ykb.js",revision:"f0a2c2b05b8588a8598b875e8d5a04de"},{url:"assets/index.html-b5l2JDLj.js",revision:"4de6157b204bda32aa5e9517ff168de3"},{url:"assets/index.html-c3NKfYSn.js",revision:"c746eaadfbe5e364fac37f3fdf1a801d"},{url:"assets/index.html-dxC6HmKS.js",revision:"13b58b42e3af50fed344bae12418e7ec"},{url:"assets/index.html-hYpF9QHg.js",revision:"708211c37144e03ec8cc5e90f5ae9b3d"},{url:"assets/index.html-IqC-sAFX.js",revision:"032d58ef5aaceba33bc2117e5d4c6811"},{url:"assets/index.html-NfP7JmCD.js",revision:"584943a7a29ff400d5125e9fb79c0250"},{url:"assets/index.html-nYDcqjx5.js",revision:"eb23205e7c74cb68c8520a571f9bff00"},{url:"assets/index.html-rmW5MKDv.js",revision:"ad78aaabd131c2ec3b71d4b1c5ee57ef"},{url:"assets/index.html-WLZyFhZW.js",revision:"45f61925f979c983465618e8153fd670"},{url:"assets/index.html-WsgEQayQ.js",revision:"62893cdc20e0350d5f657f8207c717cf"},{url:"assets/index.html-YVKYSuDE.js",revision:"111256ef875c8db74ff3ba5b25af9e41"},{url:"assets/KaTeX_AMS-Regular-0YIAJWTb.ttf",revision:"56573229753fad48910bda2ea1a6dd54"},{url:"assets/KaTeX_AMS-Regular-UIXRTGNW.woff2",revision:"66c678209ce93b6e2b583f02ce41529e"},{url:"assets/KaTeX_AMS-Regular-zJvWDgGp.woff",revision:"10824af77e9961cfd548c8a458f10851"},{url:"assets/KaTeX_Caligraphic-Bold-6vyEfazt.woff2",revision:"a9e9b0953b078cd40f5e19ef4face6fc"},{url:"assets/KaTeX_Caligraphic-Bold-AE18XbF9.ttf",revision:"497bf407c4c609c6cf1f1ad38f437f7f"},{url:"assets/KaTeX_Caligraphic-Bold-RIlxi71x.woff",revision:"de2ba279933d60f7819ff61f71c17bed"},{url:"assets/KaTeX_Caligraphic-Regular-4uo0fsfh.woff2",revision:"08d95d99bf4a2b2dc7a876653857f154"},{url:"assets/KaTeX_Caligraphic-Regular-k0QPq0y-.woff",revision:"a25140fbe6692bffe71a2ab861572eb3"},{url:"assets/KaTeX_Caligraphic-Regular-MF_e1AYw.ttf",revision:"e6fb499fc8f9925eea3138cccba17fff"},{url:"assets/KaTeX_Fraktur-Bold-bAz-dThZ.woff",revision:"40934fc076960bb989d590db044fef62"},{url:"assets/KaTeX_Fraktur-Bold-i-oP291Y.woff2",revision:"796f3797cdf36fcaea18c3070a608378"},{url:"assets/KaTeX_Fraktur-Bold-XZxETTVq.ttf",revision:"b9d7c4497cab3702487214651ab03744"},{url:"assets/KaTeX_Fraktur-Regular-8XXOHEfX.woff",revision:"e435cda5784e21b26ab2d03fbcb56a99"},{url:"assets/KaTeX_Fraktur-Regular-gf8Lq3rE.ttf",revision:"97a699d83318e9334a0deaea6ae5eda2"},{url:"assets/KaTeX_Fraktur-Regular-k2IhepQP.woff2",revision:"f9e6a99f4a543b7d6cad1efb6cf1e4b1"},{url:"assets/KaTeX_Main-Bold-CZtwCMuf.woff",revision:"4cdba6465ab9fac5d3833c6cdba7a8c3"},{url:"assets/KaTeX_Main-Bold-MGqDlVzd.ttf",revision:"8e431f7ece346b6282dae3d9d0e7a970"},{url:"assets/KaTeX_Main-Bold-sffOiHVw.woff2",revision:"a9382e25bcf75d856718fcef54d7acdb"},{url:"assets/KaTeX_Main-BoldItalic-88TzJhul.ttf",revision:"52fb39b0434c463d5df32419608ab08a"},{url:"assets/KaTeX_Main-BoldItalic-8QydwDku.woff2",revision:"d873734390c716d6e18ff3f71ac6eb8b"},{url:"assets/KaTeX_Main-BoldItalic-EqUi0SPe.woff",revision:"5f875f986a9bce1264e8c42417b56f74"},{url:"assets/KaTeX_Main-Italic-DVgO3ulm.woff2",revision:"652970624cde999882102fa2b6a8871f"},{url:"assets/KaTeX_Main-Italic-N1npxqDf.ttf",revision:"39349e0a2b366f38e2672b45aded2030"},{url:"assets/KaTeX_Main-Italic-TCzgZvdR.woff",revision:"8ffd28f6390231548ead99d7835887fa"},{url:"assets/KaTeX_Main-Regular-6_eCWgYQ.woff",revision:"f1cdb692ee31c10b37262caffced5271"},{url:"assets/KaTeX_Main-Regular-dtjb4qKe.woff2",revision:"f8a7f19f45060f7a177314855b8c7aa3"},{url:"assets/KaTeX_Main-Regular-MqWbzbVV.ttf",revision:"818582dae57e6fac46202cfd844afabb"},{url:"assets/KaTeX_Math-BoldItalic-d10o37uD.ttf",revision:"6589c4f1f587f73f0ad0af8ae35ccb53"},{url:"assets/KaTeX_Math-BoldItalic-ImPtsMme.woff",revision:"48155e43d9a284b54753e50e4ba586dc"},{url:"assets/KaTeX_Math-BoldItalic-mZ7zbAmZ.woff2",revision:"1320454d951ec809a7dbccb4f23fccf0"},{url:"assets/KaTeX_Math-Italic-H5Tq_9FA.ttf",revision:"fe5ed5875d95b18c98546cb4f47304ff"},{url:"assets/KaTeX_Math-Italic-LedwBEzP.woff2",revision:"d8b7a801bd87b324efcbae7394119c24"},{url:"assets/KaTeX_Math-Italic-wNP_z16f.woff",revision:"ed7aea12d765f9e2d0f9bc7fa2be626c"},{url:"assets/KaTeX_SansSerif-Bold-2yISjogg.woff",revision:"0e897d27f063facef504667290e408bd"},{url:"assets/KaTeX_SansSerif-Bold-9bFEtBg9.woff2",revision:"ad546b4719bcf690a3604944b90b7e42"},{url:"assets/KaTeX_SansSerif-Bold-hTHqZ76u.ttf",revision:"f2ac73121357210d91e5c3eaa42f72ea"},{url:"assets/KaTeX_SansSerif-Italic-Azdo-3Wm.woff",revision:"ef725de572b71381dccf53918e300744"},{url:"assets/KaTeX_SansSerif-Italic-GGIydc0p.ttf",revision:"f60b4a34842bb524b562df092917a542"},{url:"assets/KaTeX_SansSerif-Italic-tx9FahgZ.woff2",revision:"e934cbc86e2d59ceaf04102c43dc0b50"},{url:"assets/KaTeX_SansSerif-Regular-kun6lKiW.woff",revision:"5f8637ee731482c44a37789723f5e499"},{url:"assets/KaTeX_SansSerif-Regular-TaO4USHJ.ttf",revision:"3243452ee6817acd761c9757aef93c29"},{url:"assets/KaTeX_SansSerif-Regular-wwQp5Se8.woff2",revision:"1ac3ed6ebe34e473519ca1da86f7a384"},{url:"assets/KaTeX_Script-Regular--ckFYqpa.woff",revision:"a82fa2a7e18b8c7a1a9f6069844ebfb9"},{url:"assets/KaTeX_Script-Regular-98CFnxev.woff2",revision:"1b3161eb8cc67462d6e8c2fb96c68507"},{url:"assets/KaTeX_Script-Regular-uSZBlqPg.ttf",revision:"a189c37d73ffce63464635dc12cbbc96"},{url:"assets/KaTeX_Size1-Regular-27J7nvyK.ttf",revision:"0d8d9204004bdf126342605f7bbdffe6"},{url:"assets/KaTeX_Size1-Regular-Jgg_JgPA.woff2",revision:"82ef26dc680ba60d884e051c73d9a42d"},{url:"assets/KaTeX_Size1-Regular-tfebZ-uE.woff",revision:"4788ba5b6247e336f734b742fe9900d5"},{url:"assets/KaTeX_Size2-Regular-8uHcfdJu.woff2",revision:"95a1da914c20455a07b7c9e2dcf2836d"},{url:"assets/KaTeX_Size2-Regular-e4ClFoQr.ttf",revision:"1fdda0e59ed35495ebac28badf210574"},{url:"assets/KaTeX_Size2-Regular-KA9bXP1N.woff",revision:"b0628bfd27c979a09f702a2277979888"},{url:"assets/KaTeX_Size3-Regular-4KV7NJM_.ttf",revision:"963af864cbb10611ba33267ba7953777"},{url:"assets/KaTeX_Size3-Regular-k6uTKqBB.woff",revision:"4de844d4552e941f6b9c38837a8d487b"},{url:"assets/KaTeX_Size4-Regular-1hQb9ONy.ttf",revision:"27a23ee69999affa55491c7dab8e53bf"},{url:"assets/KaTeX_Size4-Regular-5eZcWcVX.woff2",revision:"61522cd3d9043622e235ab57762754f2"},{url:"assets/KaTeX_Size4-Regular-RfuIJGSk.woff",revision:"3045a61f722bc4b198450ce69b3e3824"},{url:"assets/KaTeX_Typewriter-Regular-9yG-_x36.ttf",revision:"6bf4287568e1d3004b54d5d60f9f08f9"},{url:"assets/KaTeX_Typewriter-Regular-juq-IZ9c.woff2",revision:"b8b8393d2e65fcebda5fa99fa3264f41"},{url:"assets/KaTeX_Typewriter-Regular-tMUvZjwd.woff",revision:"0e0460587676d22eae09accd6dcfebc6"},{url:"assets/lp.html-BGRyuCz8.js",revision:"3a265b5cfa09260aa8942704e5127075"},{url:"assets/lp.html-jETCO9wn.js",revision:"9f096bd6a2d1b33dc54a5413a9fb397d"},{url:"assets/lp.html-m-tLdpGS.js",revision:"c4b7d8cf0bc8780d7ea7cebb05f84ec9"},{url:"assets/lp.html-yx0HpcA2.js",revision:"11b98a709d0610f21b1eb6f49a897792"},{url:"assets/lua.html--q1iToUD.js",revision:"4a3d46aaa2ec6e704a321a4461f9a98e"},{url:"assets/lua.html-B6d7gWD8.js",revision:"11bebdbdff9a6b1d61237f5cd9ca0ab8"},{url:"assets/lua.html-bIzYAnJl.js",revision:"6d0a776a5549503cb307cc3c6d1f9188"},{url:"assets/lua.html-JK5rP34K.js",revision:"4289d860b06cff328a1e4c2cac74f64e"},{url:"assets/main_window-T08x4hNs.js",revision:"5eb82c24899073c51b946042d26e8f90"},{url:"assets/mip.html-6_WAczY6.js",revision:"6b1d5c8e8ad85b21f6713ecfbe09f9c1"},{url:"assets/mip.html-7cWhLBPI.js",revision:"7cceedf63c0542f4b64270fa97604fda"},{url:"assets/mip.html-EzteSB1w.js",revision:"0677e0b87706c01acd076d2605c1b2eb"},{url:"assets/mip.html-KGIauE4D.js",revision:"1ea780376d6851b7632a2bee8008b95b"},{url:"assets/module_settings-yrsWXh8u.js",revision:"f8ceb5c301327d408638074b03e227bb"},{url:"assets/network.html-IGA5rLvk.js",revision:"96a9289c777bece65c2a725cc35dc7b5"},{url:"assets/network.html-l_dMxKkp.js",revision:"c1e111cecad392a885421af6236cb95e"},{url:"assets/network.html-qaPJNigq.js",revision:"cdb0781eb59abd20e7304093d48b8799"},{url:"assets/network.html-rimWgBRX.js",revision:"2ebc77fee693065bfe8970cc050c4f01"},{url:"assets/oop.html-GH4Nnww4.js",revision:"2ac4b390dfd30f89b825c1942eba252e"},{url:"assets/oop.html-lICjQDMc.js",revision:"d37c2cceb0f29bfb7cc84222185a93de"},{url:"assets/oop.html-QdhyUyOK.js",revision:"bc8e585d8ebf4e7dced2c9c226f2c870"},{url:"assets/oop.html-VmjZry6A.js",revision:"7175ef9b55c969395108326fc55e0fe1"},{url:"assets/play-RaBYbg3m.js",revision:"adf39fd68328cfe982d5295ce5926018"},{url:"assets/plots.html-6AeiZZxH.js",revision:"233f4285e55d8cbad4adbce51f31bc4f"},{url:"assets/plots.html-FPAlzRUf.js",revision:"f1952e5173c968b19885b485beb18d70"},{url:"assets/plots.html-KiXIG1Oc.js",revision:"230e8da33c475d0a33d7f37a0304d156"},{url:"assets/plots.html-wJZ2mJax.js",revision:"66e71a6e00747f679028b2d4dd8231f0"},{url:"assets/polygon_sizes-bVJYQmiT.js",revision:"bab1b960c9f3f02a8de0a0f0be67d603"},{url:"assets/query_results-qHjDevxa.js",revision:"882cbeda53166bdcd49dd1aba437c9c9"},{url:"assets/Result-All2-cnkq843b.js",revision:"4770b4e03c8d8a2593252d676dcf4fc3"},{url:"assets/RMGObjects-PwARz0cG.js",revision:"29b8111d5b33251f3a53e0df40a82998"},{url:"assets/scene_coordinate-_YCPy6or.js",revision:"c5601b3edca12d692074face1914877e"},{url:"assets/script_editor-a48-sxc_.js",revision:"63e0109cf04f75ce0a230708470063e2"},{url:"assets/SearchBox-dgLZwYTI.js",revision:"bbc654049bd99f0a4226f611c33ab1e9"},{url:"assets/shot_parameter_id-roH75mzn.js",revision:"568201b973f1a8c3e9176d721590e7c8"},{url:"assets/shot_script_editor-VtQOeIXC.js",revision:"7df2e03661e1ff595bb4ed632c42a094"},{url:"assets/style-gRAOaLx9.css",revision:"256c72c20e5fe4f6831f8a2a0af2c87d"},{url:"assets/Subplot_Vertical-oXTmfxKU.js",revision:"40d7da2ed5af97a8ec9335424dad1252"},{url:"assets/timelapse.html-ghI-6cF8.js",revision:"69dde21a74c47f8d3962fd16bcd77883"},{url:"assets/timelapse.html-rfk9Tyut.js",revision:"9bc479044e63fa5b4dd3f3abd852ceec"},{url:"assets/timelapse.html-VDhH9cuD.js",revision:"45da34b3a3d5df8efb9581c9a1386fb4"},{url:"assets/timelapse.html-xp-pHQoZ.js",revision:"bb50b2f975cefbb3811e30993f36a242"},{url:"assets/tools.html-hzuhyAmn.js",revision:"3b94baaf0c3990808c612f9ace58a967"},{url:"assets/tools.html-LamHaYH8.js",revision:"ebefc8b279438154be31832aa39052d8"},{url:"assets/tools.html-PgdIJCR5.js",revision:"09192719254574a47103da0bdab770aa"},{url:"assets/tools.html-Tsv49Nwb.js",revision:"c151431556daaea27e3371e752b9fec4"},{url:"assets/two_way-xpspXH9g.js",revision:"2cd3803c65e256bf09e1ddf4ff7e8062"},{url:"assets/versions.html-1Kk-C1xB.js",revision:"48b23a7082db416031bd2ecc29de550c"},{url:"assets/versions.html-8A5Y-n6r.js",revision:"2728dd80179be17e64c05d33b46937af"},{url:"assets/versions.html-aHfbE8Cr.js",revision:"4fc78361855a25f3e08c91f36c285ccc"},{url:"assets/versions.html-diw0opQu.js",revision:"df6607b064a88a3e812cc329c3838706"},{url:"assets/visualization.html-2T-VgKWL.js",revision:"a06d9bbc51d60588c369fa3b7666cab2"},{url:"assets/visualization.html-skftd09s.js",revision:"fa8701c02b839351cb3d2f762653a36d"},{url:"assets/visualization.html-t9WbOvdj.js",revision:"e067631efd36fa841a8080bbc9556a89"},{url:"assets/visualization.html-URi_NNx7.js",revision:"cae9f1a3a913e926704a718192eca887"},{url:"assets/warehouse-simulation.html-5OK9wBKc.js",revision:"933199aa20804da1948635e9a4eba07d"},{url:"assets/warehouse-simulation.html-6ARLBksA.js",revision:"be324e325ac9186d73b9ab885f837b61"},{url:"assets/warehouse-simulation.html-I2Ep6WY5.js",revision:"31cb326d0010bf05c5729a2172d4ed77"},{url:"assets/warehouse-simulation.html-rJTy601K.js",revision:"84e45e8f44bb85f4bcb9ce8378728727"},{url:"assets/web-ui.html--l1JvFq2.js",revision:"2240a75b2c3333aa892ef2b422b5976e"},{url:"assets/web-ui.html-gL6LgUwH.js",revision:"0b2b3ff3450a761cf7b8880152b8061f"},{url:"assets/web-ui.html-MXj0sqtU.js",revision:"55ecd9a02b74462a2a7c2a82d17a8fb9"},{url:"assets/web-ui.html-Ub-X1RXi.js",revision:"3585b3c869862feb36d7f957d76c38f1"},{url:"404.html",revision:"bc3de9040381a314a9a44eae34544783"},{url:"docs/1.1_what_microcity_can_do.html",revision:"44556d9f9852de335b7b7cb0876e7c36"},{url:"docs/2.1_showing_a_world_map.html",revision:"233c140d5cff4010bb8e88fac0d0733e"},{url:"docs/2.2_searching_for_countries.html",revision:"60bc52285c46955e0f95bebcebfb6844"},{url:"docs/3.1_ui_overview.html",revision:"756ad309de6d69d22bf5715eab983c85"},{url:"docs/3.2_vector_shapes.html",revision:"2afce4fd376b815a4ef99f14d99ce2a0"},{url:"docs/3.3_raster_grids.html",revision:"6d2adc7f6387260f68192a7b7c612ef0"},{url:"docs/3.4_3d_scenes.html",revision:"fe2d2bf023feb6d9c1048422530f873b"},{url:"docs/3.5_tables.html",revision:"40ed756e77437c2ebef6e78e09ac974b"},{url:"docs/3.6_maps_and_layers.html",revision:"3c7f369fdb7eb159cad7cdeb0ecddbce"},{url:"docs/3.7_modules.html",revision:"dd96308008e9c3fd5a98daa9dd4f51cd"},{url:"docs/4.1_si_overview.html",revision:"ea0b8f0c8777f38dba5c4264044d4bd4"},{url:"docs/4.2_ui_control.html",revision:"bea2bd3780084b88a9ede29c807cc01e"},{url:"docs/4.3_shapes_and_tables.html",revision:"1fed17ea11de6ede4c2b446f05982f36"},{url:"docs/4.4_grids.html",revision:"e1ee9671e75b863631c262e009ad47de"},{url:"docs/4.5_3d_scenes.html",revision:"2b60e1fdae8b9569a1b0f033a1cad669"},{url:"docs/4.6_networks.html",revision:"8588e4cfccf1d69020cea269ec1efab7"},{url:"docs/4.7_des_simulations.html",revision:"415d0d2c0d8828b4b0df0cdad3964aaa"},{url:"docs/4.8_mixed_integer_programming.html",revision:"5b546f232703e832d8b5aad69ddb516b"},{url:"docs/index.html",revision:"91166137fce78cb38f54da848e0c416d"},{url:"en/docs/1.1_what_microcity_can_do.html",revision:"b3cd1df50db2394cfbaee31dfc509fbe"},{url:"en/docs/2.1_showing_a_world_map.html",revision:"a7ab35f3a5960d0af94e3a31ed4a2393"},{url:"en/docs/2.2_searching_for_countries.html",revision:"9e9ee0386571e56ee3f9379f31717aac"},{url:"en/docs/3.1_ui_overview.html",revision:"64ed2a82c00df3ea41809ed9f2ea56f5"},{url:"en/docs/3.2_vector_shapes.html",revision:"50c42cfdc6a92727ce7527222876b20f"},{url:"en/docs/3.3_raster_grids.html",revision:"1149c66dcbecc59239c53d3a65d3dd96"},{url:"en/docs/3.4_3d_scenes.html",revision:"3b8d085ffb2d5ac58bd197e3c6b7f9f9"},{url:"en/docs/3.5_tables.html",revision:"a90b65fa025416da0451bc29e4ab827e"},{url:"en/docs/3.6_maps_and_layers.html",revision:"f446db113280cfd6e42bea756098ab48"},{url:"en/docs/3.7_modules.html",revision:"6fe7288119687eb1e9ec345ce2e852b5"},{url:"en/docs/4.1_si_overview.html",revision:"44f09b4121a9ca0799b2a2257817b892"},{url:"en/docs/4.2_ui_control.html",revision:"9737dd5bd69848fc88057ce740e2dcec"},{url:"en/docs/4.3_shapes_and_tables.html",revision:"1dddc05fd48050e42dd3475fbe51e280"},{url:"en/docs/4.4_grids.html",revision:"4ae5212624adb5b80e46276cfa33d90e"},{url:"en/docs/4.5_3d_scenes.html",revision:"9ccda0cac6187ad3ecd6c2729db2a50c"},{url:"en/docs/4.6_networks.html",revision:"39bed6416d0d66c50f5a09fadc88f3ae"},{url:"en/docs/4.7_des_simulations_zh.html",revision:"758bc971a8871118bc394cf3da465113"},{url:"en/docs/4.7_des_simulations.html",revision:"96c1ada309d08c1254fbdfe91ee654d9"},{url:"en/docs/4.8_mixed_integer_programming.html",revision:"abb015b0c3bb1a6782dc93a67b1941e9"},{url:"en/docs/index.html",revision:"e74a99b668c4ae9fce3aa5ff4b117354"},{url:"en/index.html",revision:"61ed29284b295405e20d788d9ddac730"},{url:"en/notes/3d-objects.html",revision:"cb5a4bcebaf919861b3c5a3180e99f91"},{url:"en/notes/3d-scene.html",revision:"43ce60a3b645f32038e20b3706df65a6"},{url:"en/notes/cy-simulation.html",revision:"4e4bd9d2d4efc2b0e7c9a5476e90c857"},{url:"en/notes/debug.html",revision:"8ce60b075cd93f03e35eb4beb44ec6ee"},{url:"en/notes/event-scheduling.html",revision:"ebb7cc4969eebc0c926d744501210ea1"},{url:"en/notes/index.html",revision:"0b14352630d58a5df66a14c5a1d54948"},{url:"en/notes/lp.html",revision:"09058a46d76c5f0cde65b194afab49f7"},{url:"en/notes/lua.html",revision:"db5a8ba7ba59896881330823434ef8b7"},{url:"en/notes/mip.html",revision:"cd1c8093227fbd2c1a9268766044ad3d"},{url:"en/notes/network.html",revision:"39cc7dbe977ad44542566994b64de6b8"},{url:"en/notes/oop.html",revision:"44a2dc4440e21af77e447e10897e58d5"},{url:"en/notes/plots.html",revision:"69c5a2e3cbf0771d9bc068e78ff8fe56"},{url:"en/notes/timelapse.html",revision:"1e33e84d38cbeb013c7acefe0e0c91ba"},{url:"en/notes/tools.html",revision:"e4596640f782fb5c911ea9981986c7db"},{url:"en/notes/versions.html",revision:"9cdeb6b4d08dc114a05d18a9b0008aaf"},{url:"en/notes/visualization.html",revision:"8d1809823d6d05325a73af40b2f328b9"},{url:"en/notes/warehouse-simulation.html",revision:"521b4859506a7233fbcea55b5d64d1c4"},{url:"en/notes/web-ui.html",revision:"0948814f24d6c84a1bcf7fb1f13cc46d"},{url:"google3a9084eedb90aa13.html",revision:"5fdd561cbfed9c1a090e11665147df61"},{url:"images/doc/index.html",revision:"29e5060ab03404e2752e031480aaa752"},{url:"index.html",revision:"61b9ca15447543c1b447d62d0f9b4c2f"},{url:"notes/3d-objects.html",revision:"1edf507a473cc6184bf8e40ff4811363"},{url:"notes/3d-scene.html",revision:"20d8717ade078ff9ac6facb7cce94c7d"},{url:"notes/cy-simulation.html",revision:"8cfb98500d408919eca2525f536038c1"},{url:"notes/debug.html",revision:"21dc4e82d4eeb7285d82031d65897107"},{url:"notes/event-scheduling.html",revision:"fe086942d711d55c33d50c8015eed623"},{url:"notes/index.html",revision:"402c0f56b90338cbb2f3331854b69896"},{url:"notes/lp.html",revision:"08968dfb67d4ee391875a4c7c273e5ea"},{url:"notes/lua.html",revision:"1df52b65739430baee7bd5b372caaad2"},{url:"notes/mip.html",revision:"ab967a79e9af05da0b23cec975a96505"},{url:"notes/network.html",revision:"fbe9482b4782f4b0071aaa8b4fac2ee2"},{url:"notes/oop.html",revision:"48152d7d0ffe59e9301be505c6cef0f2"},{url:"notes/plots.html",revision:"7423360f812e787a69062c504607a693"},{url:"notes/timelapse.html",revision:"6513074d9855269c9d6c0456fbdef2f1"},{url:"notes/tools.html",revision:"18ec4478be7b9dc9697c5108ee47b411"},{url:"notes/versions.html",revision:"2504a75f5a9cfd887571861b8d99fa5b"},{url:"notes/visualization.html",revision:"04163485af14e0f7c7ba1bd303426488"},{url:"notes/warehouse-simulation.html",revision:"a8e6203b3acecd846c317c04a5a27d85"},{url:"notes/web-ui.html",revision:"81fe5a832ea3abefd5843da2665c57bf"},{url:"assets/3trend-e8Vz-nOo.webp",revision:"62e6f891c43c490d73e9c40baced8bda"},{url:"assets/6-1trend-iFlvvd90.webp",revision:"77b688d0752c48c1d9ceaa7543f08116"},{url:"assets/6trend-tHF37BNC.webp",revision:"29a2a9741a7f5953bb3c394f3f70a644"},{url:"assets/AceEditor-8UZqygeG.png",revision:"d79c0c73bbf389f15e08dc2aa04f6c9d"},{url:"assets/AGV2-cOVBigXf.png",revision:"ac9d28e8b7f46a60dcdb8c430ac65a04"},{url:"assets/AGVQueueModel-VbkDUcno.png",revision:"5494bf4bbcee87a6d49427e6f32ff4b5"},{url:"assets/auto_test-ttcTMf95.webp",revision:"a32c2b274444d267076dfa6f94e6d63c"},{url:"assets/AutoTranslate-oqY-EbbE.png",revision:"7cd770336647da7598fe161fa99df301"},{url:"assets/Banner-O--M2FyY.png",revision:"4126c10b826d601e7ae4ef5e11c5a747"},{url:"assets/BottomBar-Il3Sa37D.gif",revision:"63e38d376fe4a371b8d97947b73fbd8c"},{url:"assets/box_lwh-6iD8r0MK.jpg",revision:"9c29ae29f4e3a90f4bbb1bc323488e6e"},{url:"assets/city_logistics-8RxmuTB1.png",revision:"f0e83dfc21b4da0afee21ec1645a5ce4"},{url:"assets/close_save_grid-mxdTfyrH.png",revision:"06823158f287c332e303ce9e74f119b1"},{url:"assets/close_save_shapes-bnfKINWq.png",revision:"6285144c1d85e6c8d7c12459ea8ecfa2"},{url:"assets/color5-PRdlG8aV.gif",revision:"7d57428b2e042e57250ff788e5214737"},{url:"assets/color8-KLKGFsL4.gif",revision:"7190cdbbc801e3598b39822c2f4449f1"},{url:"assets/CommandBar-Pu56Q_KU.png",revision:"48edae64a9b9429350f896d96e0d7af2"},{url:"assets/coordinate-KcPjAH3b.png",revision:"4696bfa608a3929ab8ffee4ed9da17f0"},{url:"assets/CY1-KhoqZKrQ.png",revision:"8fbbafb3f2d20b7b3542517162747e4b"},{url:"assets/CY2-uRljosmO.png",revision:"54659101f5e756f8d5ae99f230a325da"},{url:"assets/CYLayout-XevrzO6A.jpg",revision:"a83265003c673e906301a65be920056d"},{url:"assets/data_visualization-HBg0SLXW.png",revision:"bcf2333bc33ffde8b5f201e79ae4fb2b"},{url:"assets/DL_Heatmap-uiGWW-lH.png",revision:"5f26dd003befff9e1f6eb994197cf3ce"},{url:"assets/edit_point-krh9tqYD.png",revision:"b56499ca449e9cb42efa0ef5fe21aefd"},{url:"assets/edit_shape-3r72h2cB.png",revision:"5ee823e7cf71f04215c697036c15acb0"},{url:"assets/EventSchedulingRefresh-P9P75NgW.jpg",revision:"47874df6c7bd878c2a64d800de62e747"},{url:"assets/fixed_increment_advance-ufFIwQjw.png",revision:"20f2f4c8bbc3113184537da242398b9c"},{url:"assets/gis_data_structure-OyzSP1K_.png",revision:"77fa044dae581369badf8cb87d8e006c"},{url:"assets/GraduatedColorProperties-QL7AyCTd.png",revision:"acaa6f8e656886bcec42e74379e9eee5"},{url:"assets/GraduatedColorResult-c1P6KfFi.png",revision:"9869925032dbd7d448f4b1b60ab3c8a9"},{url:"assets/GraduatedColorSettings-sd7MRVbC.png",revision:"74ff570e2d95f95663e1565bb86a75e8"},{url:"assets/grid_attributes-e5wa0ZGb.png",revision:"99da94947795b278ee0bb4410dcf5e0e"},{url:"assets/grid_menu-7jPQkAi1.png",revision:"636dff6ad1216aa74de6214aba408e9f"},{url:"assets/grid_selection-bdt61Cd7.png",revision:"a854dc544ec5239818be6a245b4d558a"},{url:"assets/grid_structure-vhTlEgf-.png",revision:"4be1f0e0a70ddd24dfe875312edef079"},{url:"assets/Histogram-hCqM-8K4.png",revision:"b088afe8f4f8e21e5221a00aff8e6efd"},{url:"assets/LabelAttribProperties-BNSD9rBn.png",revision:"f95bfff89484f9f07ec316c996da5cf3"},{url:"assets/layer_menu-lHo367yT.png",revision:"55d3c08736142acc4245d482c2c0ce6a"},{url:"assets/LookupTableColor-VSXylHlz.png",revision:"af9601eb62ef3be4d01eb33f51a63661"},{url:"assets/LookupTableProperties-P0W9jYQE.png",revision:"16ab4c133ef51f5e9db60a401211c0da"},{url:"assets/main_window-kvL2HSJd.png",revision:"312ba4b6c91267ecef63c6ee00bc21e9"},{url:"assets/map_coordinates-8ybUOErD.png",revision:"c39aa1c8a4c3ed6e5b507f8cf3874160"},{url:"assets/map_menu-zU_XTli2.png",revision:"a95051447bc04efd2d5e706c872d3493"},{url:"assets/module_libraries_settings-lee40Qvj.png",revision:"bf0570b0b6130844d28fa3c402a27ffb"},{url:"assets/module_settings-3JBvpV80.png",revision:"ba28f8624752e27c514377e213ea642a"},{url:"assets/modules-cY5Kwc-8.png",revision:"55cea6ae301455d142cec78857a08aa9"},{url:"assets/new_grid-4i1mP770.png",revision:"cf382a920be3a7338877a71b78d66365"},{url:"assets/new_scene-8_vgmKnR.png",revision:"d5e69908016913fe08d8e00c90f6fb13"},{url:"assets/new_shapes-RVv9IgwR.png",revision:"36c06984f09ac60f8161c8d6aa860cf7"},{url:"assets/new_table-Elg2D_3m.png",revision:"89408a0284dd95c1421c0d5b4e6131f7"},{url:"assets/new-GF873AfJ.gif",revision:"aadcfac586760bc33926ca5ce7f02a9c"},{url:"assets/object_menu-rLYhy67y.png",revision:"eec516547d2a3ac027546ae348f4f054"},{url:"assets/old-FpQSFo63.gif",revision:"4080855b1419e2c04463cebd35711270"},{url:"assets/optimal_layout-bCy9JRge.webp",revision:"584a4e39d1b598fc7c4fb08653ba0477"},{url:"assets/PlotPrice1-QAaVF6hQ.png",revision:"2343fd9de1abdbbaf15f5413236f76fb"},{url:"assets/PlotPrice2-DeodiEK_.png",revision:"1a853fda82ea81fff7b44d65ba15346a"},{url:"assets/polygon_sizes-naWR0jXW.jpg",revision:"dc376be92b128dadabd35eace5ccee21"},{url:"assets/polylines_order-v8d3qUyG.jpg",revision:"31638de01c4de5ae632f20f1b6403fee"},{url:"assets/Preset_Earth-Tllgpkll.png",revision:"f55773fa09d457dd715992b6835564b7"},{url:"assets/Preset_Truck-ZFTcQbsO.png",revision:"a77828aa329b3c20d7cd8cb8696db5dd"},{url:"assets/Presets-dDpjg8aZ.png",revision:"26dee069587516d47812b816f671eac8"},{url:"assets/problem1-AJuFUHVQ.webp",revision:"c245c369ed623e8e388767d4f830afa3"},{url:"assets/problem2-KunKgJbC.webp",revision:"325bed85492b9881ea786baa7245e353"},{url:"assets/Q1Banner-BxB6kPmr.png",revision:"bc503822f53bcbca271785e032b28a45"},{url:"assets/Q1ContainerProcessFlow-t0XYjgJ-.png",revision:"13ba28ee1e19abc2be46756fe982d86a"},{url:"assets/Q2-hS2yYPEB.jpg",revision:"7d824da5c6d3a040b3f24a27ba42171a"},{url:"assets/Q2Layout-jXHR-iYn.png",revision:"419a6e710279298f56fa3405cb685e26"},{url:"assets/query_results-8DtTlPIZ.png",revision:"527d9a24621e0953478d8cd1224d973a"},{url:"assets/RangeDotRelateToMap-s6apr58V.png",revision:"503a9b2bb8e9a9106462e15478480baa"},{url:"assets/RelateToMapBig-co0riIjm.png",revision:"f0dd5026b6fa4bee47c155db6d44d822"},{url:"assets/RelateToMapSmall-8yIwZc0w.png",revision:"10945aba05b9286a9182b5957f15ef01"},{url:"assets/RelateToScreenBig-H3UhFI8t.png",revision:"2095d6f27c66191ed2f3a5c55e4e286f"},{url:"assets/RelateToScreenSmall-RgyFR_Ap.png",revision:"9bb544030d3ed11649649524ea8d4bb4"},{url:"assets/RMG-AGV-ProcessFlow-aQWltqys.png",revision:"4d7c0cb8ca470de4c7e17eb49394de69"},{url:"assets/RMG1-zXf9sSV8.png",revision:"f2362f6e69a941146929feef9262df73"},{url:"assets/RMG2-ea6huW81.png",revision:"18bc24c71d84d836806a35f090182811"},{url:"assets/RMGObjects-yrTAIJHV.png",revision:"22386c7fb35c3987fd9fe92090a08fe8"},{url:"assets/RMGQC2-BO9lyakQ.png",revision:"b179f5f2a4bc3d9043503617887201e8"},{url:"assets/RunCode-xHWq8U-i.gif",revision:"5f634a99c4fc97eea5525a02b8f51677"},{url:"assets/scene_coordinate-muj-oFBk.png",revision:"4a5134bd71717c44e496080a75478b39"},{url:"assets/scene_menu-RSZKJk7N.png",revision:"92664f67e27932c0d91c26ade6252378"},{url:"assets/script_editor-51w4xjN9.png",revision:"5cee3858ed9d28fd46d30d87477de338"},{url:"assets/segments-wNxhsxV0.jpg",revision:"adfe33d8ae64831aebeedec7a91a1f99"},{url:"assets/SelectLinksColor--zZDTT73.png",revision:"90ba31fd0a8532b3f841b39f898c8b7e"},{url:"assets/SetParameterProperties-m8LPKWT1.png",revision:"fdbc3e7d199a408b5526279c6d1c6474"},{url:"assets/shapes_files-ShfoHRZo.png",revision:"9a734a267477ee4d92b1cf39554bd4e2"},{url:"assets/shapes_menu-aime3jTY.png",revision:"1ce52bb22c77de1d9b138fac30adbf95"},{url:"assets/SHIP2-pz8IHA_0.png",revision:"f598e405a60027016fb59b8b3b3d195c"},{url:"assets/shipping_planning-_Mkxb6xn.png",revision:"73ff5ae946bc1b3408af6852a40f14b2"},{url:"assets/shot_parameter_id-ljNzzofT.png",revision:"c89a255188060a166f8890523d9596af"},{url:"assets/shot_script_editor-_OW8Kkrd.png",revision:"d7f18072054f41155cde343988a8a176"},{url:"assets/sim-result-nEPKqIkR.webp",revision:"4d4fb876261b1b2f812c26a2459287ce"},{url:"assets/SizeProperties-xZe9_-WE.png",revision:"0c1b64600f1cac883992d07661a4832d"},{url:"assets/Subplot_Vertical-X1t_RUlM.png",revision:"d0afcb66a5aeec2fd0b1fdbdc6426337"},{url:"assets/table_menu-enNFenIu.png",revision:"568acc7e16f0e89d9aab0846e6b37969"},{url:"assets/table_view_menu-1OnsnofR.png",revision:"a5b97ce1a8ed91d31c4fe571e0d5da4e"},{url:"assets/TableSelect-jKGsdf_N.png",revision:"a2f14a33f90021823a66786f4be84fae"},{url:"assets/terminal_simulation-rx4w_Kp0.gif",revision:"b2c8c2047ae16200788732a65d9d342a"},{url:"assets/test_layout-3LvNhD-0.webp",revision:"04e32d297a5182f881182b3b039c3680"},{url:"assets/warehouse_simulation-CPwzj5dU.gif",revision:"f62546662765fda4f41338846a1af6a6"},{url:"assets/WebUIOverview-NmRQvsO9.png",revision:"769241be4e6ed733ce783a4a7bd63443"},{url:"assets/WebUIParts-yq4WXR5p.png",revision:"411be83677e6ad958f5f7fb506ec1026"},{url:"assets/world_countries-K0FhRM3K.png",revision:"e850582792c99b09af68ca948e2aff8e"},{url:"assets/无预判障碍-p5itt-RJ.gif",revision:"6b6189014d83c82c480cd0dad1d3aec0"},{url:"assets/预判障碍-hw2PZ_-s.gif",revision:"8236b76fb86d617e815a12382aa2c140"},{url:"images/icon_microcity.png",revision:"08f31df45215c6018336c0acf1ff5e4d"},{url:"images/icon_microcitynotes.png",revision:"8fab94c045ebfa93980673848abc96b2"},{url:"images/icon/icon-144.png",revision:"06593bf0bb1b7646ed53c336be5ee07b"},{url:"images/icon/icon-192.png",revision:"dd4c61d0beacce8e965296d679fff0ca"},{url:"images/icon/icon-512.png",revision:"65e0e189f0e4f4fe72e6a6c47480c655"}],{}),e.cleanupOutdatedCaches()})); //# sourceMappingURL=service-worker.js.map diff --git a/service-worker.js.map b/service-worker.js.map index d077c279..d2b818cf 100644 --- a/service-worker.js.map +++ b/service-worker.js.map @@ -1 +1 @@ -{"version":3,"file":"service-worker.js","sources":["../../../../../tmp/62793fe141f46ee29db97d0dc7bddab6/service-worker.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/MicroCityNotes/MicroCityNotes/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/MicroCityNotes/MicroCityNotes/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/MicroCityNotes/MicroCityNotes/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\nworkbox_core_clientsClaim();\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"assets/1.1_what_microcity_can_do.html-FdnWldjW.js\",\n \"revision\": \"7344a33da1ce343e83d394182088de17\"\n },\n {\n \"url\": \"assets/1.1_what_microcity_can_do.html-XJqtRZkC.js\",\n \"revision\": \"0ab7378c0495d0df88d1b2bee90405ff\"\n },\n {\n \"url\": \"assets/2.1_showing_a_world_map.html-MkZfvyzh.js\",\n \"revision\": \"6876a1cbced2335017061c6faf8c56f8\"\n },\n {\n \"url\": \"assets/2.1_showing_a_world_map.html-nIk_uI4l.js\",\n \"revision\": \"d6e4ab1e690053e3944dab0c0973a9ca\"\n },\n {\n \"url\": \"assets/2.2_searching_for_countries.html-eO0KcF_W.js\",\n \"revision\": \"f8f96d4a976e48583e5343c3feb1aee7\"\n },\n {\n \"url\": \"assets/2.2_searching_for_countries.html-JlV76Wlp.js\",\n \"revision\": \"761f50b088c067219b2362a82794d7c6\"\n },\n {\n \"url\": \"assets/3.1_ui_overview.html-9iOHDqCk.js\",\n \"revision\": \"b5d49db3a3f5119a66560f69bf55d151\"\n },\n {\n \"url\": \"assets/3.1_ui_overview.html-w-bvZnF-.js\",\n \"revision\": \"6019c61ccafc14de13ccef35cddeb21b\"\n },\n {\n \"url\": \"assets/3.2_vector_shapes.html-Ifn-q5O4.js\",\n \"revision\": \"464e56896bb8a789a4d4fbd53ec4860e\"\n },\n {\n \"url\": \"assets/3.2_vector_shapes.html-LHAJ_5Cg.js\",\n \"revision\": \"d7bfa7d459fc73bdd06a7155c0097548\"\n },\n {\n \"url\": \"assets/3.3_raster_grids.html-RHwKcATS.js\",\n \"revision\": \"416f18073b6cb4ba294e1eb801ce5fab\"\n },\n {\n \"url\": \"assets/3.3_raster_grids.html-xKWq9pqo.js\",\n \"revision\": \"5edb00b8304d4ac6a38f925db92662cd\"\n },\n {\n \"url\": \"assets/3.4_3d_scenes.html-f5Qwa3ic.js\",\n \"revision\": \"a3da8c8beedf9fbe4355892967a84eba\"\n },\n {\n \"url\": \"assets/3.4_3d_scenes.html-SpQlhrPf.js\",\n \"revision\": \"b156765cc75d445563904375287def63\"\n },\n {\n \"url\": \"assets/3.5_tables.html-p-Cvt07d.js\",\n \"revision\": \"adb25e20fa218855c1df565a527dbaf6\"\n },\n {\n \"url\": \"assets/3.5_tables.html-zF8D9g8c.js\",\n \"revision\": \"11b1bbc88d8ef0b40f463ad1c8ca8ce3\"\n },\n {\n \"url\": \"assets/3.6_maps_and_layers.html-0HlObXq2.js\",\n \"revision\": \"66200e2565317e6a14498c0e9c7a43d4\"\n },\n {\n \"url\": \"assets/3.6_maps_and_layers.html-XuAmYobJ.js\",\n \"revision\": \"c91d1546445358d73abca7b793739cd4\"\n },\n {\n \"url\": \"assets/3.7_modules.html-heS1MNUm.js\",\n \"revision\": \"3b8c7fddeef042d26f70ccddf52a4e86\"\n },\n {\n \"url\": \"assets/3.7_modules.html-q0PqEjdM.js\",\n \"revision\": \"ab8c1c301741f7abd1071d3be7a15fb0\"\n },\n {\n \"url\": \"assets/3d-objects-en.html-7DC5k-lZ.js\",\n \"revision\": \"42b8960717d86c0fb63c26ae3cd42602\"\n },\n {\n \"url\": \"assets/3d-objects-en.html-rNfsYRE-.js\",\n \"revision\": \"c6af5c14e6807d2d8207da0aae1abef4\"\n },\n {\n \"url\": \"assets/3d-objects.html-0syC6c1Y.js\",\n \"revision\": \"766ccaf4ed05f3e1e4fe66066e29f35d\"\n },\n {\n \"url\": \"assets/3d-objects.html-lKAwFYq5.js\",\n \"revision\": \"b5b8a7991d443bfecddb17f6a5683ac3\"\n },\n {\n \"url\": \"assets/3d-scene-en.html-iUVl-UL0.js\",\n \"revision\": \"0ab99ddb72ddd6532cd1fd7c4b02aa55\"\n },\n {\n \"url\": \"assets/3d-scene-en.html-M1ONxEpk.js\",\n \"revision\": \"5aa5e17b956da78bb76fc694e79025ab\"\n },\n {\n \"url\": \"assets/3d-scene.html-_tzv6BUx.js\",\n \"revision\": \"d56951ddb0cc7d024b118f0888c6d56b\"\n },\n {\n \"url\": \"assets/3d-scene.html-A33RmZzw.js\",\n \"revision\": \"4317deb1a5513d262ea76b5459bac50d\"\n },\n {\n \"url\": \"assets/4.1_si_overview.html-iNqEh7u3.js\",\n \"revision\": \"feb6417dd656ee452976f5e53f3f298e\"\n },\n {\n \"url\": \"assets/4.1_si_overview.html-umQYu3pM.js\",\n \"revision\": \"02d2ef2ac8115b345d80c74d576436b3\"\n },\n {\n \"url\": \"assets/4.2_ui_control.html-P4QU671J.js\",\n \"revision\": \"e700b2ad44dfe0836ae6e8109910d9d8\"\n },\n {\n \"url\": \"assets/4.2_ui_control.html-PXdKdANV.js\",\n \"revision\": \"35790318273e3b5b5c2f410c563afb56\"\n },\n {\n \"url\": \"assets/4.3_shapes_and_tables.html-kM2JYXcO.js\",\n \"revision\": \"cc204711980e6ea90313152865922997\"\n },\n {\n \"url\": \"assets/4.3_shapes_and_tables.html-ujzvaZYV.js\",\n \"revision\": \"ed61b01ec19780188349dfd95daef44f\"\n },\n {\n \"url\": \"assets/4.4_grids.html-7i5R0Lmo.js\",\n \"revision\": \"6fc4056926277bcd713c390c876078d9\"\n },\n {\n \"url\": \"assets/4.4_grids.html-sbNpid1M.js\",\n \"revision\": \"c3b71f04c9bd5f0cde5524671710fcc8\"\n },\n {\n \"url\": \"assets/4.5_3d_scenes.html-2AMaq24g.js\",\n \"revision\": \"fa01e9e88a6a6f4e38ada3b478e680d5\"\n },\n {\n \"url\": \"assets/4.5_3d_scenes.html-FkF6l2hE.js\",\n \"revision\": \"d8976a7c4da55861764c001ea39bf482\"\n },\n {\n \"url\": \"assets/4.6_networks.html-O88jEbX0.js\",\n \"revision\": \"4fd7a53a6c44170f856c4a2afccb7a22\"\n },\n {\n \"url\": \"assets/4.6_networks.html-PK_mfd9Y.js\",\n \"revision\": \"1dc6eef3c4af226fe7f38b0a6d994e6f\"\n },\n {\n \"url\": \"assets/4.7_des_simulations.html-8bSUiGUz.js\",\n \"revision\": \"bd2a27922ac8e47d4fae24be7410863f\"\n },\n {\n \"url\": \"assets/4.7_des_simulations.html-Ztj4rB4B.js\",\n \"revision\": \"b422b32de1f64841ced212359926d055\"\n },\n {\n \"url\": \"assets/4.8_mixed_integer_programming.html-bEUkQ8el.js\",\n \"revision\": \"7ffa2a018a336ee7060aa9a589496f19\"\n },\n {\n \"url\": \"assets/4.8_mixed_integer_programming.html-E59_LnJJ.js\",\n \"revision\": \"f796daed751e4cb95e0a918635a085aa\"\n },\n {\n \"url\": \"assets/404.html-G5wmh19c.js\",\n \"revision\": \"d1c1345bc7f03c8bf1b4bddd811a571e\"\n },\n {\n \"url\": \"assets/404.html-O1A74s9P.js\",\n \"revision\": \"d9d8bbe4476db75f55602a872936c43a\"\n },\n {\n \"url\": \"assets/A2hs-xakqhU9I.js\",\n \"revision\": \"8645e2cec1595bb1fdd1a3fd04461178\"\n },\n {\n \"url\": \"assets/app-DaLjD81q.js\",\n \"revision\": \"616e01c7af55f7f65ad71269af7e69e1\"\n },\n {\n \"url\": \"assets/AutoTranslate-DxMBsWAh.js\",\n \"revision\": \"cdab077a6f396da2b7c8b2a2436c305a\"\n },\n {\n \"url\": \"assets/button_3d-coWyniAs.js\",\n \"revision\": \"b1d87c2188190dc8f9ad758ff3209930\"\n },\n {\n \"url\": \"assets/button_action-tmG_4IgV.js\",\n \"revision\": \"a45c2da3625b69f983ea2f3f250ed37f\"\n },\n {\n \"url\": \"assets/button_load-GOP3K2yO.js\",\n \"revision\": \"391a5543a75ec54a6c326b181f2841e4\"\n },\n {\n \"url\": \"assets/CommandBar-jgj8yIQP.js\",\n \"revision\": \"a9054c9490e70200bc2a4f8fdd523d63\"\n },\n {\n \"url\": \"assets/coordinate-R7ZKfirG.js\",\n \"revision\": \"141fa761610279516cdcbc64554f02a9\"\n },\n {\n \"url\": \"assets/cy-simulation.html-bcA0fx8Y.js\",\n \"revision\": \"bd77e66463d079c9698d0880e61dc5ee\"\n },\n {\n \"url\": \"assets/cy-simulation.html-YeLzi-Ut.js\",\n \"revision\": \"12534670508f0a24ca41eebeae5e6269\"\n },\n {\n \"url\": \"assets/debug.html-mpPtl8CL.js\",\n \"revision\": \"5cc4bb74570fc3ff1fa3404e5f168866\"\n },\n {\n \"url\": \"assets/debug.html-yFg7dMCo.js\",\n \"revision\": \"eb21819f5483a77bc21e0a0e1b06b765\"\n },\n {\n \"url\": \"assets/event-scheduling-en.html-gRProVKn.js\",\n \"revision\": \"f0bc586ec830d6353977e7f48297559a\"\n },\n {\n \"url\": \"assets/event-scheduling-en.html-gy_6i2Mu.js\",\n \"revision\": \"6f2854684011d84f59e12a9a685354c7\"\n },\n {\n \"url\": \"assets/event-scheduling.html-7ezvA1AX.js\",\n \"revision\": \"7c160ddbd2d30399ec12eed8a9d44de3\"\n },\n {\n \"url\": \"assets/event-scheduling.html-o4tYPrMB.js\",\n \"revision\": \"892130c78961166d5ff053f7f03f3112\"\n },\n {\n \"url\": \"assets/flowchart-loQwkp6e.js\",\n \"revision\": \"d0922e56732b0ff9f2eb72eccb4e7e36\"\n },\n {\n \"url\": \"assets/giscus-unEZQsJ0.js\",\n \"revision\": \"34c4288ad53e7d9be8d0f44c9fdba069\"\n },\n {\n \"url\": \"assets/icon_microcity-Je85-7MO.js\",\n \"revision\": \"0e7e05a07396d393fc7977851d9d6556\"\n },\n {\n \"url\": \"assets/icon_module-AxwvBQMt.js\",\n \"revision\": \"927274ea2b678bc32f744ed0e157301f\"\n },\n {\n \"url\": \"assets/icon_script_editor-ibm_2NsU.js\",\n \"revision\": \"2a9329638f5d3bdd769734a539f336b3\"\n },\n {\n \"url\": \"assets/icon_shapes_polygon-5WS2EZQN.js\",\n \"revision\": \"780fc09847b268c582be5334dce3ca5f\"\n },\n {\n \"url\": \"assets/index-7SG8bi1h.js\",\n \"revision\": \"46a193641571106d3b7b43f9bc2a2735\"\n },\n {\n \"url\": \"assets/index.html-8_XflqQA.js\",\n \"revision\": \"85ab13090c155db4e8e7e075bf0a495c\"\n },\n {\n \"url\": \"assets/index.html-ciQEBxId.js\",\n \"revision\": \"a3a26a5025e50ce083931f1d98d9b9cf\"\n },\n {\n \"url\": \"assets/index.html-hph7Dv3o.js\",\n \"revision\": \"e0173cc7b6b4369c18e2ed850ad7b5a3\"\n },\n {\n \"url\": \"assets/index.html-HwGLrUxL.js\",\n \"revision\": \"725e46b0abce3b136519f1f0e950ce11\"\n },\n {\n \"url\": \"assets/index.html-ijEhgMTC.js\",\n \"revision\": \"9f5fd939c5027d9494f5f4f1cd282973\"\n },\n {\n \"url\": \"assets/index.html-lZExp6Yz.js\",\n \"revision\": \"183ca6e222c60f27c3fdefd1793019dd\"\n },\n {\n \"url\": \"assets/index.html-nFm7KTWc.js\",\n \"revision\": \"3db036f82763891587e590de9a10f2d2\"\n },\n {\n \"url\": \"assets/index.html-ps9YKXkA.js\",\n \"revision\": \"d34b9b5e9f4dfa2056862771068d2add\"\n },\n {\n \"url\": \"assets/KaTeX_AMS-Regular-0YIAJWTb.ttf\",\n \"revision\": \"56573229753fad48910bda2ea1a6dd54\"\n },\n {\n \"url\": \"assets/KaTeX_AMS-Regular-UIXRTGNW.woff2\",\n \"revision\": \"66c678209ce93b6e2b583f02ce41529e\"\n },\n {\n \"url\": \"assets/KaTeX_AMS-Regular-zJvWDgGp.woff\",\n \"revision\": \"10824af77e9961cfd548c8a458f10851\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Bold-6vyEfazt.woff2\",\n \"revision\": \"a9e9b0953b078cd40f5e19ef4face6fc\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Bold-AE18XbF9.ttf\",\n \"revision\": \"497bf407c4c609c6cf1f1ad38f437f7f\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Bold-RIlxi71x.woff\",\n \"revision\": \"de2ba279933d60f7819ff61f71c17bed\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Regular-4uo0fsfh.woff2\",\n \"revision\": \"08d95d99bf4a2b2dc7a876653857f154\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Regular-k0QPq0y-.woff\",\n \"revision\": \"a25140fbe6692bffe71a2ab861572eb3\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Regular-MF_e1AYw.ttf\",\n \"revision\": \"e6fb499fc8f9925eea3138cccba17fff\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Bold-bAz-dThZ.woff\",\n \"revision\": \"40934fc076960bb989d590db044fef62\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Bold-i-oP291Y.woff2\",\n \"revision\": \"796f3797cdf36fcaea18c3070a608378\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Bold-XZxETTVq.ttf\",\n \"revision\": \"b9d7c4497cab3702487214651ab03744\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Regular-8XXOHEfX.woff\",\n \"revision\": \"e435cda5784e21b26ab2d03fbcb56a99\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Regular-gf8Lq3rE.ttf\",\n \"revision\": \"97a699d83318e9334a0deaea6ae5eda2\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Regular-k2IhepQP.woff2\",\n \"revision\": \"f9e6a99f4a543b7d6cad1efb6cf1e4b1\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Bold-CZtwCMuf.woff\",\n \"revision\": \"4cdba6465ab9fac5d3833c6cdba7a8c3\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Bold-MGqDlVzd.ttf\",\n \"revision\": \"8e431f7ece346b6282dae3d9d0e7a970\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Bold-sffOiHVw.woff2\",\n \"revision\": \"a9382e25bcf75d856718fcef54d7acdb\"\n },\n {\n \"url\": \"assets/KaTeX_Main-BoldItalic-88TzJhul.ttf\",\n \"revision\": \"52fb39b0434c463d5df32419608ab08a\"\n },\n {\n \"url\": \"assets/KaTeX_Main-BoldItalic-8QydwDku.woff2\",\n \"revision\": \"d873734390c716d6e18ff3f71ac6eb8b\"\n },\n {\n \"url\": \"assets/KaTeX_Main-BoldItalic-EqUi0SPe.woff\",\n \"revision\": \"5f875f986a9bce1264e8c42417b56f74\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Italic-DVgO3ulm.woff2\",\n \"revision\": \"652970624cde999882102fa2b6a8871f\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Italic-N1npxqDf.ttf\",\n \"revision\": \"39349e0a2b366f38e2672b45aded2030\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Italic-TCzgZvdR.woff\",\n \"revision\": \"8ffd28f6390231548ead99d7835887fa\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Regular-6_eCWgYQ.woff\",\n \"revision\": \"f1cdb692ee31c10b37262caffced5271\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Regular-dtjb4qKe.woff2\",\n \"revision\": \"f8a7f19f45060f7a177314855b8c7aa3\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Regular-MqWbzbVV.ttf\",\n \"revision\": \"818582dae57e6fac46202cfd844afabb\"\n },\n {\n \"url\": \"assets/KaTeX_Math-BoldItalic-d10o37uD.ttf\",\n \"revision\": \"6589c4f1f587f73f0ad0af8ae35ccb53\"\n },\n {\n \"url\": \"assets/KaTeX_Math-BoldItalic-ImPtsMme.woff\",\n \"revision\": \"48155e43d9a284b54753e50e4ba586dc\"\n },\n {\n \"url\": \"assets/KaTeX_Math-BoldItalic-mZ7zbAmZ.woff2\",\n \"revision\": \"1320454d951ec809a7dbccb4f23fccf0\"\n },\n {\n \"url\": \"assets/KaTeX_Math-Italic-H5Tq_9FA.ttf\",\n \"revision\": \"fe5ed5875d95b18c98546cb4f47304ff\"\n },\n {\n \"url\": \"assets/KaTeX_Math-Italic-LedwBEzP.woff2\",\n \"revision\": \"d8b7a801bd87b324efcbae7394119c24\"\n },\n {\n \"url\": \"assets/KaTeX_Math-Italic-wNP_z16f.woff\",\n \"revision\": \"ed7aea12d765f9e2d0f9bc7fa2be626c\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Bold-2yISjogg.woff\",\n \"revision\": \"0e897d27f063facef504667290e408bd\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Bold-9bFEtBg9.woff2\",\n \"revision\": \"ad546b4719bcf690a3604944b90b7e42\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Bold-hTHqZ76u.ttf\",\n \"revision\": \"f2ac73121357210d91e5c3eaa42f72ea\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Italic-Azdo-3Wm.woff\",\n \"revision\": \"ef725de572b71381dccf53918e300744\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Italic-GGIydc0p.ttf\",\n \"revision\": \"f60b4a34842bb524b562df092917a542\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Italic-tx9FahgZ.woff2\",\n \"revision\": \"e934cbc86e2d59ceaf04102c43dc0b50\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Regular-kun6lKiW.woff\",\n \"revision\": \"5f8637ee731482c44a37789723f5e499\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Regular-TaO4USHJ.ttf\",\n \"revision\": \"3243452ee6817acd761c9757aef93c29\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Regular-wwQp5Se8.woff2\",\n \"revision\": \"1ac3ed6ebe34e473519ca1da86f7a384\"\n },\n {\n \"url\": \"assets/KaTeX_Script-Regular--ckFYqpa.woff\",\n \"revision\": \"a82fa2a7e18b8c7a1a9f6069844ebfb9\"\n },\n {\n \"url\": \"assets/KaTeX_Script-Regular-98CFnxev.woff2\",\n \"revision\": \"1b3161eb8cc67462d6e8c2fb96c68507\"\n },\n {\n \"url\": \"assets/KaTeX_Script-Regular-uSZBlqPg.ttf\",\n \"revision\": \"a189c37d73ffce63464635dc12cbbc96\"\n },\n {\n \"url\": \"assets/KaTeX_Size1-Regular-27J7nvyK.ttf\",\n \"revision\": \"0d8d9204004bdf126342605f7bbdffe6\"\n },\n {\n \"url\": \"assets/KaTeX_Size1-Regular-Jgg_JgPA.woff2\",\n \"revision\": \"82ef26dc680ba60d884e051c73d9a42d\"\n },\n {\n \"url\": \"assets/KaTeX_Size1-Regular-tfebZ-uE.woff\",\n \"revision\": \"4788ba5b6247e336f734b742fe9900d5\"\n },\n {\n \"url\": \"assets/KaTeX_Size2-Regular-8uHcfdJu.woff2\",\n \"revision\": \"95a1da914c20455a07b7c9e2dcf2836d\"\n },\n {\n \"url\": \"assets/KaTeX_Size2-Regular-e4ClFoQr.ttf\",\n \"revision\": \"1fdda0e59ed35495ebac28badf210574\"\n },\n {\n \"url\": \"assets/KaTeX_Size2-Regular-KA9bXP1N.woff\",\n \"revision\": \"b0628bfd27c979a09f702a2277979888\"\n },\n {\n \"url\": \"assets/KaTeX_Size3-Regular-4KV7NJM_.ttf\",\n \"revision\": \"963af864cbb10611ba33267ba7953777\"\n },\n {\n \"url\": \"assets/KaTeX_Size3-Regular-k6uTKqBB.woff\",\n \"revision\": \"4de844d4552e941f6b9c38837a8d487b\"\n },\n {\n \"url\": \"assets/KaTeX_Size4-Regular-1hQb9ONy.ttf\",\n \"revision\": \"27a23ee69999affa55491c7dab8e53bf\"\n },\n {\n \"url\": \"assets/KaTeX_Size4-Regular-5eZcWcVX.woff2\",\n \"revision\": \"61522cd3d9043622e235ab57762754f2\"\n },\n {\n \"url\": \"assets/KaTeX_Size4-Regular-RfuIJGSk.woff\",\n \"revision\": \"3045a61f722bc4b198450ce69b3e3824\"\n },\n {\n \"url\": \"assets/KaTeX_Typewriter-Regular-9yG-_x36.ttf\",\n \"revision\": \"6bf4287568e1d3004b54d5d60f9f08f9\"\n },\n {\n \"url\": \"assets/KaTeX_Typewriter-Regular-juq-IZ9c.woff2\",\n \"revision\": \"b8b8393d2e65fcebda5fa99fa3264f41\"\n },\n {\n \"url\": \"assets/KaTeX_Typewriter-Regular-tMUvZjwd.woff\",\n \"revision\": \"0e0460587676d22eae09accd6dcfebc6\"\n },\n {\n \"url\": \"assets/lp.html-I7wRJlfF.js\",\n \"revision\": \"73e78f76ccf3e544d1815ae6c4be0268\"\n },\n {\n \"url\": \"assets/lp.html-NKzjcq8T.js\",\n \"revision\": \"e469607be84d2c72afb35c12c8c36b7b\"\n },\n {\n \"url\": \"assets/lua.html-x5twFLDp.js\",\n \"revision\": \"986e735f4b44488517237f02812d7f26\"\n },\n {\n \"url\": \"assets/lua.html-zCkaxI4j.js\",\n \"revision\": \"f4c31548b9d4451b270e33c3d520a72f\"\n },\n {\n \"url\": \"assets/mip-en.html-23DYx6JR.js\",\n \"revision\": \"c387d933a956b9ca4c9d45147933bedf\"\n },\n {\n \"url\": \"assets/mip-en.html-IS2AhQjv.js\",\n \"revision\": \"22df9ba494886c5b7612429629e435fe\"\n },\n {\n \"url\": \"assets/mip.html-B6IhijhB.js\",\n \"revision\": \"8fbc56f876e3cfa84f97c76386b20408\"\n },\n {\n \"url\": \"assets/mip.html-Jt_OOSuJ.js\",\n \"revision\": \"a244a41f6081ef8afe6805942d8bb049\"\n },\n {\n \"url\": \"assets/network.html-m23VzkXJ.js\",\n \"revision\": \"301fd7cb2b71676ab9a598d87c3235fb\"\n },\n {\n \"url\": \"assets/network.html-td-Kb3D8.js\",\n \"revision\": \"5a35c481d99eb07566b6e593c22e90ab\"\n },\n {\n \"url\": \"assets/oop.html-3LUP3-Yz.js\",\n \"revision\": \"74008a05fa1e374820db98ffd4291119\"\n },\n {\n \"url\": \"assets/oop.html-azlXcYwP.js\",\n \"revision\": \"9254b3b86ba10479af96ca199cea9b89\"\n },\n {\n \"url\": \"assets/plots.html-JiB_VWcB.js\",\n \"revision\": \"a2ce12dc052a1510fb6e8e63019a8531\"\n },\n {\n \"url\": \"assets/plots.html-ODP8nuzQ.js\",\n \"revision\": \"989ad3b461d29fb59dda4515dbb80d33\"\n },\n {\n \"url\": \"assets/polygon_sizes-bVJYQmiT.js\",\n \"revision\": \"bab1b960c9f3f02a8de0a0f0be67d603\"\n },\n {\n \"url\": \"assets/SearchBox-cTU2Stp4.js\",\n \"revision\": \"ae3f72117b33e33ce436da5c97928579\"\n },\n {\n \"url\": \"assets/style-gRAOaLx9.css\",\n \"revision\": \"256c72c20e5fe4f6831f8a2a0af2c87d\"\n },\n {\n \"url\": \"assets/timelapse.html-hdyuE7Lk.js\",\n \"revision\": \"1d0e9843035bc3656d961901023e5cae\"\n },\n {\n \"url\": \"assets/timelapse.html-mpQRHhbv.js\",\n \"revision\": \"0e1e78a1eff5754faf8f0e600a843d22\"\n },\n {\n \"url\": \"assets/tools.html-kWg64VtA.js\",\n \"revision\": \"6e9453fbc21afe4906a14f2681717e00\"\n },\n {\n \"url\": \"assets/tools.html-zf97O5Kc.js\",\n \"revision\": \"bc284426edc777de344faaa30fbba52a\"\n },\n {\n \"url\": \"assets/versions.html-9uZsLBnu.js\",\n \"revision\": \"77a821c48d5cb3c9eec77f0705aa75d9\"\n },\n {\n \"url\": \"assets/versions.html-HjNHjtrH.js\",\n \"revision\": \"ef57ae6a5e3557acf10ca9deba3dce56\"\n },\n {\n \"url\": \"assets/visualization.html--w3hFG24.js\",\n \"revision\": \"441c692190d7274db6c5b8c38a7de5d2\"\n },\n {\n \"url\": \"assets/visualization.html-xF8N-_EY.js\",\n \"revision\": \"546940ef4c0a29e36d90973137ccbd49\"\n },\n {\n \"url\": \"assets/warehouse-simulation.html-3NwF3MxT.js\",\n \"revision\": \"19335076774294adfc8748752315ed91\"\n },\n {\n \"url\": \"assets/warehouse-simulation.html-GfcmApNM.js\",\n \"revision\": \"a3cc462c1483cc228f0a048d1ba532c6\"\n },\n {\n \"url\": \"assets/web-ui-en.html-9hWYZBEN.js\",\n \"revision\": \"a0b47462faa918f2795e57ecaa4eaa95\"\n },\n {\n \"url\": \"assets/web-ui-en.html-FPAIksJ9.js\",\n \"revision\": \"1a324ae30026932aea1cb0d97a0151ea\"\n },\n {\n \"url\": \"assets/web-ui.html-cjOV8UTz.js\",\n \"revision\": \"d251b838391b3194f56974bab2a347e6\"\n },\n {\n \"url\": \"assets/web-ui.html-zrAeLt4a.js\",\n \"revision\": \"01c1accc3a425a63329dacd4423fe788\"\n },\n {\n \"url\": \"404.html\",\n \"revision\": \"dd7866e72fc3f4d299abfd27946d3b85\"\n },\n {\n \"url\": \"docs/1.1_what_microcity_can_do.html\",\n \"revision\": \"b76f00c02a1128b742eb12818f928372\"\n },\n {\n \"url\": \"docs/2.1_showing_a_world_map.html\",\n \"revision\": \"e64941f12c26314cb02bf7a1e175676b\"\n },\n {\n \"url\": \"docs/2.2_searching_for_countries.html\",\n \"revision\": \"bef8e41517ea71b7a1edb12f46c75840\"\n },\n {\n \"url\": \"docs/3.1_ui_overview.html\",\n \"revision\": \"685c833c837a5188afa532dfa2584c4b\"\n },\n {\n \"url\": \"docs/3.2_vector_shapes.html\",\n \"revision\": \"456a4a413f8017eb4e257c5aa908211f\"\n },\n {\n \"url\": \"docs/3.3_raster_grids.html\",\n \"revision\": \"0c62cda412d0eaaec2f6d20ebf0a3ee0\"\n },\n {\n \"url\": \"docs/3.4_3d_scenes.html\",\n \"revision\": \"85cc759550c82a4fe461884e3f637c1f\"\n },\n {\n \"url\": \"docs/3.5_tables.html\",\n \"revision\": \"cade86c3bcf15c8b70cd5122d405c55c\"\n },\n {\n \"url\": \"docs/3.6_maps_and_layers.html\",\n \"revision\": \"0a9c3b29e9ae13ec4e11ed239efa2ae8\"\n },\n {\n \"url\": \"docs/3.7_modules.html\",\n \"revision\": \"70d1c6f7cef8d5df9b3e891577d27e17\"\n },\n {\n \"url\": \"docs/4.1_si_overview.html\",\n \"revision\": \"4a2c4951c208582aeddb778eb29f9c00\"\n },\n {\n \"url\": \"docs/4.2_ui_control.html\",\n \"revision\": \"c890b080d1e524fbb88bf478adae5070\"\n },\n {\n \"url\": \"docs/4.3_shapes_and_tables.html\",\n \"revision\": \"42aa4081f6f75e297e2b941eaafbd956\"\n },\n {\n \"url\": \"docs/4.4_grids.html\",\n \"revision\": \"312a11f10d238f18f863ea704a73f645\"\n },\n {\n \"url\": \"docs/4.5_3d_scenes.html\",\n \"revision\": \"904acbefb1fd6586a755e66199049eec\"\n },\n {\n \"url\": \"docs/4.6_networks.html\",\n \"revision\": \"355c830511fc1efec74761ce1e28480c\"\n },\n {\n \"url\": \"docs/4.7_des_simulations.html\",\n \"revision\": \"9ae752a8d844a6aaac3466eb0a513dfd\"\n },\n {\n \"url\": \"docs/4.8_mixed_integer_programming.html\",\n \"revision\": \"18b2d41ae0395859fb577b930b36ddde\"\n },\n {\n \"url\": \"docs/imgs/index.html\",\n \"revision\": \"98b03fe69260b6a020bde822b1091595\"\n },\n {\n \"url\": \"docs/index.html\",\n \"revision\": \"305fdfb377346acf0985b0e86a8c1318\"\n },\n {\n \"url\": \"google3a9084eedb90aa13.html\",\n \"revision\": \"5fdd561cbfed9c1a090e11665147df61\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"5a7a6298a6bcdd90070640b79dcd4623\"\n },\n {\n \"url\": \"notes/3d-objects-en.html\",\n \"revision\": \"c9cffc498d111b3f7736f10b1c5b2572\"\n },\n {\n \"url\": \"notes/3d-objects.html\",\n \"revision\": \"1dfea4089f4636a823efa1f96943dd27\"\n },\n {\n \"url\": \"notes/3d-scene-en.html\",\n \"revision\": \"f94c977c6717501d824fdc691af74efe\"\n },\n {\n \"url\": \"notes/3d-scene.html\",\n \"revision\": \"f289dc7d9a1230c31c9e0fc7544a8ad0\"\n },\n {\n \"url\": \"notes/cy-simulation.html\",\n \"revision\": \"c1087df9c5adc4c8374e2411c7331ead\"\n },\n {\n \"url\": \"notes/debug.html\",\n \"revision\": \"eb4681ef7d14a224b64290a16bac8210\"\n },\n {\n \"url\": \"notes/event-scheduling-en.html\",\n \"revision\": \"5ac3b82266508eed1448ad8662ddafb3\"\n },\n {\n \"url\": \"notes/event-scheduling.html\",\n \"revision\": \"7367a34b5f885a47deab6e11f59a7c5d\"\n },\n {\n \"url\": \"notes/index.html\",\n \"revision\": \"f753fb653c733456fa446c071bb8fdf0\"\n },\n {\n \"url\": \"notes/lp.html\",\n \"revision\": \"a0cbcd40db9a650cbdae3ab88feabafe\"\n },\n {\n \"url\": \"notes/lua.html\",\n \"revision\": \"48762ce35d314f03f42c8f89cb054864\"\n },\n {\n \"url\": \"notes/mip-en.html\",\n \"revision\": \"55a92a21833f0dc50a313ef6eacadc05\"\n },\n {\n \"url\": \"notes/mip.html\",\n \"revision\": \"6567828fd786f0c1696fe09dc02c0639\"\n },\n {\n \"url\": \"notes/network.html\",\n \"revision\": \"bc2633a867e8eea8da23541b6d07d5ad\"\n },\n {\n \"url\": \"notes/oop.html\",\n \"revision\": \"e88b479cc1b4947014fb314be900e733\"\n },\n {\n \"url\": \"notes/plots.html\",\n \"revision\": \"c1ca6af908fc17826a13408a248e3943\"\n },\n {\n \"url\": \"notes/timelapse.html\",\n \"revision\": \"81270f4d58216846077730421233508d\"\n },\n {\n \"url\": \"notes/tools.html\",\n \"revision\": \"c77ad6c6c5797fc41ddbb0de6d72fea1\"\n },\n {\n \"url\": \"notes/versions.html\",\n \"revision\": \"3790516c8edc480d200979ea767c0b43\"\n },\n {\n \"url\": \"notes/visualization.html\",\n \"revision\": \"b05923335337842dc6d03cac617c2d20\"\n },\n {\n \"url\": \"notes/warehouse-simulation.html\",\n \"revision\": \"f8910b97a29643576e000667ee5805c6\"\n },\n {\n \"url\": \"notes/web-ui-en.html\",\n \"revision\": \"22d2d414438c6498e1a7875215c3b09e\"\n },\n {\n \"url\": \"notes/web-ui.html\",\n \"revision\": \"3ca0db04542a231792323d33208c8610\"\n },\n {\n \"url\": \"assets/3trend-e8Vz-nOo.webp\",\n \"revision\": \"62e6f891c43c490d73e9c40baced8bda\"\n },\n {\n \"url\": \"assets/6-1trend-iFlvvd90.webp\",\n \"revision\": \"77b688d0752c48c1d9ceaa7543f08116\"\n },\n {\n \"url\": \"assets/6trend-tHF37BNC.webp\",\n \"revision\": \"29a2a9741a7f5953bb3c394f3f70a644\"\n },\n {\n \"url\": \"assets/AceEditor-8UZqygeG.png\",\n \"revision\": \"d79c0c73bbf389f15e08dc2aa04f6c9d\"\n },\n {\n \"url\": \"assets/AGV2-cOVBigXf.png\",\n \"revision\": \"ac9d28e8b7f46a60dcdb8c430ac65a04\"\n },\n {\n \"url\": \"assets/AGVQueueModel-VbkDUcno.png\",\n \"revision\": \"5494bf4bbcee87a6d49427e6f32ff4b5\"\n },\n {\n \"url\": \"assets/auto_test-ttcTMf95.webp\",\n \"revision\": \"a32c2b274444d267076dfa6f94e6d63c\"\n },\n {\n \"url\": \"assets/AutoTranslate-oqY-EbbE.png\",\n \"revision\": \"7cd770336647da7598fe161fa99df301\"\n },\n {\n \"url\": \"assets/Banner-O--M2FyY.png\",\n \"revision\": \"4126c10b826d601e7ae4ef5e11c5a747\"\n },\n {\n \"url\": \"assets/BottomBar-Il3Sa37D.gif\",\n \"revision\": \"63e38d376fe4a371b8d97947b73fbd8c\"\n },\n {\n \"url\": \"assets/box_lwh-6iD8r0MK.jpg\",\n \"revision\": \"9c29ae29f4e3a90f4bbb1bc323488e6e\"\n },\n {\n \"url\": \"assets/city_logistics-8RxmuTB1.png\",\n \"revision\": \"f0e83dfc21b4da0afee21ec1645a5ce4\"\n },\n {\n \"url\": \"assets/close_save_grid-mxdTfyrH.png\",\n \"revision\": \"06823158f287c332e303ce9e74f119b1\"\n },\n {\n \"url\": \"assets/close_save_shapes-bnfKINWq.png\",\n \"revision\": \"6285144c1d85e6c8d7c12459ea8ecfa2\"\n },\n {\n \"url\": \"assets/color5-PRdlG8aV.gif\",\n \"revision\": \"7d57428b2e042e57250ff788e5214737\"\n },\n {\n \"url\": \"assets/color8-KLKGFsL4.gif\",\n \"revision\": \"7190cdbbc801e3598b39822c2f4449f1\"\n },\n {\n \"url\": \"assets/CommandBar-Pu56Q_KU.png\",\n \"revision\": \"48edae64a9b9429350f896d96e0d7af2\"\n },\n {\n \"url\": \"assets/coordinate-KcPjAH3b.png\",\n \"revision\": \"4696bfa608a3929ab8ffee4ed9da17f0\"\n },\n {\n \"url\": \"assets/CY1-KhoqZKrQ.png\",\n \"revision\": \"8fbbafb3f2d20b7b3542517162747e4b\"\n },\n {\n \"url\": \"assets/CY2-uRljosmO.png\",\n \"revision\": \"54659101f5e756f8d5ae99f230a325da\"\n },\n {\n \"url\": \"assets/CYLayout-XevrzO6A.jpg\",\n \"revision\": \"a83265003c673e906301a65be920056d\"\n },\n {\n \"url\": \"assets/data_visualization-HBg0SLXW.png\",\n \"revision\": \"bcf2333bc33ffde8b5f201e79ae4fb2b\"\n },\n {\n \"url\": \"assets/DL_Heatmap-uiGWW-lH.png\",\n \"revision\": \"5f26dd003befff9e1f6eb994197cf3ce\"\n },\n {\n \"url\": \"assets/edit_point-krh9tqYD.png\",\n \"revision\": \"b56499ca449e9cb42efa0ef5fe21aefd\"\n },\n {\n \"url\": \"assets/edit_shape-3r72h2cB.png\",\n \"revision\": \"5ee823e7cf71f04215c697036c15acb0\"\n },\n {\n \"url\": \"assets/EventSchedulingRefresh-P9P75NgW.jpg\",\n \"revision\": \"47874df6c7bd878c2a64d800de62e747\"\n },\n {\n \"url\": \"assets/fixed_increment_advance-ufFIwQjw.png\",\n \"revision\": \"20f2f4c8bbc3113184537da242398b9c\"\n },\n {\n \"url\": \"assets/gis_data_structure-OyzSP1K_.png\",\n \"revision\": \"77fa044dae581369badf8cb87d8e006c\"\n },\n {\n \"url\": \"assets/GraduatedColorProperties-QL7AyCTd.png\",\n \"revision\": \"acaa6f8e656886bcec42e74379e9eee5\"\n },\n {\n \"url\": \"assets/GraduatedColorResult-c1P6KfFi.png\",\n \"revision\": \"9869925032dbd7d448f4b1b60ab3c8a9\"\n },\n {\n \"url\": \"assets/GraduatedColorSettings-sd7MRVbC.png\",\n \"revision\": \"74ff570e2d95f95663e1565bb86a75e8\"\n },\n {\n \"url\": \"assets/grid_attributes-e5wa0ZGb.png\",\n \"revision\": \"99da94947795b278ee0bb4410dcf5e0e\"\n },\n {\n \"url\": \"assets/grid_menu-7jPQkAi1.png\",\n \"revision\": \"636dff6ad1216aa74de6214aba408e9f\"\n },\n {\n \"url\": \"assets/grid_selection-bdt61Cd7.png\",\n \"revision\": \"a854dc544ec5239818be6a245b4d558a\"\n },\n {\n \"url\": \"assets/grid_structure-vhTlEgf-.png\",\n \"revision\": \"4be1f0e0a70ddd24dfe875312edef079\"\n },\n {\n \"url\": \"assets/Histogram-hCqM-8K4.png\",\n \"revision\": \"b088afe8f4f8e21e5221a00aff8e6efd\"\n },\n {\n \"url\": \"assets/LabelAttribProperties-BNSD9rBn.png\",\n \"revision\": \"f95bfff89484f9f07ec316c996da5cf3\"\n },\n {\n \"url\": \"assets/layer_menu-lHo367yT.png\",\n \"revision\": \"55d3c08736142acc4245d482c2c0ce6a\"\n },\n {\n \"url\": \"assets/LookupTableColor-VSXylHlz.png\",\n \"revision\": \"af9601eb62ef3be4d01eb33f51a63661\"\n },\n {\n \"url\": \"assets/LookupTableProperties-P0W9jYQE.png\",\n \"revision\": \"16ab4c133ef51f5e9db60a401211c0da\"\n },\n {\n \"url\": \"assets/main_window-kvL2HSJd.png\",\n \"revision\": \"312ba4b6c91267ecef63c6ee00bc21e9\"\n },\n {\n \"url\": \"assets/map_coordinates-8ybUOErD.png\",\n \"revision\": \"c39aa1c8a4c3ed6e5b507f8cf3874160\"\n },\n {\n \"url\": \"assets/map_menu-zU_XTli2.png\",\n \"revision\": \"a95051447bc04efd2d5e706c872d3493\"\n },\n {\n \"url\": \"assets/module_libraries_settings-lee40Qvj.png\",\n \"revision\": \"bf0570b0b6130844d28fa3c402a27ffb\"\n },\n {\n \"url\": \"assets/module_settings-3JBvpV80.png\",\n \"revision\": \"ba28f8624752e27c514377e213ea642a\"\n },\n {\n \"url\": \"assets/modules-cY5Kwc-8.png\",\n \"revision\": \"55cea6ae301455d142cec78857a08aa9\"\n },\n {\n \"url\": \"assets/new_grid-4i1mP770.png\",\n \"revision\": \"cf382a920be3a7338877a71b78d66365\"\n },\n {\n \"url\": \"assets/new_scene-8_vgmKnR.png\",\n \"revision\": \"d5e69908016913fe08d8e00c90f6fb13\"\n },\n {\n \"url\": \"assets/new_shapes-RVv9IgwR.png\",\n \"revision\": \"36c06984f09ac60f8161c8d6aa860cf7\"\n },\n {\n \"url\": \"assets/new_table-Elg2D_3m.png\",\n \"revision\": \"89408a0284dd95c1421c0d5b4e6131f7\"\n },\n {\n \"url\": \"assets/new-GF873AfJ.gif\",\n \"revision\": \"aadcfac586760bc33926ca5ce7f02a9c\"\n },\n {\n \"url\": \"assets/object_menu-rLYhy67y.png\",\n \"revision\": \"eec516547d2a3ac027546ae348f4f054\"\n },\n {\n \"url\": \"assets/old-FpQSFo63.gif\",\n \"revision\": \"4080855b1419e2c04463cebd35711270\"\n },\n {\n \"url\": \"assets/optimal_layout-bCy9JRge.webp\",\n \"revision\": \"584a4e39d1b598fc7c4fb08653ba0477\"\n },\n {\n \"url\": \"assets/PlotPrice1-QAaVF6hQ.png\",\n \"revision\": \"2343fd9de1abdbbaf15f5413236f76fb\"\n },\n {\n \"url\": \"assets/PlotPrice2-DeodiEK_.png\",\n \"revision\": \"1a853fda82ea81fff7b44d65ba15346a\"\n },\n {\n \"url\": \"assets/polygon_sizes-naWR0jXW.jpg\",\n \"revision\": \"dc376be92b128dadabd35eace5ccee21\"\n },\n {\n \"url\": \"assets/polylines_order-v8d3qUyG.jpg\",\n \"revision\": \"31638de01c4de5ae632f20f1b6403fee\"\n },\n {\n \"url\": \"assets/Preset_Earth-Tllgpkll.png\",\n \"revision\": \"f55773fa09d457dd715992b6835564b7\"\n },\n {\n \"url\": \"assets/Preset_Truck-ZFTcQbsO.png\",\n \"revision\": \"a77828aa329b3c20d7cd8cb8696db5dd\"\n },\n {\n \"url\": \"assets/Presets-dDpjg8aZ.png\",\n \"revision\": \"26dee069587516d47812b816f671eac8\"\n },\n {\n \"url\": \"assets/problem1-AJuFUHVQ.webp\",\n \"revision\": \"c245c369ed623e8e388767d4f830afa3\"\n },\n {\n \"url\": \"assets/problem2-KunKgJbC.webp\",\n \"revision\": \"325bed85492b9881ea786baa7245e353\"\n },\n {\n \"url\": \"assets/Q1Banner-BxB6kPmr.png\",\n \"revision\": \"bc503822f53bcbca271785e032b28a45\"\n },\n {\n \"url\": \"assets/Q1ContainerProcessFlow-t0XYjgJ-.png\",\n \"revision\": \"13ba28ee1e19abc2be46756fe982d86a\"\n },\n {\n \"url\": \"assets/Q2-hS2yYPEB.jpg\",\n \"revision\": \"7d824da5c6d3a040b3f24a27ba42171a\"\n },\n {\n \"url\": \"assets/Q2Layout-jXHR-iYn.png\",\n \"revision\": \"419a6e710279298f56fa3405cb685e26\"\n },\n {\n \"url\": \"assets/query_results-8DtTlPIZ.png\",\n \"revision\": \"527d9a24621e0953478d8cd1224d973a\"\n },\n {\n \"url\": \"assets/RangeDotRelateToMap-s6apr58V.png\",\n \"revision\": \"503a9b2bb8e9a9106462e15478480baa\"\n },\n {\n \"url\": \"assets/RelateToMapBig-co0riIjm.png\",\n \"revision\": \"f0dd5026b6fa4bee47c155db6d44d822\"\n },\n {\n \"url\": \"assets/RelateToMapSmall-8yIwZc0w.png\",\n \"revision\": \"10945aba05b9286a9182b5957f15ef01\"\n },\n {\n \"url\": \"assets/RelateToScreenBig-H3UhFI8t.png\",\n \"revision\": \"2095d6f27c66191ed2f3a5c55e4e286f\"\n },\n {\n \"url\": \"assets/RelateToScreenSmall-RgyFR_Ap.png\",\n \"revision\": \"9bb544030d3ed11649649524ea8d4bb4\"\n },\n {\n \"url\": \"assets/RMG-AGV-ProcessFlow-aQWltqys.png\",\n \"revision\": \"4d7c0cb8ca470de4c7e17eb49394de69\"\n },\n {\n \"url\": \"assets/RMG1-zXf9sSV8.png\",\n \"revision\": \"f2362f6e69a941146929feef9262df73\"\n },\n {\n \"url\": \"assets/RMG2-ea6huW81.png\",\n \"revision\": \"18bc24c71d84d836806a35f090182811\"\n },\n {\n \"url\": \"assets/RMGObjects-yrTAIJHV.png\",\n \"revision\": \"22386c7fb35c3987fd9fe92090a08fe8\"\n },\n {\n \"url\": \"assets/RMGQC2-BO9lyakQ.png\",\n \"revision\": \"b179f5f2a4bc3d9043503617887201e8\"\n },\n {\n \"url\": \"assets/RunCode-xHWq8U-i.gif\",\n \"revision\": \"5f634a99c4fc97eea5525a02b8f51677\"\n },\n {\n \"url\": \"assets/scene_coordinate-muj-oFBk.png\",\n \"revision\": \"4a5134bd71717c44e496080a75478b39\"\n },\n {\n \"url\": \"assets/scene_menu-RSZKJk7N.png\",\n \"revision\": \"92664f67e27932c0d91c26ade6252378\"\n },\n {\n \"url\": \"assets/script_editor-51w4xjN9.png\",\n \"revision\": \"5cee3858ed9d28fd46d30d87477de338\"\n },\n {\n \"url\": \"assets/segments-wNxhsxV0.jpg\",\n \"revision\": \"adfe33d8ae64831aebeedec7a91a1f99\"\n },\n {\n \"url\": \"assets/SelectLinksColor--zZDTT73.png\",\n \"revision\": \"90ba31fd0a8532b3f841b39f898c8b7e\"\n },\n {\n \"url\": \"assets/SetParameterProperties-m8LPKWT1.png\",\n \"revision\": \"fdbc3e7d199a408b5526279c6d1c6474\"\n },\n {\n \"url\": \"assets/shapes_files-ShfoHRZo.png\",\n \"revision\": \"9a734a267477ee4d92b1cf39554bd4e2\"\n },\n {\n \"url\": \"assets/shapes_menu-aime3jTY.png\",\n \"revision\": \"1ce52bb22c77de1d9b138fac30adbf95\"\n },\n {\n \"url\": \"assets/SHIP2-pz8IHA_0.png\",\n \"revision\": \"f598e405a60027016fb59b8b3b3d195c\"\n },\n {\n \"url\": \"assets/shipping_planning-_Mkxb6xn.png\",\n \"revision\": \"73ff5ae946bc1b3408af6852a40f14b2\"\n },\n {\n \"url\": \"assets/shot_parameter_id-ljNzzofT.png\",\n \"revision\": \"c89a255188060a166f8890523d9596af\"\n },\n {\n \"url\": \"assets/shot_script_editor-_OW8Kkrd.png\",\n \"revision\": \"d7f18072054f41155cde343988a8a176\"\n },\n {\n \"url\": \"assets/sim-result-nEPKqIkR.webp\",\n \"revision\": \"4d4fb876261b1b2f812c26a2459287ce\"\n },\n {\n \"url\": \"assets/SizeProperties-xZe9_-WE.png\",\n \"revision\": \"0c1b64600f1cac883992d07661a4832d\"\n },\n {\n \"url\": \"assets/Subplot_Vertical-X1t_RUlM.png\",\n \"revision\": \"d0afcb66a5aeec2fd0b1fdbdc6426337\"\n },\n {\n \"url\": \"assets/table_menu-enNFenIu.png\",\n \"revision\": \"568acc7e16f0e89d9aab0846e6b37969\"\n },\n {\n \"url\": \"assets/table_view_menu-1OnsnofR.png\",\n \"revision\": \"a5b97ce1a8ed91d31c4fe571e0d5da4e\"\n },\n {\n \"url\": \"assets/TableSelect-jKGsdf_N.png\",\n \"revision\": \"a2f14a33f90021823a66786f4be84fae\"\n },\n {\n \"url\": \"assets/terminal_simulation-rx4w_Kp0.gif\",\n \"revision\": \"b2c8c2047ae16200788732a65d9d342a\"\n },\n {\n \"url\": \"assets/test_layout-3LvNhD-0.webp\",\n \"revision\": \"04e32d297a5182f881182b3b039c3680\"\n },\n {\n \"url\": \"assets/warehouse_simulation-CPwzj5dU.gif\",\n \"revision\": \"f62546662765fda4f41338846a1af6a6\"\n },\n {\n \"url\": \"assets/WebUIOverview-NmRQvsO9.png\",\n \"revision\": \"769241be4e6ed733ce783a4a7bd63443\"\n },\n {\n \"url\": \"assets/WebUIParts-yq4WXR5p.png\",\n \"revision\": \"411be83677e6ad958f5f7fb506ec1026\"\n },\n {\n \"url\": \"assets/world_countries-K0FhRM3K.png\",\n \"revision\": \"e850582792c99b09af68ca948e2aff8e\"\n },\n {\n \"url\": \"assets/无预判障碍-p5itt-RJ.gif\",\n \"revision\": \"6b6189014d83c82c480cd0dad1d3aec0\"\n },\n {\n \"url\": \"assets/预判障碍-hw2PZ_-s.gif\",\n \"revision\": \"8236b76fb86d617e815a12382aa2c140\"\n },\n {\n \"url\": \"images/icon_microcity.png\",\n \"revision\": \"08f31df45215c6018336c0acf1ff5e4d\"\n },\n {\n \"url\": \"images/icon_microcitynotes.png\",\n \"revision\": \"8fab94c045ebfa93980673848abc96b2\"\n },\n {\n \"url\": \"images/icon/icon-144.png\",\n \"revision\": \"06593bf0bb1b7646ed53c336be5ee07b\"\n },\n {\n \"url\": \"images/icon/icon-192.png\",\n \"revision\": \"dd4c61d0beacce8e965296d679fff0ca\"\n },\n {\n \"url\": \"images/icon/icon-512.png\",\n \"revision\": \"65e0e189f0e4f4fe72e6a6c47480c655\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\n\n\n\n\n\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches"],"mappings":"0nBAqBAA,KAAKC,iBAAiB,WAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,aACP,IAGFC,EAAAA,eAQAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,oDACPC,SAAY,oCAEd,CACED,IAAO,oDACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,sDACPC,SAAY,oCAEd,CACED,IAAO,sDACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,iDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,iDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,WACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,wBACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,kBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,wBACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,qCAEb,CAAE,GACLC,EAAAA"} \ No newline at end of file +{"version":3,"file":"service-worker.js","sources":["../../../../../tmp/11df650e31d65702c86eb2908195f5cb/service-worker.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/MicroCityNotes/MicroCityNotes/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/MicroCityNotes/MicroCityNotes/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/MicroCityNotes/MicroCityNotes/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\nworkbox_core_clientsClaim();\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"assets/1.1_what_microcity_can_do.html-BudeEahj.js\",\n \"revision\": \"cb0291f908ebf4dff4c593b7c388868e\"\n },\n {\n \"url\": \"assets/1.1_what_microcity_can_do.html-HcIFtvfI.js\",\n \"revision\": \"5feaea56c63e9e54f21f95c1ea973fa1\"\n },\n {\n \"url\": \"assets/1.1_what_microcity_can_do.html-m1yQS0yR.js\",\n \"revision\": \"202d178cfc2007b9e95f7f0ddceecaac\"\n },\n {\n \"url\": \"assets/1.1_what_microcity_can_do.html-YHpuvmc-.js\",\n \"revision\": \"3ab3c24555a0c9b7a1b54c2f195fae04\"\n },\n {\n \"url\": \"assets/2.1_showing_a_world_map.html-6qnXe-uR.js\",\n \"revision\": \"a08a857bb7a2e4a6fd683a7ea94e4c51\"\n },\n {\n \"url\": \"assets/2.1_showing_a_world_map.html-F73HLlmh.js\",\n \"revision\": \"8bf0eaa37a5339257a352112ba456d5c\"\n },\n {\n \"url\": \"assets/2.1_showing_a_world_map.html-GZyM8T_I.js\",\n \"revision\": \"630c976ef0d3555c323d68637ab1b734\"\n },\n {\n \"url\": \"assets/2.1_showing_a_world_map.html-Ybz9X3FC.js\",\n \"revision\": \"d39d69b8b91a8a678a8a1c4edcdef9d4\"\n },\n {\n \"url\": \"assets/2.2_searching_for_countries.html-I1-AYfhY.js\",\n \"revision\": \"3ca0380620c99d950fbd70aca8248cbe\"\n },\n {\n \"url\": \"assets/2.2_searching_for_countries.html-OCp2-Zt6.js\",\n \"revision\": \"681b9588dd2c743ffab021b93e57f49c\"\n },\n {\n \"url\": \"assets/2.2_searching_for_countries.html-t7DQyHf7.js\",\n \"revision\": \"66694b76e641e4857987e40bfca86266\"\n },\n {\n \"url\": \"assets/2.2_searching_for_countries.html-Y0QCK0Nw.js\",\n \"revision\": \"9874a64f07c3b4171103d6a0d549d678\"\n },\n {\n \"url\": \"assets/3.1_ui_overview.html-3VU9Yk9s.js\",\n \"revision\": \"843ceeaead657f1e475037551471b6d2\"\n },\n {\n \"url\": \"assets/3.1_ui_overview.html-6J3N08CW.js\",\n \"revision\": \"ebd7e07061ce2e93b8b35a2d2d2566e4\"\n },\n {\n \"url\": \"assets/3.1_ui_overview.html-MdRgXeyu.js\",\n \"revision\": \"a2fbfd91eb2fd7fd46674a8c13ada58d\"\n },\n {\n \"url\": \"assets/3.1_ui_overview.html-v38UIHQc.js\",\n \"revision\": \"2bdb9c693b83fb64b0b8e47af6edf94e\"\n },\n {\n \"url\": \"assets/3.2_vector_shapes.html-Ggy6120F.js\",\n \"revision\": \"0b9a7b956a4cd3fe26c59b1e6364002c\"\n },\n {\n \"url\": \"assets/3.2_vector_shapes.html-hHGdBrtV.js\",\n \"revision\": \"39c9bbb22eae7d20ce6b53458785f2a7\"\n },\n {\n \"url\": \"assets/3.2_vector_shapes.html-o5HA4H30.js\",\n \"revision\": \"1a93e013c29b95215275ed78f544021f\"\n },\n {\n \"url\": \"assets/3.2_vector_shapes.html-uMTzJRD1.js\",\n \"revision\": \"f0b9ccc940bc43c9eaaed7c1cb3d3363\"\n },\n {\n \"url\": \"assets/3.3_raster_grids.html-_OMWjBic.js\",\n \"revision\": \"e49369e12c65a091e5a7ff2bd42e2dcc\"\n },\n {\n \"url\": \"assets/3.3_raster_grids.html-KMfHWMMp.js\",\n \"revision\": \"1315c95fe419e5ded38aff3244321a47\"\n },\n {\n \"url\": \"assets/3.3_raster_grids.html-OMCyU_6r.js\",\n \"revision\": \"9298e0bc116b87de9e6a80b8700c46ba\"\n },\n {\n \"url\": \"assets/3.3_raster_grids.html-t2xEoSZE.js\",\n \"revision\": \"1a2449917bf1131929bfdca0f4df51c9\"\n },\n {\n \"url\": \"assets/3.4_3d_scenes.html-2qe1Dffq.js\",\n \"revision\": \"f1c3a668d1b2386da152ad51a7de868c\"\n },\n {\n \"url\": \"assets/3.4_3d_scenes.html-E-00tpZF.js\",\n \"revision\": \"f15e9b83ada3b9910a6afe6fdc59a318\"\n },\n {\n \"url\": \"assets/3.4_3d_scenes.html-IfcyMMcw.js\",\n \"revision\": \"62a22eacc8276445b1793572636f8510\"\n },\n {\n \"url\": \"assets/3.4_3d_scenes.html-Q6eGIaTn.js\",\n \"revision\": \"4d4c97efef0cdcdcd1030491549e0d13\"\n },\n {\n \"url\": \"assets/3.5_tables.html-KMEBPMHz.js\",\n \"revision\": \"576f04f4b3ce3be2b91a54f00266ff2a\"\n },\n {\n \"url\": \"assets/3.5_tables.html-LpE0kpTR.js\",\n \"revision\": \"f12b59a6605923c7fcba04f681272d09\"\n },\n {\n \"url\": \"assets/3.5_tables.html-p1nKqUcK.js\",\n \"revision\": \"6c573cdb51e696a8be5def3b4dafc58f\"\n },\n {\n \"url\": \"assets/3.5_tables.html-rfKSY5-v.js\",\n \"revision\": \"167c188f4300fc54671e63772a40f4da\"\n },\n {\n \"url\": \"assets/3.6_maps_and_layers.html-IZMNuK0Y.js\",\n \"revision\": \"cf43517de6e390f9bfa86bffe888427a\"\n },\n {\n \"url\": \"assets/3.6_maps_and_layers.html-KNvuRdkG.js\",\n \"revision\": \"96a0613891e2196f8d272fc1af9653e2\"\n },\n {\n \"url\": \"assets/3.6_maps_and_layers.html-T_p6rWde.js\",\n \"revision\": \"55e2ef5e5bacf9baa29d1fa7b05ab1a0\"\n },\n {\n \"url\": \"assets/3.6_maps_and_layers.html-Zp7Na5N3.js\",\n \"revision\": \"6479df3f21ee871bb4a5b118fae06309\"\n },\n {\n \"url\": \"assets/3.7_modules.html-acS-BfiZ.js\",\n \"revision\": \"f5e4bb2103fe19682c84dea7c9e9192f\"\n },\n {\n \"url\": \"assets/3.7_modules.html-d3BG3VZc.js\",\n \"revision\": \"027718608c542ae258a4536adfa9cd99\"\n },\n {\n \"url\": \"assets/3.7_modules.html-mmRRzoSK.js\",\n \"revision\": \"7c7d26e5f29a41b2273255d369fec6a3\"\n },\n {\n \"url\": \"assets/3.7_modules.html-yzio17Ud.js\",\n \"revision\": \"87e68594b9e0ccc50ccd9b89f11fddde\"\n },\n {\n \"url\": \"assets/3d-objects.html-AEqGn78x.js\",\n \"revision\": \"9f706206d96fe62920c59b49369f7532\"\n },\n {\n \"url\": \"assets/3d-objects.html-frmlnhRb.js\",\n \"revision\": \"79460193fd95ef858861a948b4d73fd3\"\n },\n {\n \"url\": \"assets/3d-objects.html-jGytICR_.js\",\n \"revision\": \"d5b0a215bd813a5d3a87308ef4d4f073\"\n },\n {\n \"url\": \"assets/3d-objects.html-l7ht6tpD.js\",\n \"revision\": \"c0b5fc7f1f5fc09476d4774196d56b2e\"\n },\n {\n \"url\": \"assets/3d-scene.html-iJwBMXhE.js\",\n \"revision\": \"8de4eb2b56ff653ac9109f342212191f\"\n },\n {\n \"url\": \"assets/3d-scene.html-pmrdLLCG.js\",\n \"revision\": \"f651b354357642c6b01635a46488276c\"\n },\n {\n \"url\": \"assets/3d-scene.html-QeNNxNdQ.js\",\n \"revision\": \"ac2f364be8b6f76d99c84350ec8dbb74\"\n },\n {\n \"url\": \"assets/3d-scene.html-smFwVKZl.js\",\n \"revision\": \"79bd8400b98b1802f4856de49f878e61\"\n },\n {\n \"url\": \"assets/4.1_si_overview.html-3JNy66LR.js\",\n \"revision\": \"bfd889632330ebcbc5d657ec496d2833\"\n },\n {\n \"url\": \"assets/4.1_si_overview.html-aQjVZ38p.js\",\n \"revision\": \"937ae5cdc486f1e73bb76e7613f40626\"\n },\n {\n \"url\": \"assets/4.1_si_overview.html-mGhzJSIB.js\",\n \"revision\": \"aac7651b53a30a6ffe5b891a5c20712e\"\n },\n {\n \"url\": \"assets/4.1_si_overview.html-niv4qRLq.js\",\n \"revision\": \"03b6d83b4bd33259b3d40a2200a90aa4\"\n },\n {\n \"url\": \"assets/4.2_ui_control.html-it8dN_Kd.js\",\n \"revision\": \"d3a6d2116d5afd8865baca6ee0ceaa69\"\n },\n {\n \"url\": \"assets/4.2_ui_control.html-n4jA58yX.js\",\n \"revision\": \"7608e8e218e4ca30ea085ce37ed01b3b\"\n },\n {\n \"url\": \"assets/4.2_ui_control.html-qgHwWAaN.js\",\n \"revision\": \"9c0339071c7f204f3425ec06b2d233fc\"\n },\n {\n \"url\": \"assets/4.2_ui_control.html-Zsu36Eou.js\",\n \"revision\": \"9a55c2948ff4b1e5d23e6087181d5e32\"\n },\n {\n \"url\": \"assets/4.3_shapes_and_tables.html-9CbssTxf.js\",\n \"revision\": \"0c2e6d17fa2542a0f359dc5d9b44da88\"\n },\n {\n \"url\": \"assets/4.3_shapes_and_tables.html-Ix5omLFZ.js\",\n \"revision\": \"100f9d7826261aa2d0939c5437dc5797\"\n },\n {\n \"url\": \"assets/4.3_shapes_and_tables.html-SxckQf89.js\",\n \"revision\": \"4094406db447a86d408ec0232d747be6\"\n },\n {\n \"url\": \"assets/4.3_shapes_and_tables.html-TBHhEBxq.js\",\n \"revision\": \"bc506d14389ed368a2851318d3a64d1d\"\n },\n {\n \"url\": \"assets/4.4_grids.html-1OY5s52Z.js\",\n \"revision\": \"b2dad7515a90e4c6b35572afe3daada0\"\n },\n {\n \"url\": \"assets/4.4_grids.html-exxRQ7PN.js\",\n \"revision\": \"1ed8a20a8f499d769208fbee67a72abc\"\n },\n {\n \"url\": \"assets/4.4_grids.html-H6iZCbel.js\",\n \"revision\": \"e1cd82f2ab18039b06fbb437f3cebee8\"\n },\n {\n \"url\": \"assets/4.4_grids.html-JfxVQVat.js\",\n \"revision\": \"7bb54a78f70d95f03eb83ad9619d5313\"\n },\n {\n \"url\": \"assets/4.5_3d_scenes.html-I_su3OaS.js\",\n \"revision\": \"3ff8fd95c4cf90205752840a29094bcb\"\n },\n {\n \"url\": \"assets/4.5_3d_scenes.html-IYlmTIee.js\",\n \"revision\": \"ee2648795f89d542acf61f94350a1116\"\n },\n {\n \"url\": \"assets/4.5_3d_scenes.html-rRFZU4Tx.js\",\n \"revision\": \"7335abb03b648309433bd1a260225f1c\"\n },\n {\n \"url\": \"assets/4.5_3d_scenes.html-wmTORBrk.js\",\n \"revision\": \"531a535c22fe8e549a7c3d536c79be15\"\n },\n {\n \"url\": \"assets/4.6_networks.html-0YdpivDj.js\",\n \"revision\": \"b27e00123f43da0995c58770eeab9f6b\"\n },\n {\n \"url\": \"assets/4.6_networks.html-HJVUieG0.js\",\n \"revision\": \"819df90cfac4b7e1a38ffd252053c88f\"\n },\n {\n \"url\": \"assets/4.6_networks.html-kqO_isZV.js\",\n \"revision\": \"89a4f98be45c03fb784b212114f4c646\"\n },\n {\n \"url\": \"assets/4.6_networks.html-Z1GoybBX.js\",\n \"revision\": \"b835fd7b2015c2144e40b23c7248fd08\"\n },\n {\n \"url\": \"assets/4.7_des_simulations_zh.html-dVopgWmS.js\",\n \"revision\": \"ff385f224575c8dff49da5b36f4cc0a6\"\n },\n {\n \"url\": \"assets/4.7_des_simulations_zh.html-PYbnXFlK.js\",\n \"revision\": \"85897bfb02a4bd5801eff4fe8905a956\"\n },\n {\n \"url\": \"assets/4.7_des_simulations.html-Ie9zDG_n.js\",\n \"revision\": \"c9a88484f8e21fb519faa53a4ed0b056\"\n },\n {\n \"url\": \"assets/4.7_des_simulations.html-JlfYhUg2.js\",\n \"revision\": \"a7892b80d467a4dd3324f1ea6381064a\"\n },\n {\n \"url\": \"assets/4.7_des_simulations.html-W4OcSvr1.js\",\n \"revision\": \"ed5377561cdc68b82babb03cc30364c8\"\n },\n {\n \"url\": \"assets/4.7_des_simulations.html-WnzqINmi.js\",\n \"revision\": \"f43cc11e4107ca429c70783ce70cf2e4\"\n },\n {\n \"url\": \"assets/4.8_mixed_integer_programming.html-ixWGOETF.js\",\n \"revision\": \"a5c12615e437e1739d6d7ea3ac909e0a\"\n },\n {\n \"url\": \"assets/4.8_mixed_integer_programming.html-MExXnfeH.js\",\n \"revision\": \"128634a14b4ac3d8e096a8fb6df46436\"\n },\n {\n \"url\": \"assets/4.8_mixed_integer_programming.html-spXsyES8.js\",\n \"revision\": \"5c8f511d999d56f26c500489c96d0667\"\n },\n {\n \"url\": \"assets/4.8_mixed_integer_programming.html-TGfmzRJO.js\",\n \"revision\": \"aaa1ac49a5767f35c2c9266e60ed24e2\"\n },\n {\n \"url\": \"assets/404.html-O1A74s9P.js\",\n \"revision\": \"d9d8bbe4476db75f55602a872936c43a\"\n },\n {\n \"url\": \"assets/404.html-tJ8VjSOS.js\",\n \"revision\": \"8c1c828efd6590cf001958bd2779f3e2\"\n },\n {\n \"url\": \"assets/6-1trend-atJpgMOK.js\",\n \"revision\": \"88c80d3213ed2759f43df19e5415c7e0\"\n },\n {\n \"url\": \"assets/A2hs-LwmLJR8r.js\",\n \"revision\": \"eb5177b4dd756facb4195b00a4856fee\"\n },\n {\n \"url\": \"assets/add_field-ZFhY51wb.js\",\n \"revision\": \"f3ae3d0717ce3f1b08575d9ab24fe7b4\"\n },\n {\n \"url\": \"assets/app-LOf__QKq.js\",\n \"revision\": \"0a251a62d29152943699be940ed07c83\"\n },\n {\n \"url\": \"assets/AutoTranslate-DxMBsWAh.js\",\n \"revision\": \"cdab077a6f396da2b7c8b2a2436c305a\"\n },\n {\n \"url\": \"assets/button_3d-coWyniAs.js\",\n \"revision\": \"b1d87c2188190dc8f9ad758ff3209930\"\n },\n {\n \"url\": \"assets/button_action-tmG_4IgV.js\",\n \"revision\": \"a45c2da3625b69f983ea2f3f250ed37f\"\n },\n {\n \"url\": \"assets/button_load-GOP3K2yO.js\",\n \"revision\": \"391a5543a75ec54a6c326b181f2841e4\"\n },\n {\n \"url\": \"assets/button_ruler-TjPjykp6.js\",\n \"revision\": \"85978e9104a2ffdc5bc0a70e57406a1a\"\n },\n {\n \"url\": \"assets/CommandBar-jgj8yIQP.js\",\n \"revision\": \"a9054c9490e70200bc2a4f8fdd523d63\"\n },\n {\n \"url\": \"assets/coordinate-R7ZKfirG.js\",\n \"revision\": \"141fa761610279516cdcbc64554f02a9\"\n },\n {\n \"url\": \"assets/cy-simulation.html-0hk7J5DH.js\",\n \"revision\": \"65f5231cce4d47ce35d44756fc38bf96\"\n },\n {\n \"url\": \"assets/cy-simulation.html-5ddk20cl.js\",\n \"revision\": \"bad1162346c50be9ab8d70fac2771250\"\n },\n {\n \"url\": \"assets/cy-simulation.html-ms-pVG5v.js\",\n \"revision\": \"8651dcbfc7ff3c0d1db1dbbd0fbdf093\"\n },\n {\n \"url\": \"assets/cy-simulation.html-x04vq-Lr.js\",\n \"revision\": \"af9211cc19a0aa821a21e8890d58ab9e\"\n },\n {\n \"url\": \"assets/data_visualization-NDO9FqTF.js\",\n \"revision\": \"747175bdc3a6382a86d95e8e2f2235d1\"\n },\n {\n \"url\": \"assets/debug.html-80fcUM2q.js\",\n \"revision\": \"9c7dca47d4443ca8ea19a7ed492ae2a4\"\n },\n {\n \"url\": \"assets/debug.html-Pj0zKe-s.js\",\n \"revision\": \"d227123d8f7af9df0e53cd3816c6925b\"\n },\n {\n \"url\": \"assets/debug.html-vC47hElk.js\",\n \"revision\": \"f300271cb8a897afcead571d139d5a5b\"\n },\n {\n \"url\": \"assets/debug.html-YQ27enDU.js\",\n \"revision\": \"7efea725a844e42c64fcd5100ede149b\"\n },\n {\n \"url\": \"assets/DL_Heatmap-RXB-9ZZK.js\",\n \"revision\": \"69db2faeab7d5948158145e27669982e\"\n },\n {\n \"url\": \"assets/edit_point-Z0R1Z63o.js\",\n \"revision\": \"9a9b8413c46df7b403983ec0cccde203\"\n },\n {\n \"url\": \"assets/event-scheduling.html-_wHScoNu.js\",\n \"revision\": \"9e54dea262d14b3c4c5866f3e6e6e6b7\"\n },\n {\n \"url\": \"assets/event-scheduling.html-3ysZ_CTt.js\",\n \"revision\": \"aeb11ee564034e31f390a8148156e1d0\"\n },\n {\n \"url\": \"assets/event-scheduling.html-py4kt8T8.js\",\n \"revision\": \"6ea888e991ba1e2f4ecd5426c7a1e7c8\"\n },\n {\n \"url\": \"assets/event-scheduling.html-UZg_AtmL.js\",\n \"revision\": \"fd097dad87d6a364a4b627ecff783b19\"\n },\n {\n \"url\": \"assets/fixed_increment_advance-iwDvqivb.js\",\n \"revision\": \"5e576c226069a2d9fcca516a02cba73a\"\n },\n {\n \"url\": \"assets/flowchart-loQwkp6e.js\",\n \"revision\": \"d0922e56732b0ff9f2eb72eccb4e7e36\"\n },\n {\n \"url\": \"assets/giscus-unEZQsJ0.js\",\n \"revision\": \"34c4288ad53e7d9be8d0f44c9fdba069\"\n },\n {\n \"url\": \"assets/grid_attributes-xxRYXyrC.js\",\n \"revision\": \"27ccac6184ab099332a5a65f4b4056d5\"\n },\n {\n \"url\": \"assets/icon_microcity-Je85-7MO.js\",\n \"revision\": \"0e7e05a07396d393fc7977851d9d6556\"\n },\n {\n \"url\": \"assets/icon_module-AxwvBQMt.js\",\n \"revision\": \"927274ea2b678bc32f744ed0e157301f\"\n },\n {\n \"url\": \"assets/icon_script_editor-ibm_2NsU.js\",\n \"revision\": \"2a9329638f5d3bdd769734a539f336b3\"\n },\n {\n \"url\": \"assets/icon_shapes_polygon-5WS2EZQN.js\",\n \"revision\": \"780fc09847b268c582be5334dce3ca5f\"\n },\n {\n \"url\": \"assets/index-7SG8bi1h.js\",\n \"revision\": \"46a193641571106d3b7b43f9bc2a2735\"\n },\n {\n \"url\": \"assets/index.html-2U8qpeQG.js\",\n \"revision\": \"44d28ad2eaebb766e081fc7c29547ba2\"\n },\n {\n \"url\": \"assets/index.html-92lUUdK6.js\",\n \"revision\": \"8e66d9798dbd7b640c897ffe75286ab5\"\n },\n {\n \"url\": \"assets/index.html-a5Ef1Ykb.js\",\n \"revision\": \"f0a2c2b05b8588a8598b875e8d5a04de\"\n },\n {\n \"url\": \"assets/index.html-b5l2JDLj.js\",\n \"revision\": \"4de6157b204bda32aa5e9517ff168de3\"\n },\n {\n \"url\": \"assets/index.html-c3NKfYSn.js\",\n \"revision\": \"c746eaadfbe5e364fac37f3fdf1a801d\"\n },\n {\n \"url\": \"assets/index.html-dxC6HmKS.js\",\n \"revision\": \"13b58b42e3af50fed344bae12418e7ec\"\n },\n {\n \"url\": \"assets/index.html-hYpF9QHg.js\",\n \"revision\": \"708211c37144e03ec8cc5e90f5ae9b3d\"\n },\n {\n \"url\": \"assets/index.html-IqC-sAFX.js\",\n \"revision\": \"032d58ef5aaceba33bc2117e5d4c6811\"\n },\n {\n \"url\": \"assets/index.html-NfP7JmCD.js\",\n \"revision\": \"584943a7a29ff400d5125e9fb79c0250\"\n },\n {\n \"url\": \"assets/index.html-nYDcqjx5.js\",\n \"revision\": \"eb23205e7c74cb68c8520a571f9bff00\"\n },\n {\n \"url\": \"assets/index.html-rmW5MKDv.js\",\n \"revision\": \"ad78aaabd131c2ec3b71d4b1c5ee57ef\"\n },\n {\n \"url\": \"assets/index.html-WLZyFhZW.js\",\n \"revision\": \"45f61925f979c983465618e8153fd670\"\n },\n {\n \"url\": \"assets/index.html-WsgEQayQ.js\",\n \"revision\": \"62893cdc20e0350d5f657f8207c717cf\"\n },\n {\n \"url\": \"assets/index.html-YVKYSuDE.js\",\n \"revision\": \"111256ef875c8db74ff3ba5b25af9e41\"\n },\n {\n \"url\": \"assets/KaTeX_AMS-Regular-0YIAJWTb.ttf\",\n \"revision\": \"56573229753fad48910bda2ea1a6dd54\"\n },\n {\n \"url\": \"assets/KaTeX_AMS-Regular-UIXRTGNW.woff2\",\n \"revision\": \"66c678209ce93b6e2b583f02ce41529e\"\n },\n {\n \"url\": \"assets/KaTeX_AMS-Regular-zJvWDgGp.woff\",\n \"revision\": \"10824af77e9961cfd548c8a458f10851\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Bold-6vyEfazt.woff2\",\n \"revision\": \"a9e9b0953b078cd40f5e19ef4face6fc\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Bold-AE18XbF9.ttf\",\n \"revision\": \"497bf407c4c609c6cf1f1ad38f437f7f\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Bold-RIlxi71x.woff\",\n \"revision\": \"de2ba279933d60f7819ff61f71c17bed\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Regular-4uo0fsfh.woff2\",\n \"revision\": \"08d95d99bf4a2b2dc7a876653857f154\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Regular-k0QPq0y-.woff\",\n \"revision\": \"a25140fbe6692bffe71a2ab861572eb3\"\n },\n {\n \"url\": \"assets/KaTeX_Caligraphic-Regular-MF_e1AYw.ttf\",\n \"revision\": \"e6fb499fc8f9925eea3138cccba17fff\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Bold-bAz-dThZ.woff\",\n \"revision\": \"40934fc076960bb989d590db044fef62\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Bold-i-oP291Y.woff2\",\n \"revision\": \"796f3797cdf36fcaea18c3070a608378\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Bold-XZxETTVq.ttf\",\n \"revision\": \"b9d7c4497cab3702487214651ab03744\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Regular-8XXOHEfX.woff\",\n \"revision\": \"e435cda5784e21b26ab2d03fbcb56a99\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Regular-gf8Lq3rE.ttf\",\n \"revision\": \"97a699d83318e9334a0deaea6ae5eda2\"\n },\n {\n \"url\": \"assets/KaTeX_Fraktur-Regular-k2IhepQP.woff2\",\n \"revision\": \"f9e6a99f4a543b7d6cad1efb6cf1e4b1\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Bold-CZtwCMuf.woff\",\n \"revision\": \"4cdba6465ab9fac5d3833c6cdba7a8c3\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Bold-MGqDlVzd.ttf\",\n \"revision\": \"8e431f7ece346b6282dae3d9d0e7a970\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Bold-sffOiHVw.woff2\",\n \"revision\": \"a9382e25bcf75d856718fcef54d7acdb\"\n },\n {\n \"url\": \"assets/KaTeX_Main-BoldItalic-88TzJhul.ttf\",\n \"revision\": \"52fb39b0434c463d5df32419608ab08a\"\n },\n {\n \"url\": \"assets/KaTeX_Main-BoldItalic-8QydwDku.woff2\",\n \"revision\": \"d873734390c716d6e18ff3f71ac6eb8b\"\n },\n {\n \"url\": \"assets/KaTeX_Main-BoldItalic-EqUi0SPe.woff\",\n \"revision\": \"5f875f986a9bce1264e8c42417b56f74\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Italic-DVgO3ulm.woff2\",\n \"revision\": \"652970624cde999882102fa2b6a8871f\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Italic-N1npxqDf.ttf\",\n \"revision\": \"39349e0a2b366f38e2672b45aded2030\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Italic-TCzgZvdR.woff\",\n \"revision\": \"8ffd28f6390231548ead99d7835887fa\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Regular-6_eCWgYQ.woff\",\n \"revision\": \"f1cdb692ee31c10b37262caffced5271\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Regular-dtjb4qKe.woff2\",\n \"revision\": \"f8a7f19f45060f7a177314855b8c7aa3\"\n },\n {\n \"url\": \"assets/KaTeX_Main-Regular-MqWbzbVV.ttf\",\n \"revision\": \"818582dae57e6fac46202cfd844afabb\"\n },\n {\n \"url\": \"assets/KaTeX_Math-BoldItalic-d10o37uD.ttf\",\n \"revision\": \"6589c4f1f587f73f0ad0af8ae35ccb53\"\n },\n {\n \"url\": \"assets/KaTeX_Math-BoldItalic-ImPtsMme.woff\",\n \"revision\": \"48155e43d9a284b54753e50e4ba586dc\"\n },\n {\n \"url\": \"assets/KaTeX_Math-BoldItalic-mZ7zbAmZ.woff2\",\n \"revision\": \"1320454d951ec809a7dbccb4f23fccf0\"\n },\n {\n \"url\": \"assets/KaTeX_Math-Italic-H5Tq_9FA.ttf\",\n \"revision\": \"fe5ed5875d95b18c98546cb4f47304ff\"\n },\n {\n \"url\": \"assets/KaTeX_Math-Italic-LedwBEzP.woff2\",\n \"revision\": \"d8b7a801bd87b324efcbae7394119c24\"\n },\n {\n \"url\": \"assets/KaTeX_Math-Italic-wNP_z16f.woff\",\n \"revision\": \"ed7aea12d765f9e2d0f9bc7fa2be626c\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Bold-2yISjogg.woff\",\n \"revision\": \"0e897d27f063facef504667290e408bd\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Bold-9bFEtBg9.woff2\",\n \"revision\": \"ad546b4719bcf690a3604944b90b7e42\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Bold-hTHqZ76u.ttf\",\n \"revision\": \"f2ac73121357210d91e5c3eaa42f72ea\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Italic-Azdo-3Wm.woff\",\n \"revision\": \"ef725de572b71381dccf53918e300744\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Italic-GGIydc0p.ttf\",\n \"revision\": \"f60b4a34842bb524b562df092917a542\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Italic-tx9FahgZ.woff2\",\n \"revision\": \"e934cbc86e2d59ceaf04102c43dc0b50\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Regular-kun6lKiW.woff\",\n \"revision\": \"5f8637ee731482c44a37789723f5e499\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Regular-TaO4USHJ.ttf\",\n \"revision\": \"3243452ee6817acd761c9757aef93c29\"\n },\n {\n \"url\": \"assets/KaTeX_SansSerif-Regular-wwQp5Se8.woff2\",\n \"revision\": \"1ac3ed6ebe34e473519ca1da86f7a384\"\n },\n {\n \"url\": \"assets/KaTeX_Script-Regular--ckFYqpa.woff\",\n \"revision\": \"a82fa2a7e18b8c7a1a9f6069844ebfb9\"\n },\n {\n \"url\": \"assets/KaTeX_Script-Regular-98CFnxev.woff2\",\n \"revision\": \"1b3161eb8cc67462d6e8c2fb96c68507\"\n },\n {\n \"url\": \"assets/KaTeX_Script-Regular-uSZBlqPg.ttf\",\n \"revision\": \"a189c37d73ffce63464635dc12cbbc96\"\n },\n {\n \"url\": \"assets/KaTeX_Size1-Regular-27J7nvyK.ttf\",\n \"revision\": \"0d8d9204004bdf126342605f7bbdffe6\"\n },\n {\n \"url\": \"assets/KaTeX_Size1-Regular-Jgg_JgPA.woff2\",\n \"revision\": \"82ef26dc680ba60d884e051c73d9a42d\"\n },\n {\n \"url\": \"assets/KaTeX_Size1-Regular-tfebZ-uE.woff\",\n \"revision\": \"4788ba5b6247e336f734b742fe9900d5\"\n },\n {\n \"url\": \"assets/KaTeX_Size2-Regular-8uHcfdJu.woff2\",\n \"revision\": \"95a1da914c20455a07b7c9e2dcf2836d\"\n },\n {\n \"url\": \"assets/KaTeX_Size2-Regular-e4ClFoQr.ttf\",\n \"revision\": \"1fdda0e59ed35495ebac28badf210574\"\n },\n {\n \"url\": \"assets/KaTeX_Size2-Regular-KA9bXP1N.woff\",\n \"revision\": \"b0628bfd27c979a09f702a2277979888\"\n },\n {\n \"url\": \"assets/KaTeX_Size3-Regular-4KV7NJM_.ttf\",\n \"revision\": \"963af864cbb10611ba33267ba7953777\"\n },\n {\n \"url\": \"assets/KaTeX_Size3-Regular-k6uTKqBB.woff\",\n \"revision\": \"4de844d4552e941f6b9c38837a8d487b\"\n },\n {\n \"url\": \"assets/KaTeX_Size4-Regular-1hQb9ONy.ttf\",\n \"revision\": \"27a23ee69999affa55491c7dab8e53bf\"\n },\n {\n \"url\": \"assets/KaTeX_Size4-Regular-5eZcWcVX.woff2\",\n \"revision\": \"61522cd3d9043622e235ab57762754f2\"\n },\n {\n \"url\": \"assets/KaTeX_Size4-Regular-RfuIJGSk.woff\",\n \"revision\": \"3045a61f722bc4b198450ce69b3e3824\"\n },\n {\n \"url\": \"assets/KaTeX_Typewriter-Regular-9yG-_x36.ttf\",\n \"revision\": \"6bf4287568e1d3004b54d5d60f9f08f9\"\n },\n {\n \"url\": \"assets/KaTeX_Typewriter-Regular-juq-IZ9c.woff2\",\n \"revision\": \"b8b8393d2e65fcebda5fa99fa3264f41\"\n },\n {\n \"url\": \"assets/KaTeX_Typewriter-Regular-tMUvZjwd.woff\",\n \"revision\": \"0e0460587676d22eae09accd6dcfebc6\"\n },\n {\n \"url\": \"assets/lp.html-BGRyuCz8.js\",\n \"revision\": \"3a265b5cfa09260aa8942704e5127075\"\n },\n {\n \"url\": \"assets/lp.html-jETCO9wn.js\",\n \"revision\": \"9f096bd6a2d1b33dc54a5413a9fb397d\"\n },\n {\n \"url\": \"assets/lp.html-m-tLdpGS.js\",\n \"revision\": \"c4b7d8cf0bc8780d7ea7cebb05f84ec9\"\n },\n {\n \"url\": \"assets/lp.html-yx0HpcA2.js\",\n \"revision\": \"11b98a709d0610f21b1eb6f49a897792\"\n },\n {\n \"url\": \"assets/lua.html--q1iToUD.js\",\n \"revision\": \"4a3d46aaa2ec6e704a321a4461f9a98e\"\n },\n {\n \"url\": \"assets/lua.html-B6d7gWD8.js\",\n \"revision\": \"11bebdbdff9a6b1d61237f5cd9ca0ab8\"\n },\n {\n \"url\": \"assets/lua.html-bIzYAnJl.js\",\n \"revision\": \"6d0a776a5549503cb307cc3c6d1f9188\"\n },\n {\n \"url\": \"assets/lua.html-JK5rP34K.js\",\n \"revision\": \"4289d860b06cff328a1e4c2cac74f64e\"\n },\n {\n \"url\": \"assets/main_window-T08x4hNs.js\",\n \"revision\": \"5eb82c24899073c51b946042d26e8f90\"\n },\n {\n \"url\": \"assets/mip.html-6_WAczY6.js\",\n \"revision\": \"6b1d5c8e8ad85b21f6713ecfbe09f9c1\"\n },\n {\n \"url\": \"assets/mip.html-7cWhLBPI.js\",\n \"revision\": \"7cceedf63c0542f4b64270fa97604fda\"\n },\n {\n \"url\": \"assets/mip.html-EzteSB1w.js\",\n \"revision\": \"0677e0b87706c01acd076d2605c1b2eb\"\n },\n {\n \"url\": \"assets/mip.html-KGIauE4D.js\",\n \"revision\": \"1ea780376d6851b7632a2bee8008b95b\"\n },\n {\n \"url\": \"assets/module_settings-yrsWXh8u.js\",\n \"revision\": \"f8ceb5c301327d408638074b03e227bb\"\n },\n {\n \"url\": \"assets/network.html-IGA5rLvk.js\",\n \"revision\": \"96a9289c777bece65c2a725cc35dc7b5\"\n },\n {\n \"url\": \"assets/network.html-l_dMxKkp.js\",\n \"revision\": \"c1e111cecad392a885421af6236cb95e\"\n },\n {\n \"url\": \"assets/network.html-qaPJNigq.js\",\n \"revision\": \"cdb0781eb59abd20e7304093d48b8799\"\n },\n {\n \"url\": \"assets/network.html-rimWgBRX.js\",\n \"revision\": \"2ebc77fee693065bfe8970cc050c4f01\"\n },\n {\n \"url\": \"assets/oop.html-GH4Nnww4.js\",\n \"revision\": \"2ac4b390dfd30f89b825c1942eba252e\"\n },\n {\n \"url\": \"assets/oop.html-lICjQDMc.js\",\n \"revision\": \"d37c2cceb0f29bfb7cc84222185a93de\"\n },\n {\n \"url\": \"assets/oop.html-QdhyUyOK.js\",\n \"revision\": \"bc8e585d8ebf4e7dced2c9c226f2c870\"\n },\n {\n \"url\": \"assets/oop.html-VmjZry6A.js\",\n \"revision\": \"7175ef9b55c969395108326fc55e0fe1\"\n },\n {\n \"url\": \"assets/play-RaBYbg3m.js\",\n \"revision\": \"adf39fd68328cfe982d5295ce5926018\"\n },\n {\n \"url\": \"assets/plots.html-6AeiZZxH.js\",\n \"revision\": \"233f4285e55d8cbad4adbce51f31bc4f\"\n },\n {\n \"url\": \"assets/plots.html-FPAlzRUf.js\",\n \"revision\": \"f1952e5173c968b19885b485beb18d70\"\n },\n {\n \"url\": \"assets/plots.html-KiXIG1Oc.js\",\n \"revision\": \"230e8da33c475d0a33d7f37a0304d156\"\n },\n {\n \"url\": \"assets/plots.html-wJZ2mJax.js\",\n \"revision\": \"66e71a6e00747f679028b2d4dd8231f0\"\n },\n {\n \"url\": \"assets/polygon_sizes-bVJYQmiT.js\",\n \"revision\": \"bab1b960c9f3f02a8de0a0f0be67d603\"\n },\n {\n \"url\": \"assets/query_results-qHjDevxa.js\",\n \"revision\": \"882cbeda53166bdcd49dd1aba437c9c9\"\n },\n {\n \"url\": \"assets/Result-All2-cnkq843b.js\",\n \"revision\": \"4770b4e03c8d8a2593252d676dcf4fc3\"\n },\n {\n \"url\": \"assets/RMGObjects-PwARz0cG.js\",\n \"revision\": \"29b8111d5b33251f3a53e0df40a82998\"\n },\n {\n \"url\": \"assets/scene_coordinate-_YCPy6or.js\",\n \"revision\": \"c5601b3edca12d692074face1914877e\"\n },\n {\n \"url\": \"assets/script_editor-a48-sxc_.js\",\n \"revision\": \"63e0109cf04f75ce0a230708470063e2\"\n },\n {\n \"url\": \"assets/SearchBox-dgLZwYTI.js\",\n \"revision\": \"bbc654049bd99f0a4226f611c33ab1e9\"\n },\n {\n \"url\": \"assets/shot_parameter_id-roH75mzn.js\",\n \"revision\": \"568201b973f1a8c3e9176d721590e7c8\"\n },\n {\n \"url\": \"assets/shot_script_editor-VtQOeIXC.js\",\n \"revision\": \"7df2e03661e1ff595bb4ed632c42a094\"\n },\n {\n \"url\": \"assets/style-gRAOaLx9.css\",\n \"revision\": \"256c72c20e5fe4f6831f8a2a0af2c87d\"\n },\n {\n \"url\": \"assets/Subplot_Vertical-oXTmfxKU.js\",\n \"revision\": \"40d7da2ed5af97a8ec9335424dad1252\"\n },\n {\n \"url\": \"assets/timelapse.html-ghI-6cF8.js\",\n \"revision\": \"69dde21a74c47f8d3962fd16bcd77883\"\n },\n {\n \"url\": \"assets/timelapse.html-rfk9Tyut.js\",\n \"revision\": \"9bc479044e63fa5b4dd3f3abd852ceec\"\n },\n {\n \"url\": \"assets/timelapse.html-VDhH9cuD.js\",\n \"revision\": \"45da34b3a3d5df8efb9581c9a1386fb4\"\n },\n {\n \"url\": \"assets/timelapse.html-xp-pHQoZ.js\",\n \"revision\": \"bb50b2f975cefbb3811e30993f36a242\"\n },\n {\n \"url\": \"assets/tools.html-hzuhyAmn.js\",\n \"revision\": \"3b94baaf0c3990808c612f9ace58a967\"\n },\n {\n \"url\": \"assets/tools.html-LamHaYH8.js\",\n \"revision\": \"ebefc8b279438154be31832aa39052d8\"\n },\n {\n \"url\": \"assets/tools.html-PgdIJCR5.js\",\n \"revision\": \"09192719254574a47103da0bdab770aa\"\n },\n {\n \"url\": \"assets/tools.html-Tsv49Nwb.js\",\n \"revision\": \"c151431556daaea27e3371e752b9fec4\"\n },\n {\n \"url\": \"assets/two_way-xpspXH9g.js\",\n \"revision\": \"2cd3803c65e256bf09e1ddf4ff7e8062\"\n },\n {\n \"url\": \"assets/versions.html-1Kk-C1xB.js\",\n \"revision\": \"48b23a7082db416031bd2ecc29de550c\"\n },\n {\n \"url\": \"assets/versions.html-8A5Y-n6r.js\",\n \"revision\": \"2728dd80179be17e64c05d33b46937af\"\n },\n {\n \"url\": \"assets/versions.html-aHfbE8Cr.js\",\n \"revision\": \"4fc78361855a25f3e08c91f36c285ccc\"\n },\n {\n \"url\": \"assets/versions.html-diw0opQu.js\",\n \"revision\": \"df6607b064a88a3e812cc329c3838706\"\n },\n {\n \"url\": \"assets/visualization.html-2T-VgKWL.js\",\n \"revision\": \"a06d9bbc51d60588c369fa3b7666cab2\"\n },\n {\n \"url\": \"assets/visualization.html-skftd09s.js\",\n \"revision\": \"fa8701c02b839351cb3d2f762653a36d\"\n },\n {\n \"url\": \"assets/visualization.html-t9WbOvdj.js\",\n \"revision\": \"e067631efd36fa841a8080bbc9556a89\"\n },\n {\n \"url\": \"assets/visualization.html-URi_NNx7.js\",\n \"revision\": \"cae9f1a3a913e926704a718192eca887\"\n },\n {\n \"url\": \"assets/warehouse-simulation.html-5OK9wBKc.js\",\n \"revision\": \"933199aa20804da1948635e9a4eba07d\"\n },\n {\n \"url\": \"assets/warehouse-simulation.html-6ARLBksA.js\",\n \"revision\": \"be324e325ac9186d73b9ab885f837b61\"\n },\n {\n \"url\": \"assets/warehouse-simulation.html-I2Ep6WY5.js\",\n \"revision\": \"31cb326d0010bf05c5729a2172d4ed77\"\n },\n {\n \"url\": \"assets/warehouse-simulation.html-rJTy601K.js\",\n \"revision\": \"84e45e8f44bb85f4bcb9ce8378728727\"\n },\n {\n \"url\": \"assets/web-ui.html--l1JvFq2.js\",\n \"revision\": \"2240a75b2c3333aa892ef2b422b5976e\"\n },\n {\n \"url\": \"assets/web-ui.html-gL6LgUwH.js\",\n \"revision\": \"0b2b3ff3450a761cf7b8880152b8061f\"\n },\n {\n \"url\": \"assets/web-ui.html-MXj0sqtU.js\",\n \"revision\": \"55ecd9a02b74462a2a7c2a82d17a8fb9\"\n },\n {\n \"url\": \"assets/web-ui.html-Ub-X1RXi.js\",\n \"revision\": \"3585b3c869862feb36d7f957d76c38f1\"\n },\n {\n \"url\": \"404.html\",\n \"revision\": \"bc3de9040381a314a9a44eae34544783\"\n },\n {\n \"url\": \"docs/1.1_what_microcity_can_do.html\",\n \"revision\": \"44556d9f9852de335b7b7cb0876e7c36\"\n },\n {\n \"url\": \"docs/2.1_showing_a_world_map.html\",\n \"revision\": \"233c140d5cff4010bb8e88fac0d0733e\"\n },\n {\n \"url\": \"docs/2.2_searching_for_countries.html\",\n \"revision\": \"60bc52285c46955e0f95bebcebfb6844\"\n },\n {\n \"url\": \"docs/3.1_ui_overview.html\",\n \"revision\": \"756ad309de6d69d22bf5715eab983c85\"\n },\n {\n \"url\": \"docs/3.2_vector_shapes.html\",\n \"revision\": \"2afce4fd376b815a4ef99f14d99ce2a0\"\n },\n {\n \"url\": \"docs/3.3_raster_grids.html\",\n \"revision\": \"6d2adc7f6387260f68192a7b7c612ef0\"\n },\n {\n \"url\": \"docs/3.4_3d_scenes.html\",\n \"revision\": \"fe2d2bf023feb6d9c1048422530f873b\"\n },\n {\n \"url\": \"docs/3.5_tables.html\",\n \"revision\": \"40ed756e77437c2ebef6e78e09ac974b\"\n },\n {\n \"url\": \"docs/3.6_maps_and_layers.html\",\n \"revision\": \"3c7f369fdb7eb159cad7cdeb0ecddbce\"\n },\n {\n \"url\": \"docs/3.7_modules.html\",\n \"revision\": \"dd96308008e9c3fd5a98daa9dd4f51cd\"\n },\n {\n \"url\": \"docs/4.1_si_overview.html\",\n \"revision\": \"ea0b8f0c8777f38dba5c4264044d4bd4\"\n },\n {\n \"url\": \"docs/4.2_ui_control.html\",\n \"revision\": \"bea2bd3780084b88a9ede29c807cc01e\"\n },\n {\n \"url\": \"docs/4.3_shapes_and_tables.html\",\n \"revision\": \"1fed17ea11de6ede4c2b446f05982f36\"\n },\n {\n \"url\": \"docs/4.4_grids.html\",\n \"revision\": \"e1ee9671e75b863631c262e009ad47de\"\n },\n {\n \"url\": \"docs/4.5_3d_scenes.html\",\n \"revision\": \"2b60e1fdae8b9569a1b0f033a1cad669\"\n },\n {\n \"url\": \"docs/4.6_networks.html\",\n \"revision\": \"8588e4cfccf1d69020cea269ec1efab7\"\n },\n {\n \"url\": \"docs/4.7_des_simulations.html\",\n \"revision\": \"415d0d2c0d8828b4b0df0cdad3964aaa\"\n },\n {\n \"url\": \"docs/4.8_mixed_integer_programming.html\",\n \"revision\": \"5b546f232703e832d8b5aad69ddb516b\"\n },\n {\n \"url\": \"docs/index.html\",\n \"revision\": \"91166137fce78cb38f54da848e0c416d\"\n },\n {\n \"url\": \"en/docs/1.1_what_microcity_can_do.html\",\n \"revision\": \"b3cd1df50db2394cfbaee31dfc509fbe\"\n },\n {\n \"url\": \"en/docs/2.1_showing_a_world_map.html\",\n \"revision\": \"a7ab35f3a5960d0af94e3a31ed4a2393\"\n },\n {\n \"url\": \"en/docs/2.2_searching_for_countries.html\",\n \"revision\": \"9e9ee0386571e56ee3f9379f31717aac\"\n },\n {\n \"url\": \"en/docs/3.1_ui_overview.html\",\n \"revision\": \"64ed2a82c00df3ea41809ed9f2ea56f5\"\n },\n {\n \"url\": \"en/docs/3.2_vector_shapes.html\",\n \"revision\": \"50c42cfdc6a92727ce7527222876b20f\"\n },\n {\n \"url\": \"en/docs/3.3_raster_grids.html\",\n \"revision\": \"1149c66dcbecc59239c53d3a65d3dd96\"\n },\n {\n \"url\": \"en/docs/3.4_3d_scenes.html\",\n \"revision\": \"3b8d085ffb2d5ac58bd197e3c6b7f9f9\"\n },\n {\n \"url\": \"en/docs/3.5_tables.html\",\n \"revision\": \"a90b65fa025416da0451bc29e4ab827e\"\n },\n {\n \"url\": \"en/docs/3.6_maps_and_layers.html\",\n \"revision\": \"f446db113280cfd6e42bea756098ab48\"\n },\n {\n \"url\": \"en/docs/3.7_modules.html\",\n \"revision\": \"6fe7288119687eb1e9ec345ce2e852b5\"\n },\n {\n \"url\": \"en/docs/4.1_si_overview.html\",\n \"revision\": \"44f09b4121a9ca0799b2a2257817b892\"\n },\n {\n \"url\": \"en/docs/4.2_ui_control.html\",\n \"revision\": \"9737dd5bd69848fc88057ce740e2dcec\"\n },\n {\n \"url\": \"en/docs/4.3_shapes_and_tables.html\",\n \"revision\": \"1dddc05fd48050e42dd3475fbe51e280\"\n },\n {\n \"url\": \"en/docs/4.4_grids.html\",\n \"revision\": \"4ae5212624adb5b80e46276cfa33d90e\"\n },\n {\n \"url\": \"en/docs/4.5_3d_scenes.html\",\n \"revision\": \"9ccda0cac6187ad3ecd6c2729db2a50c\"\n },\n {\n \"url\": \"en/docs/4.6_networks.html\",\n \"revision\": \"39bed6416d0d66c50f5a09fadc88f3ae\"\n },\n {\n \"url\": \"en/docs/4.7_des_simulations_zh.html\",\n \"revision\": \"758bc971a8871118bc394cf3da465113\"\n },\n {\n \"url\": \"en/docs/4.7_des_simulations.html\",\n \"revision\": \"96c1ada309d08c1254fbdfe91ee654d9\"\n },\n {\n \"url\": \"en/docs/4.8_mixed_integer_programming.html\",\n \"revision\": \"abb015b0c3bb1a6782dc93a67b1941e9\"\n },\n {\n \"url\": \"en/docs/index.html\",\n \"revision\": \"e74a99b668c4ae9fce3aa5ff4b117354\"\n },\n {\n \"url\": \"en/index.html\",\n \"revision\": \"61ed29284b295405e20d788d9ddac730\"\n },\n {\n \"url\": \"en/notes/3d-objects.html\",\n \"revision\": \"cb5a4bcebaf919861b3c5a3180e99f91\"\n },\n {\n \"url\": \"en/notes/3d-scene.html\",\n \"revision\": \"43ce60a3b645f32038e20b3706df65a6\"\n },\n {\n \"url\": \"en/notes/cy-simulation.html\",\n \"revision\": \"4e4bd9d2d4efc2b0e7c9a5476e90c857\"\n },\n {\n \"url\": \"en/notes/debug.html\",\n \"revision\": \"8ce60b075cd93f03e35eb4beb44ec6ee\"\n },\n {\n \"url\": \"en/notes/event-scheduling.html\",\n \"revision\": \"ebb7cc4969eebc0c926d744501210ea1\"\n },\n {\n \"url\": \"en/notes/index.html\",\n \"revision\": \"0b14352630d58a5df66a14c5a1d54948\"\n },\n {\n \"url\": \"en/notes/lp.html\",\n \"revision\": \"09058a46d76c5f0cde65b194afab49f7\"\n },\n {\n \"url\": \"en/notes/lua.html\",\n \"revision\": \"db5a8ba7ba59896881330823434ef8b7\"\n },\n {\n \"url\": \"en/notes/mip.html\",\n \"revision\": \"cd1c8093227fbd2c1a9268766044ad3d\"\n },\n {\n \"url\": \"en/notes/network.html\",\n \"revision\": \"39cc7dbe977ad44542566994b64de6b8\"\n },\n {\n \"url\": \"en/notes/oop.html\",\n \"revision\": \"44a2dc4440e21af77e447e10897e58d5\"\n },\n {\n \"url\": \"en/notes/plots.html\",\n \"revision\": \"69c5a2e3cbf0771d9bc068e78ff8fe56\"\n },\n {\n \"url\": \"en/notes/timelapse.html\",\n \"revision\": \"1e33e84d38cbeb013c7acefe0e0c91ba\"\n },\n {\n \"url\": \"en/notes/tools.html\",\n \"revision\": \"e4596640f782fb5c911ea9981986c7db\"\n },\n {\n \"url\": \"en/notes/versions.html\",\n \"revision\": \"9cdeb6b4d08dc114a05d18a9b0008aaf\"\n },\n {\n \"url\": \"en/notes/visualization.html\",\n \"revision\": \"8d1809823d6d05325a73af40b2f328b9\"\n },\n {\n \"url\": \"en/notes/warehouse-simulation.html\",\n \"revision\": \"521b4859506a7233fbcea55b5d64d1c4\"\n },\n {\n \"url\": \"en/notes/web-ui.html\",\n \"revision\": \"0948814f24d6c84a1bcf7fb1f13cc46d\"\n },\n {\n \"url\": \"google3a9084eedb90aa13.html\",\n \"revision\": \"5fdd561cbfed9c1a090e11665147df61\"\n },\n {\n \"url\": \"images/doc/index.html\",\n \"revision\": \"29e5060ab03404e2752e031480aaa752\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"61b9ca15447543c1b447d62d0f9b4c2f\"\n },\n {\n \"url\": \"notes/3d-objects.html\",\n \"revision\": \"1edf507a473cc6184bf8e40ff4811363\"\n },\n {\n \"url\": \"notes/3d-scene.html\",\n \"revision\": \"20d8717ade078ff9ac6facb7cce94c7d\"\n },\n {\n \"url\": \"notes/cy-simulation.html\",\n \"revision\": \"8cfb98500d408919eca2525f536038c1\"\n },\n {\n \"url\": \"notes/debug.html\",\n \"revision\": \"21dc4e82d4eeb7285d82031d65897107\"\n },\n {\n \"url\": \"notes/event-scheduling.html\",\n \"revision\": \"fe086942d711d55c33d50c8015eed623\"\n },\n {\n \"url\": \"notes/index.html\",\n \"revision\": \"402c0f56b90338cbb2f3331854b69896\"\n },\n {\n \"url\": \"notes/lp.html\",\n \"revision\": \"08968dfb67d4ee391875a4c7c273e5ea\"\n },\n {\n \"url\": \"notes/lua.html\",\n \"revision\": \"1df52b65739430baee7bd5b372caaad2\"\n },\n {\n \"url\": \"notes/mip.html\",\n \"revision\": \"ab967a79e9af05da0b23cec975a96505\"\n },\n {\n \"url\": \"notes/network.html\",\n \"revision\": \"fbe9482b4782f4b0071aaa8b4fac2ee2\"\n },\n {\n \"url\": \"notes/oop.html\",\n \"revision\": \"48152d7d0ffe59e9301be505c6cef0f2\"\n },\n {\n \"url\": \"notes/plots.html\",\n \"revision\": \"7423360f812e787a69062c504607a693\"\n },\n {\n \"url\": \"notes/timelapse.html\",\n \"revision\": \"6513074d9855269c9d6c0456fbdef2f1\"\n },\n {\n \"url\": \"notes/tools.html\",\n \"revision\": \"18ec4478be7b9dc9697c5108ee47b411\"\n },\n {\n \"url\": \"notes/versions.html\",\n \"revision\": \"2504a75f5a9cfd887571861b8d99fa5b\"\n },\n {\n \"url\": \"notes/visualization.html\",\n \"revision\": \"04163485af14e0f7c7ba1bd303426488\"\n },\n {\n \"url\": \"notes/warehouse-simulation.html\",\n \"revision\": \"a8e6203b3acecd846c317c04a5a27d85\"\n },\n {\n \"url\": \"notes/web-ui.html\",\n \"revision\": \"81fe5a832ea3abefd5843da2665c57bf\"\n },\n {\n \"url\": \"assets/3trend-e8Vz-nOo.webp\",\n \"revision\": \"62e6f891c43c490d73e9c40baced8bda\"\n },\n {\n \"url\": \"assets/6-1trend-iFlvvd90.webp\",\n \"revision\": \"77b688d0752c48c1d9ceaa7543f08116\"\n },\n {\n \"url\": \"assets/6trend-tHF37BNC.webp\",\n \"revision\": \"29a2a9741a7f5953bb3c394f3f70a644\"\n },\n {\n \"url\": \"assets/AceEditor-8UZqygeG.png\",\n \"revision\": \"d79c0c73bbf389f15e08dc2aa04f6c9d\"\n },\n {\n \"url\": \"assets/AGV2-cOVBigXf.png\",\n \"revision\": \"ac9d28e8b7f46a60dcdb8c430ac65a04\"\n },\n {\n \"url\": \"assets/AGVQueueModel-VbkDUcno.png\",\n \"revision\": \"5494bf4bbcee87a6d49427e6f32ff4b5\"\n },\n {\n \"url\": \"assets/auto_test-ttcTMf95.webp\",\n \"revision\": \"a32c2b274444d267076dfa6f94e6d63c\"\n },\n {\n \"url\": \"assets/AutoTranslate-oqY-EbbE.png\",\n \"revision\": \"7cd770336647da7598fe161fa99df301\"\n },\n {\n \"url\": \"assets/Banner-O--M2FyY.png\",\n \"revision\": \"4126c10b826d601e7ae4ef5e11c5a747\"\n },\n {\n \"url\": \"assets/BottomBar-Il3Sa37D.gif\",\n \"revision\": \"63e38d376fe4a371b8d97947b73fbd8c\"\n },\n {\n \"url\": \"assets/box_lwh-6iD8r0MK.jpg\",\n \"revision\": \"9c29ae29f4e3a90f4bbb1bc323488e6e\"\n },\n {\n \"url\": \"assets/city_logistics-8RxmuTB1.png\",\n \"revision\": \"f0e83dfc21b4da0afee21ec1645a5ce4\"\n },\n {\n \"url\": \"assets/close_save_grid-mxdTfyrH.png\",\n \"revision\": \"06823158f287c332e303ce9e74f119b1\"\n },\n {\n \"url\": \"assets/close_save_shapes-bnfKINWq.png\",\n \"revision\": \"6285144c1d85e6c8d7c12459ea8ecfa2\"\n },\n {\n \"url\": \"assets/color5-PRdlG8aV.gif\",\n \"revision\": \"7d57428b2e042e57250ff788e5214737\"\n },\n {\n \"url\": \"assets/color8-KLKGFsL4.gif\",\n \"revision\": \"7190cdbbc801e3598b39822c2f4449f1\"\n },\n {\n \"url\": \"assets/CommandBar-Pu56Q_KU.png\",\n \"revision\": \"48edae64a9b9429350f896d96e0d7af2\"\n },\n {\n \"url\": \"assets/coordinate-KcPjAH3b.png\",\n \"revision\": \"4696bfa608a3929ab8ffee4ed9da17f0\"\n },\n {\n \"url\": \"assets/CY1-KhoqZKrQ.png\",\n \"revision\": \"8fbbafb3f2d20b7b3542517162747e4b\"\n },\n {\n \"url\": \"assets/CY2-uRljosmO.png\",\n \"revision\": \"54659101f5e756f8d5ae99f230a325da\"\n },\n {\n \"url\": \"assets/CYLayout-XevrzO6A.jpg\",\n \"revision\": \"a83265003c673e906301a65be920056d\"\n },\n {\n \"url\": \"assets/data_visualization-HBg0SLXW.png\",\n \"revision\": \"bcf2333bc33ffde8b5f201e79ae4fb2b\"\n },\n {\n \"url\": \"assets/DL_Heatmap-uiGWW-lH.png\",\n \"revision\": \"5f26dd003befff9e1f6eb994197cf3ce\"\n },\n {\n \"url\": \"assets/edit_point-krh9tqYD.png\",\n \"revision\": \"b56499ca449e9cb42efa0ef5fe21aefd\"\n },\n {\n \"url\": \"assets/edit_shape-3r72h2cB.png\",\n \"revision\": \"5ee823e7cf71f04215c697036c15acb0\"\n },\n {\n \"url\": \"assets/EventSchedulingRefresh-P9P75NgW.jpg\",\n \"revision\": \"47874df6c7bd878c2a64d800de62e747\"\n },\n {\n \"url\": \"assets/fixed_increment_advance-ufFIwQjw.png\",\n \"revision\": \"20f2f4c8bbc3113184537da242398b9c\"\n },\n {\n \"url\": \"assets/gis_data_structure-OyzSP1K_.png\",\n \"revision\": \"77fa044dae581369badf8cb87d8e006c\"\n },\n {\n \"url\": \"assets/GraduatedColorProperties-QL7AyCTd.png\",\n \"revision\": \"acaa6f8e656886bcec42e74379e9eee5\"\n },\n {\n \"url\": \"assets/GraduatedColorResult-c1P6KfFi.png\",\n \"revision\": \"9869925032dbd7d448f4b1b60ab3c8a9\"\n },\n {\n \"url\": \"assets/GraduatedColorSettings-sd7MRVbC.png\",\n \"revision\": \"74ff570e2d95f95663e1565bb86a75e8\"\n },\n {\n \"url\": \"assets/grid_attributes-e5wa0ZGb.png\",\n \"revision\": \"99da94947795b278ee0bb4410dcf5e0e\"\n },\n {\n \"url\": \"assets/grid_menu-7jPQkAi1.png\",\n \"revision\": \"636dff6ad1216aa74de6214aba408e9f\"\n },\n {\n \"url\": \"assets/grid_selection-bdt61Cd7.png\",\n \"revision\": \"a854dc544ec5239818be6a245b4d558a\"\n },\n {\n \"url\": \"assets/grid_structure-vhTlEgf-.png\",\n \"revision\": \"4be1f0e0a70ddd24dfe875312edef079\"\n },\n {\n \"url\": \"assets/Histogram-hCqM-8K4.png\",\n \"revision\": \"b088afe8f4f8e21e5221a00aff8e6efd\"\n },\n {\n \"url\": \"assets/LabelAttribProperties-BNSD9rBn.png\",\n \"revision\": \"f95bfff89484f9f07ec316c996da5cf3\"\n },\n {\n \"url\": \"assets/layer_menu-lHo367yT.png\",\n \"revision\": \"55d3c08736142acc4245d482c2c0ce6a\"\n },\n {\n \"url\": \"assets/LookupTableColor-VSXylHlz.png\",\n \"revision\": \"af9601eb62ef3be4d01eb33f51a63661\"\n },\n {\n \"url\": \"assets/LookupTableProperties-P0W9jYQE.png\",\n \"revision\": \"16ab4c133ef51f5e9db60a401211c0da\"\n },\n {\n \"url\": \"assets/main_window-kvL2HSJd.png\",\n \"revision\": \"312ba4b6c91267ecef63c6ee00bc21e9\"\n },\n {\n \"url\": \"assets/map_coordinates-8ybUOErD.png\",\n \"revision\": \"c39aa1c8a4c3ed6e5b507f8cf3874160\"\n },\n {\n \"url\": \"assets/map_menu-zU_XTli2.png\",\n \"revision\": \"a95051447bc04efd2d5e706c872d3493\"\n },\n {\n \"url\": \"assets/module_libraries_settings-lee40Qvj.png\",\n \"revision\": \"bf0570b0b6130844d28fa3c402a27ffb\"\n },\n {\n \"url\": \"assets/module_settings-3JBvpV80.png\",\n \"revision\": \"ba28f8624752e27c514377e213ea642a\"\n },\n {\n \"url\": \"assets/modules-cY5Kwc-8.png\",\n \"revision\": \"55cea6ae301455d142cec78857a08aa9\"\n },\n {\n \"url\": \"assets/new_grid-4i1mP770.png\",\n \"revision\": \"cf382a920be3a7338877a71b78d66365\"\n },\n {\n \"url\": \"assets/new_scene-8_vgmKnR.png\",\n \"revision\": \"d5e69908016913fe08d8e00c90f6fb13\"\n },\n {\n \"url\": \"assets/new_shapes-RVv9IgwR.png\",\n \"revision\": \"36c06984f09ac60f8161c8d6aa860cf7\"\n },\n {\n \"url\": \"assets/new_table-Elg2D_3m.png\",\n \"revision\": \"89408a0284dd95c1421c0d5b4e6131f7\"\n },\n {\n \"url\": \"assets/new-GF873AfJ.gif\",\n \"revision\": \"aadcfac586760bc33926ca5ce7f02a9c\"\n },\n {\n \"url\": \"assets/object_menu-rLYhy67y.png\",\n \"revision\": \"eec516547d2a3ac027546ae348f4f054\"\n },\n {\n \"url\": \"assets/old-FpQSFo63.gif\",\n \"revision\": \"4080855b1419e2c04463cebd35711270\"\n },\n {\n \"url\": \"assets/optimal_layout-bCy9JRge.webp\",\n \"revision\": \"584a4e39d1b598fc7c4fb08653ba0477\"\n },\n {\n \"url\": \"assets/PlotPrice1-QAaVF6hQ.png\",\n \"revision\": \"2343fd9de1abdbbaf15f5413236f76fb\"\n },\n {\n \"url\": \"assets/PlotPrice2-DeodiEK_.png\",\n \"revision\": \"1a853fda82ea81fff7b44d65ba15346a\"\n },\n {\n \"url\": \"assets/polygon_sizes-naWR0jXW.jpg\",\n \"revision\": \"dc376be92b128dadabd35eace5ccee21\"\n },\n {\n \"url\": \"assets/polylines_order-v8d3qUyG.jpg\",\n \"revision\": \"31638de01c4de5ae632f20f1b6403fee\"\n },\n {\n \"url\": \"assets/Preset_Earth-Tllgpkll.png\",\n \"revision\": \"f55773fa09d457dd715992b6835564b7\"\n },\n {\n \"url\": \"assets/Preset_Truck-ZFTcQbsO.png\",\n \"revision\": \"a77828aa329b3c20d7cd8cb8696db5dd\"\n },\n {\n \"url\": \"assets/Presets-dDpjg8aZ.png\",\n \"revision\": \"26dee069587516d47812b816f671eac8\"\n },\n {\n \"url\": \"assets/problem1-AJuFUHVQ.webp\",\n \"revision\": \"c245c369ed623e8e388767d4f830afa3\"\n },\n {\n \"url\": \"assets/problem2-KunKgJbC.webp\",\n \"revision\": \"325bed85492b9881ea786baa7245e353\"\n },\n {\n \"url\": \"assets/Q1Banner-BxB6kPmr.png\",\n \"revision\": \"bc503822f53bcbca271785e032b28a45\"\n },\n {\n \"url\": \"assets/Q1ContainerProcessFlow-t0XYjgJ-.png\",\n \"revision\": \"13ba28ee1e19abc2be46756fe982d86a\"\n },\n {\n \"url\": \"assets/Q2-hS2yYPEB.jpg\",\n \"revision\": \"7d824da5c6d3a040b3f24a27ba42171a\"\n },\n {\n \"url\": \"assets/Q2Layout-jXHR-iYn.png\",\n \"revision\": \"419a6e710279298f56fa3405cb685e26\"\n },\n {\n \"url\": \"assets/query_results-8DtTlPIZ.png\",\n \"revision\": \"527d9a24621e0953478d8cd1224d973a\"\n },\n {\n \"url\": \"assets/RangeDotRelateToMap-s6apr58V.png\",\n \"revision\": \"503a9b2bb8e9a9106462e15478480baa\"\n },\n {\n \"url\": \"assets/RelateToMapBig-co0riIjm.png\",\n \"revision\": \"f0dd5026b6fa4bee47c155db6d44d822\"\n },\n {\n \"url\": \"assets/RelateToMapSmall-8yIwZc0w.png\",\n \"revision\": \"10945aba05b9286a9182b5957f15ef01\"\n },\n {\n \"url\": \"assets/RelateToScreenBig-H3UhFI8t.png\",\n \"revision\": \"2095d6f27c66191ed2f3a5c55e4e286f\"\n },\n {\n \"url\": \"assets/RelateToScreenSmall-RgyFR_Ap.png\",\n \"revision\": \"9bb544030d3ed11649649524ea8d4bb4\"\n },\n {\n \"url\": \"assets/RMG-AGV-ProcessFlow-aQWltqys.png\",\n \"revision\": \"4d7c0cb8ca470de4c7e17eb49394de69\"\n },\n {\n \"url\": \"assets/RMG1-zXf9sSV8.png\",\n \"revision\": \"f2362f6e69a941146929feef9262df73\"\n },\n {\n \"url\": \"assets/RMG2-ea6huW81.png\",\n \"revision\": \"18bc24c71d84d836806a35f090182811\"\n },\n {\n \"url\": \"assets/RMGObjects-yrTAIJHV.png\",\n \"revision\": \"22386c7fb35c3987fd9fe92090a08fe8\"\n },\n {\n \"url\": \"assets/RMGQC2-BO9lyakQ.png\",\n \"revision\": \"b179f5f2a4bc3d9043503617887201e8\"\n },\n {\n \"url\": \"assets/RunCode-xHWq8U-i.gif\",\n \"revision\": \"5f634a99c4fc97eea5525a02b8f51677\"\n },\n {\n \"url\": \"assets/scene_coordinate-muj-oFBk.png\",\n \"revision\": \"4a5134bd71717c44e496080a75478b39\"\n },\n {\n \"url\": \"assets/scene_menu-RSZKJk7N.png\",\n \"revision\": \"92664f67e27932c0d91c26ade6252378\"\n },\n {\n \"url\": \"assets/script_editor-51w4xjN9.png\",\n \"revision\": \"5cee3858ed9d28fd46d30d87477de338\"\n },\n {\n \"url\": \"assets/segments-wNxhsxV0.jpg\",\n \"revision\": \"adfe33d8ae64831aebeedec7a91a1f99\"\n },\n {\n \"url\": \"assets/SelectLinksColor--zZDTT73.png\",\n \"revision\": \"90ba31fd0a8532b3f841b39f898c8b7e\"\n },\n {\n \"url\": \"assets/SetParameterProperties-m8LPKWT1.png\",\n \"revision\": \"fdbc3e7d199a408b5526279c6d1c6474\"\n },\n {\n \"url\": \"assets/shapes_files-ShfoHRZo.png\",\n \"revision\": \"9a734a267477ee4d92b1cf39554bd4e2\"\n },\n {\n \"url\": \"assets/shapes_menu-aime3jTY.png\",\n \"revision\": \"1ce52bb22c77de1d9b138fac30adbf95\"\n },\n {\n \"url\": \"assets/SHIP2-pz8IHA_0.png\",\n \"revision\": \"f598e405a60027016fb59b8b3b3d195c\"\n },\n {\n \"url\": \"assets/shipping_planning-_Mkxb6xn.png\",\n \"revision\": \"73ff5ae946bc1b3408af6852a40f14b2\"\n },\n {\n \"url\": \"assets/shot_parameter_id-ljNzzofT.png\",\n \"revision\": \"c89a255188060a166f8890523d9596af\"\n },\n {\n \"url\": \"assets/shot_script_editor-_OW8Kkrd.png\",\n \"revision\": \"d7f18072054f41155cde343988a8a176\"\n },\n {\n \"url\": \"assets/sim-result-nEPKqIkR.webp\",\n \"revision\": \"4d4fb876261b1b2f812c26a2459287ce\"\n },\n {\n \"url\": \"assets/SizeProperties-xZe9_-WE.png\",\n \"revision\": \"0c1b64600f1cac883992d07661a4832d\"\n },\n {\n \"url\": \"assets/Subplot_Vertical-X1t_RUlM.png\",\n \"revision\": \"d0afcb66a5aeec2fd0b1fdbdc6426337\"\n },\n {\n \"url\": \"assets/table_menu-enNFenIu.png\",\n \"revision\": \"568acc7e16f0e89d9aab0846e6b37969\"\n },\n {\n \"url\": \"assets/table_view_menu-1OnsnofR.png\",\n \"revision\": \"a5b97ce1a8ed91d31c4fe571e0d5da4e\"\n },\n {\n \"url\": \"assets/TableSelect-jKGsdf_N.png\",\n \"revision\": \"a2f14a33f90021823a66786f4be84fae\"\n },\n {\n \"url\": \"assets/terminal_simulation-rx4w_Kp0.gif\",\n \"revision\": \"b2c8c2047ae16200788732a65d9d342a\"\n },\n {\n \"url\": \"assets/test_layout-3LvNhD-0.webp\",\n \"revision\": \"04e32d297a5182f881182b3b039c3680\"\n },\n {\n \"url\": \"assets/warehouse_simulation-CPwzj5dU.gif\",\n \"revision\": \"f62546662765fda4f41338846a1af6a6\"\n },\n {\n \"url\": \"assets/WebUIOverview-NmRQvsO9.png\",\n \"revision\": \"769241be4e6ed733ce783a4a7bd63443\"\n },\n {\n \"url\": \"assets/WebUIParts-yq4WXR5p.png\",\n \"revision\": \"411be83677e6ad958f5f7fb506ec1026\"\n },\n {\n \"url\": \"assets/world_countries-K0FhRM3K.png\",\n \"revision\": \"e850582792c99b09af68ca948e2aff8e\"\n },\n {\n \"url\": \"assets/无预判障碍-p5itt-RJ.gif\",\n \"revision\": \"6b6189014d83c82c480cd0dad1d3aec0\"\n },\n {\n \"url\": \"assets/预判障碍-hw2PZ_-s.gif\",\n \"revision\": \"8236b76fb86d617e815a12382aa2c140\"\n },\n {\n \"url\": \"images/icon_microcity.png\",\n \"revision\": \"08f31df45215c6018336c0acf1ff5e4d\"\n },\n {\n \"url\": \"images/icon_microcitynotes.png\",\n \"revision\": \"8fab94c045ebfa93980673848abc96b2\"\n },\n {\n \"url\": \"images/icon/icon-144.png\",\n \"revision\": \"06593bf0bb1b7646ed53c336be5ee07b\"\n },\n {\n \"url\": \"images/icon/icon-192.png\",\n \"revision\": \"dd4c61d0beacce8e965296d679fff0ca\"\n },\n {\n \"url\": \"images/icon/icon-512.png\",\n \"revision\": \"65e0e189f0e4f4fe72e6a6c47480c655\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\n\n\n\n\n\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches"],"mappings":"0nBAqBAA,KAAKC,iBAAiB,WAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,aACP,IAGFC,EAAAA,eAQAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,oDACPC,SAAY,oCAEd,CACED,IAAO,oDACPC,SAAY,oCAEd,CACED,IAAO,oDACPC,SAAY,oCAEd,CACED,IAAO,oDACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,sDACPC,SAAY,oCAEd,CACED,IAAO,sDACPC,SAAY,oCAEd,CACED,IAAO,sDACPC,SAAY,oCAEd,CACED,IAAO,sDACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,iDACPC,SAAY,oCAEd,CACED,IAAO,iDACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,kDACPC,SAAY,oCAEd,CACED,IAAO,iDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,iDACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,WACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,wBACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,kBACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,wBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,wBACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,wBACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,8CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,+CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,gDACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,gCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,yBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,6BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,qCACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,mCACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,oCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,sCACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,oCAEd,CACED,IAAO,2BACPC,SAAY,qCAEb,CAAE,GACLC,EAAAA"} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index a356b12e..078cf58c 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,3 +1,3 @@ -https://huuhghhgyg.github.io/MicroCityNotes/2023-11-20T16:01:42.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/1.1_what_microcity_can_do.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/2.1_showing_a_world_map.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/2.2_searching_for_countries.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.1_ui_overview.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.2_vector_shapes.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.3_raster_grids.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.4_3d_scenes.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.5_tables.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.6_maps_and_layers.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.7_modules.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.1_si_overview.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.2_ui_control.html2022-12-11T04:14:01.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.3_shapes_and_tables.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.4_grids.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.5_3d_scenes.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.6_networks.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.7_des_simulations.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.8_mixed_integer_programming.html2022-12-05T16:00:29.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/2022-12-19T14:44:21.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects-en.html2023-11-14T09:36:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects.html2023-11-14T13:50:52.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene-en.html2023-05-21T06:17:26.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene.html2023-11-14T13:50:52.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/2023-11-20T15:27:43.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/cy-simulation.html2023-06-03T03:38:14.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/debug.html2023-11-20T15:27:43.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling-en.html2023-06-03T03:38:14.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling.html2023-11-14T13:50:52.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/lp.html2023-11-19T10:07:10.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/lua.html2023-11-14T13:29:55.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/mip-en.html2023-11-14T13:50:52.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/mip.html2023-11-14T13:50:52.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/network.html2022-12-20T02:50:58.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/oop.html2023-05-21T08:26:32.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/plots.html2023-05-21T06:17:26.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/timelapse.html2023-06-01T08:12:10.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/tools.html2023-11-20T14:40:11.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/versions.html2023-11-20T15:40:00.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/visualization.html2022-12-24T07:33:47.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/warehouse-simulation.html2023-05-21T08:42:49.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui-en.html2023-05-21T06:17:26.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui.html2023-11-14T13:50:52.000Zdaily \ No newline at end of file +https://huuhghhgyg.github.io/MicroCityNotes/2023-11-27T04:49:40.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/2023-11-27T04:45:10.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/1.1_what_microcity_can_do.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/2.1_showing_a_world_map.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/2.2_searching_for_countries.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.1_ui_overview.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.2_vector_shapes.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.3_raster_grids.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.4_3d_scenes.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.5_tables.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.6_maps_and_layers.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/3.7_modules.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.1_si_overview.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.2_ui_control.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.3_shapes_and_tables.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.4_grids.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.5_3d_scenes.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.6_networks.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.7_des_simulations.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/4.8_mixed_integer_programming.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/docs/2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/3d-objects.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/3d-scene.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/2023-11-27T04:49:40.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/cy-simulation.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/debug.html2023-11-20T15:27:43.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/event-scheduling.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/lp.html2023-11-19T10:07:10.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/lua.html2023-11-14T13:29:55.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/mip.html2023-11-14T13:50:52.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/network.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/oop.html2023-11-26T16:30:53.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/plots.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/timelapse.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/tools.html2023-11-20T14:40:11.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/versions.html2023-11-20T15:40:00.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/visualization.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/warehouse-simulation.html2023-11-26T16:30:53.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/notes/web-ui.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/1.1_what_microcity_can_do.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/2.1_showing_a_world_map.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/2.2_searching_for_countries.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.1_ui_overview.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.2_vector_shapes.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.3_raster_grids.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.4_3d_scenes.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.5_tables.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.6_maps_and_layers.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/3.7_modules.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.1_si_overview.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.2_ui_control.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.3_shapes_and_tables.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.4_grids.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.5_3d_scenes.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.6_networks.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.7_des_simulations.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.7_des_simulations_zh.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/4.8_mixed_integer_programming.html2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/docs/2023-11-25T03:41:16.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/3d-objects.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/3d-scene.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/2023-11-27T04:54:45.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/cy-simulation.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/debug.html2023-11-27T04:54:45.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/event-scheduling.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/lp.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/lua.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/mip.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/network.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/oop.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/plots.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/timelapse.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/tools.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/versions.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/visualization.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/warehouse-simulation.html2023-11-27T04:37:02.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/en/notes/web-ui.html2023-11-26T15:09:59.000Zdailyhttps://huuhghhgyg.github.io/MicroCityNotes/images/doc/2023-11-25T03:41:16.000Zdaily \ No newline at end of file